diff options
| author | LukePulverenti <luke.pulverenti@gmail.com> | 2013-02-24 16:53:54 -0500 |
|---|---|---|
| committer | LukePulverenti <luke.pulverenti@gmail.com> | 2013-02-24 16:53:54 -0500 |
| commit | 8ce3e74e8112a94773df22827849bf274fc88198 (patch) | |
| tree | a4ce1edf34466be697e2e432609f6be80b6c6df6 /MediaBrowser.Common | |
| parent | 6c86721f6de2acbe68e9419064ff21111ff3a223 (diff) | |
More DI
Diffstat (limited to 'MediaBrowser.Common')
33 files changed, 439 insertions, 2249 deletions
diff --git a/MediaBrowser.Common/Kernel/BaseApplicationPaths.cs b/MediaBrowser.Common/Kernel/BaseApplicationPaths.cs deleted file mode 100644 index 936c484c8a..0000000000 --- a/MediaBrowser.Common/Kernel/BaseApplicationPaths.cs +++ /dev/null @@ -1,304 +0,0 @@ -using System; -using System.Configuration; -using System.IO; -using System.Reflection; - -namespace MediaBrowser.Common.Kernel -{ - /// <summary> - /// Provides a base class to hold common application paths used by both the Ui and Server. - /// This can be subclassed to add application-specific paths. - /// </summary> - public abstract class BaseApplicationPaths - { - /// <summary> - /// The _program data path - /// </summary> - private string _programDataPath; - /// <summary> - /// Gets the path to the program data folder - /// </summary> - /// <value>The program data path.</value> - public string ProgramDataPath - { - get - { - return _programDataPath ?? (_programDataPath = GetProgramDataPath()); - } - } - - /// <summary> - /// The _data directory - /// </summary> - private string _dataDirectory; - /// <summary> - /// Gets the folder path to the data directory - /// </summary> - /// <value>The data directory.</value> - public string DataPath - { - get - { - if (_dataDirectory == null) - { - _dataDirectory = Path.Combine(ProgramDataPath, "data"); - - if (!Directory.Exists(_dataDirectory)) - { - Directory.CreateDirectory(_dataDirectory); - } - } - - return _dataDirectory; - } - } - - /// <summary> - /// The _image cache path - /// </summary> - private string _imageCachePath; - /// <summary> - /// Gets the image cache path. - /// </summary> - /// <value>The image cache path.</value> - public string ImageCachePath - { - get - { - if (_imageCachePath == null) - { - _imageCachePath = Path.Combine(CachePath, "images"); - - if (!Directory.Exists(_imageCachePath)) - { - Directory.CreateDirectory(_imageCachePath); - } - } - - return _imageCachePath; - } - } - - /// <summary> - /// The _plugins path - /// </summary> - private string _pluginsPath; - /// <summary> - /// Gets the path to the plugin directory - /// </summary> - /// <value>The plugins path.</value> - public string PluginsPath - { - get - { - if (_pluginsPath == null) - { - _pluginsPath = Path.Combine(ProgramDataPath, "plugins"); - if (!Directory.Exists(_pluginsPath)) - { - Directory.CreateDirectory(_pluginsPath); - } - } - - return _pluginsPath; - } - } - - /// <summary> - /// The _plugin configurations path - /// </summary> - private string _pluginConfigurationsPath; - /// <summary> - /// Gets the path to the plugin configurations directory - /// </summary> - /// <value>The plugin configurations path.</value> - public string PluginConfigurationsPath - { - get - { - if (_pluginConfigurationsPath == null) - { - _pluginConfigurationsPath = Path.Combine(PluginsPath, "configurations"); - if (!Directory.Exists(_pluginConfigurationsPath)) - { - Directory.CreateDirectory(_pluginConfigurationsPath); - } - } - - return _pluginConfigurationsPath; - } - } - - private string _tempUpdatePath; - /// <summary> - /// Gets the path to where temporary update files will be stored - /// </summary> - /// <value>The plugin configurations path.</value> - public string TempUpdatePath - { - get - { - if (_tempUpdatePath == null) - { - _tempUpdatePath = Path.Combine(ProgramDataPath, "Updates"); - if (!Directory.Exists(_tempUpdatePath)) - { - Directory.CreateDirectory(_tempUpdatePath); - } - } - - return _tempUpdatePath; - } - } - - /// <summary> - /// The _log directory path - /// </summary> - private string _logDirectoryPath; - /// <summary> - /// Gets the path to the log directory - /// </summary> - /// <value>The log directory path.</value> - public string LogDirectoryPath - { - get - { - if (_logDirectoryPath == null) - { - _logDirectoryPath = Path.Combine(ProgramDataPath, "logs"); - if (!Directory.Exists(_logDirectoryPath)) - { - Directory.CreateDirectory(_logDirectoryPath); - } - } - return _logDirectoryPath; - } - } - - /// <summary> - /// The _configuration directory path - /// </summary> - private string _configurationDirectoryPath; - /// <summary> - /// Gets the path to the application configuration root directory - /// </summary> - /// <value>The configuration directory path.</value> - public string ConfigurationDirectoryPath - { - get - { - if (_configurationDirectoryPath == null) - { - _configurationDirectoryPath = Path.Combine(ProgramDataPath, "config"); - if (!Directory.Exists(_configurationDirectoryPath)) - { - Directory.CreateDirectory(_configurationDirectoryPath); - } - } - return _configurationDirectoryPath; - } - } - - /// <summary> - /// The _system configuration file path - /// </summary> - private string _systemConfigurationFilePath; - /// <summary> - /// Gets the path to the system configuration file - /// </summary> - /// <value>The system configuration file path.</value> - public string SystemConfigurationFilePath - { - get - { - return _systemConfigurationFilePath ?? (_systemConfigurationFilePath = Path.Combine(ConfigurationDirectoryPath, "system.xml")); - } - } - - /// <summary> - /// The _cache directory - /// </summary> - private string _cachePath; - /// <summary> - /// Gets the folder path to the cache directory - /// </summary> - /// <value>The cache directory.</value> - public string CachePath - { - get - { - if (_cachePath == null) - { - _cachePath = Path.Combine(ProgramDataPath, "cache"); - - if (!Directory.Exists(_cachePath)) - { - Directory.CreateDirectory(_cachePath); - } - } - - return _cachePath; - } - } - - /// <summary> - /// The _temp directory - /// </summary> - private string _tempDirectory; - /// <summary> - /// Gets the folder path to the temp directory within the cache folder - /// </summary> - /// <value>The temp directory.</value> - public string TempDirectory - { - get - { - if (_tempDirectory == null) - { - _tempDirectory = Path.Combine(CachePath, "temp"); - - if (!Directory.Exists(_tempDirectory)) - { - Directory.CreateDirectory(_tempDirectory); - } - } - - return _tempDirectory; - } - } - - /// <summary> - /// Gets the path to the application's ProgramDataFolder - /// </summary> - /// <returns>System.String.</returns> - public static string GetProgramDataPath() - { -#if DEBUG - string programDataPath = ConfigurationManager.AppSettings["DebugProgramDataPath"]; - -#else - string programDataPath = Path.Combine(ConfigurationManager.AppSettings["ReleaseProgramDataPath"], ConfigurationManager.AppSettings["ProgramDataFolderName"]); -#endif - - programDataPath = programDataPath.Replace("%CommonApplicationData%", Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); - - // If it's a relative path, e.g. "..\" - if (!Path.IsPathRooted(programDataPath)) - { - var path = Assembly.GetExecutingAssembly().Location; - path = Path.GetDirectoryName(path); - - programDataPath = Path.Combine(path, programDataPath); - - programDataPath = Path.GetFullPath(programDataPath); - } - - if (!Directory.Exists(programDataPath)) - { - Directory.CreateDirectory(programDataPath); - } - - return programDataPath; - } - } -} diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index 28ccd8602d..a5a9b46ecb 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -2,16 +2,14 @@ using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Common.Serialization; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; using MediaBrowser.Model.System; 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; @@ -24,7 +22,7 @@ namespace MediaBrowser.Common.Kernel /// <typeparam name="TApplicationPathsType">The type of the T application paths type.</typeparam> public abstract class BaseKernel<TConfigurationType, TApplicationPathsType> : IDisposable, IKernel where TConfigurationType : BaseApplicationConfiguration, new() - where TApplicationPathsType : BaseApplicationPaths, new() + where TApplicationPathsType : IApplicationPaths { /// <summary> /// Occurs when [has pending restart changed]. @@ -129,7 +127,7 @@ namespace MediaBrowser.Common.Kernel get { // Lazy load - LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => XmlSerializer.GetXmlConfiguration<TConfigurationType>(ApplicationPaths.SystemConfigurationFilePath, Logger)); + LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => GetXmlConfiguration<TConfigurationType>(ApplicationPaths.SystemConfigurationFilePath)); return _configuration; } protected set @@ -162,19 +160,6 @@ namespace MediaBrowser.Common.Kernel public TApplicationPathsType ApplicationPaths { get; private set; } /// <summary> - /// The _failed assembly loads - /// </summary> - private readonly List<string> _failedPluginAssemblies = new List<string>(); - /// <summary> - /// Gets the plugin assemblies that failed to load. - /// </summary> - /// <value>The failed assembly loads.</value> - public IEnumerable<string> FailedPluginAssemblies - { - get { return _failedPluginAssemblies; } - } - - /// <summary> /// Gets the list of currently loaded plugins /// </summary> /// <value>The plugins.</value> @@ -205,46 +190,6 @@ namespace MediaBrowser.Common.Kernel public IEnumerable<IRestfulService> RestServices { get; private set; } /// <summary> - /// The disposable parts - /// </summary> - private readonly List<IDisposable> _disposableParts = new List<IDisposable>(); - - /// <summary> - /// The _protobuf serializer initialized - /// </summary> - private bool _protobufSerializerInitialized; - /// <summary> - /// The _protobuf serializer sync lock - /// </summary> - private object _protobufSerializerSyncLock = new object(); - /// <summary> - /// Gets a dynamically compiled generated serializer that can serialize protocontracts without reflection - /// </summary> - private DynamicProtobufSerializer _protobufSerializer; - /// <summary> - /// Gets the protobuf serializer. - /// </summary> - /// <value>The protobuf serializer.</value> - public DynamicProtobufSerializer ProtobufSerializer - { - get - { - // Lazy load - LazyInitializer.EnsureInitialized(ref _protobufSerializer, ref _protobufSerializerInitialized, ref _protobufSerializerSyncLock, () => DynamicProtobufSerializer.Create(AllTypes)); - return _protobufSerializer; - } - private set - { - _protobufSerializer = value; - - if (value == null) - { - _protobufSerializerInitialized = false; - } - } - } - - /// <summary> /// Gets the UDP server port number. /// This can't be configurable because then the user would have to configure their client to discover the server. /// </summary> @@ -301,42 +246,40 @@ namespace MediaBrowser.Common.Kernel protected IApplicationHost ApplicationHost { get; private set; } /// <summary> - /// Gets or sets the task manager. - /// </summary> - /// <value>The task manager.</value> - protected ITaskManager TaskManager { get; set; } - - /// <summary> - /// Gets the assemblies. + /// The _XML serializer /// </summary> - /// <value>The assemblies.</value> - protected Assembly[] Assemblies { get; private set; } - - /// <summary> - /// Gets all types. - /// </summary> - /// <value>All types.</value> - public Type[] AllTypes { get; private set; } + private readonly IXmlSerializer _xmlSerializer; /// <summary> /// Initializes a new instance of the <see cref="BaseKernel{TApplicationPathsType}" /> class. /// </summary> /// <param name="appHost">The app host.</param> + /// <param name="appPaths">The app paths.</param> + /// <param name="xmlSerializer">The XML serializer.</param> /// <param name="logger">The logger.</param> /// <exception cref="System.ArgumentNullException">isoManager</exception> - protected BaseKernel(IApplicationHost appHost, ILogger logger) + protected BaseKernel(IApplicationHost appHost, TApplicationPathsType appPaths, IXmlSerializer xmlSerializer, ILogger logger) { if (appHost == null) { throw new ArgumentNullException("appHost"); } - + if (appPaths == null) + { + throw new ArgumentNullException("appPaths"); + } + if (xmlSerializer == null) + { + throw new ArgumentNullException("xmlSerializer"); + } if (logger == null) { throw new ArgumentNullException("logger"); } + ApplicationPaths = appPaths; ApplicationHost = appHost; + _xmlSerializer = xmlSerializer; Logger = logger; } @@ -344,14 +287,12 @@ namespace MediaBrowser.Common.Kernel /// Initializes the Kernel /// </summary> /// <returns>Task.</returns> - public async Task Init() + public Task Init() { - ApplicationPaths = new TApplicationPathsType(); - IsFirstRun = !File.Exists(ApplicationPaths.SystemConfigurationFilePath); // Performs initializations that can be reloaded at anytime - await Reload().ConfigureAwait(false); + return Reload(); } /// <summary> @@ -377,7 +318,6 @@ namespace MediaBrowser.Common.Kernel { // Set these to null so that they can be lazy loaded again Configuration = null; - ProtobufSerializer = null; ReloadLogger(); @@ -388,14 +328,12 @@ namespace MediaBrowser.Common.Kernel await OnConfigurationLoaded().ConfigureAwait(false); - DisposeTaskManager(); - TaskManager = new TaskManager(Logger); + FindParts(); - Logger.Info("Loading Plugins"); - await ReloadComposableParts().ConfigureAwait(false); + await OnComposablePartsLoaded().ConfigureAwait(false); DisposeTcpManager(); - TcpManager = new TcpManager(ApplicationHost, this, ApplicationHost.Resolve<INetworkManager>(), Logger); + TcpManager = (TcpManager)ApplicationHost.CreateInstance(typeof(TcpManager)); } /// <summary> @@ -418,183 +356,13 @@ namespace MediaBrowser.Common.Kernel } /// <summary> - /// Uses MEF to locate plugins - /// Subclasses can use this to locate types within plugins - /// </summary> - /// <returns>Task.</returns> - private async Task ReloadComposableParts() - { - _failedPluginAssemblies.Clear(); - - DisposeComposableParts(); - - Assemblies = GetComposablePartAssemblies().ToArray(); - - AllTypes = Assemblies.SelectMany(GetTypes).ToArray(); - - ComposeParts(AllTypes); - - await OnComposablePartsLoaded().ConfigureAwait(false); - } - - /// <summary> - /// Composes the parts. - /// </summary> - /// <param name="allTypes">All types.</param> - private void ComposeParts(IEnumerable<Type> allTypes) - { - var concreteTypes = allTypes.Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType).ToArray(); - - RegisterExportedValues(); - - FindParts(concreteTypes); - } - - /// <summary> /// Composes the parts with ioc container. /// </summary> - /// <param name="allTypes">All types.</param> - protected virtual void FindParts(Type[] allTypes) - { - RestServices = GetExports<IRestfulService>(allTypes); - WebSocketListeners = GetExports<IWebSocketListener>(allTypes); - Plugins = GetExports<IPlugin>(allTypes); - - var tasks = GetExports<IScheduledTask>(allTypes, false); - - TaskManager.AddTasks(tasks); - } - - /// <summary> - /// Gets the exports. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="allTypes">All types.</param> - /// <param name="manageLiftime">if set to <c>true</c> [manage liftime].</param> - /// <returns>IEnumerable{``0}.</returns> - protected IEnumerable<T> GetExports<T>(Type[] allTypes, bool manageLiftime = true) - { - var currentType = typeof(T); - - Logger.Info("Composing instances of " + currentType.Name); - - var parts = allTypes.Where(currentType.IsAssignableFrom).Select(Instantiate).Cast<T>().ToArray(); - - if (manageLiftime) - { - _disposableParts.AddRange(parts.OfType<IDisposable>()); - } - - return parts; - } - - /// <summary> - /// Instantiates the specified type. - /// </summary> - /// <param name="type">The type.</param> - /// <returns>System.Object.</returns> - private object Instantiate(Type type) - { - return ApplicationHost.CreateInstance(type); - } - - /// <summary> - /// Composes the exported values. - /// </summary> - /// <param name="container">The container.</param> - protected virtual void RegisterExportedValues() + protected virtual void FindParts() { - ApplicationHost.RegisterSingleInstance<IKernel>(this); - ApplicationHost.RegisterSingleInstance(TaskManager); - } - - /// <summary> - /// Gets the composable part assemblies. - /// </summary> - /// <returns>IEnumerable{Assembly}.</returns> - protected virtual IEnumerable<Assembly> 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 - var pluginAssemblies = Directory.EnumerateFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly) - .Select(file => - { - try - { - return Assembly.Load(File.ReadAllBytes((file))); - } - catch (Exception ex) - { - _failedPluginAssemblies.Add(file); - Logger.ErrorException("Error loading {0}", ex, file); - return null; - } - - }).Where(a => a != null); - - foreach (var pluginAssembly in pluginAssemblies) - { - 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 - pluginAssemblies = Directory.EnumerateFiles(corePluginDirectory, "*.dll", SearchOption.TopDirectoryOnly) - .Select(file => - { - try - { - return Assembly.Load(File.ReadAllBytes((file))); - } - catch (Exception ex) - { - _failedPluginAssemblies.Add(file); - Logger.ErrorException("Error loading {0}", ex, file); - return null; - } - - }).Where(a => a != null); - - foreach (var pluginAssembly in pluginAssemblies) - { - yield return pluginAssembly; - } - - // Include composable parts in the Model assembly - yield return typeof(SystemInfo).Assembly; - - // Include composable parts in the Common assembly - yield return Assembly.GetExecutingAssembly(); - - // Include composable parts in the subclass assembly - yield return GetType().Assembly; - } - - /// <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> - private static 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); - } + RestServices = ApplicationHost.GetExports<IRestfulService>(); + WebSocketListeners = ApplicationHost.GetExports<IWebSocketListener>(); + Plugins = ApplicationHost.GetExports<IPlugin>(); } /// <summary> @@ -612,7 +380,7 @@ namespace MediaBrowser.Common.Kernel try { - plugin.Initialize(this, Logger); + plugin.Initialize(this, _xmlSerializer, Logger); Logger.Info("{0} {1} initialized.", plugin.Name, plugin.Version); } @@ -654,12 +422,7 @@ namespace MediaBrowser.Common.Kernel if (dispose) { DisposeTcpManager(); - DisposeTaskManager(); DisposeHttpManager(); - - DisposeComposableParts(); - - _disposableParts.Clear(); } } @@ -676,18 +439,6 @@ namespace MediaBrowser.Common.Kernel } /// <summary> - /// Disposes the task manager. - /// </summary> - private void DisposeTaskManager() - { - if (TaskManager != null) - { - TaskManager.Dispose(); - TaskManager = null; - } - } - - /// <summary> /// Disposes the HTTP manager. /// </summary> private void DisposeHttpManager() @@ -700,17 +451,6 @@ namespace MediaBrowser.Common.Kernel } /// <summary> - /// Disposes all objects gathered through MEF composable parts - /// </summary> - protected virtual void DisposeComposableParts() - { - foreach (var part in _disposableParts) - { - part.Dispose(); - } - } - - /// <summary> /// Gets the current application version /// </summary> /// <value>The application version.</value> @@ -761,7 +501,7 @@ namespace MediaBrowser.Common.Kernel IsNetworkDeployed = ApplicationHost.CanSelfUpdate, WebSocketPortNumber = TcpManager.WebSocketPortNumber, SupportsNativeWebSocket = TcpManager.SupportsNativeWebSocket, - FailedPluginAssemblies = FailedPluginAssemblies.ToArray() + FailedPluginAssemblies = ApplicationHost.FailedAssemblies.ToArray() }; } @@ -777,7 +517,7 @@ namespace MediaBrowser.Common.Kernel { lock (_configurationSaveLock) { - XmlSerializer.SerializeToFile(Configuration, ApplicationPaths.SystemConfigurationFilePath); + _xmlSerializer.SerializeToFile(Configuration, ApplicationPaths.SystemConfigurationFilePath); } OnConfigurationUpdated(); @@ -787,7 +527,7 @@ namespace MediaBrowser.Common.Kernel /// Gets the application paths. /// </summary> /// <value>The application paths.</value> - BaseApplicationPaths IKernel.ApplicationPaths + IApplicationPaths IKernel.ApplicationPaths { get { return ApplicationPaths; } } @@ -798,6 +538,63 @@ namespace MediaBrowser.Common.Kernel BaseApplicationConfiguration IKernel.Configuration { get { return Configuration; } + } + + /// <summary> + /// Reads an xml configuration file from the file system + /// It will immediately re-serialize and save if new serialization data is available due to property changes + /// </summary> + /// <param name="type">The type.</param> + /// <param name="path">The path.</param> + /// <returns>System.Object.</returns> + public object GetXmlConfiguration(Type type, string path) + { + Logger.Info("Loading {0} at {1}", type.Name, path); + + object configuration; + + byte[] buffer = null; + + // Use try/catch to avoid the extra file system lookup using File.Exists + try + { + buffer = File.ReadAllBytes(path); + + configuration = _xmlSerializer.DeserializeFromBytes(type, buffer); + } + catch (FileNotFoundException) + { + configuration = ApplicationHost.CreateInstance(type); + } + + // Take the object we just got and serialize it back to bytes + var newBytes = _xmlSerializer.SerializeToBytes(configuration); + + // If the file didn't exist before, or if something has changed, re-save + if (buffer == null || !buffer.SequenceEqual(newBytes)) + { + Logger.Info("Saving {0} to {1}", type.Name, path); + + // Save it after load in case we got new items + File.WriteAllBytes(path, newBytes); + } + + return configuration; + } + + + /// <summary> + /// Reads an xml configuration file from the file system + /// It will immediately save the configuration after loading it, just + /// in case there are new serializable properties + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="path">The path.</param> + /// <returns>``0.</returns> + private T GetXmlConfiguration<T>(string path) + where T : class + { + return GetXmlConfiguration(typeof(T), path) as T; } } } diff --git a/MediaBrowser.Common/Kernel/IApplicationHost.cs b/MediaBrowser.Common/Kernel/IApplicationHost.cs index fe2f00a126..4b564581b4 100644 --- a/MediaBrowser.Common/Kernel/IApplicationHost.cs +++ b/MediaBrowser.Common/Kernel/IApplicationHost.cs @@ -1,5 +1,6 @@ using MediaBrowser.Model.Updates; using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -33,6 +34,26 @@ namespace MediaBrowser.Common.Kernel bool CanSelfUpdate { get; } /// <summary> + /// Gets the failed assemblies. + /// </summary> + /// <value>The failed assemblies.</value> + IEnumerable<string> FailedAssemblies { get; } + + /// <summary> + /// Gets all concrete types. + /// </summary> + /// <value>All concrete types.</value> + Type[] AllConcreteTypes { get; } + + /// <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> + IEnumerable<T> GetExports<T>(bool manageLiftime = true); + + /// <summary> /// Checks for update. /// </summary> /// <returns>Task{CheckForUpdateResult}.</returns> diff --git a/MediaBrowser.Common/Kernel/IApplicationPaths.cs b/MediaBrowser.Common/Kernel/IApplicationPaths.cs new file mode 100644 index 0000000000..abb7836423 --- /dev/null +++ b/MediaBrowser.Common/Kernel/IApplicationPaths.cs @@ -0,0 +1,76 @@ + +namespace MediaBrowser.Common.Kernel +{ + /// <summary> + /// Interface IApplicationPaths + /// </summary> + public interface IApplicationPaths + { + /// <summary> + /// Gets the path to the program data folder + /// </summary> + /// <value>The program data path.</value> + string ProgramDataPath { get; } + + /// <summary> + /// Gets the folder path to the data directory + /// </summary> + /// <value>The data directory.</value> + string DataPath { get; } + + /// <summary> + /// Gets the image cache path. + /// </summary> + /// <value>The image cache path.</value> + string ImageCachePath { get; } + + /// <summary> + /// Gets the path to the plugin directory + /// </summary> + /// <value>The plugins path.</value> + string PluginsPath { get; } + + /// <summary> + /// Gets the path to the plugin configurations directory + /// </summary> + /// <value>The plugin configurations path.</value> + string PluginConfigurationsPath { get; } + + /// <summary> + /// Gets the path to where temporary update files will be stored + /// </summary> + /// <value>The plugin configurations path.</value> + string TempUpdatePath { get; } + + /// <summary> + /// Gets the path to the log directory + /// </summary> + /// <value>The log directory path.</value> + string LogDirectoryPath { get; } + + /// <summary> + /// Gets the path to the application configuration root directory + /// </summary> + /// <value>The configuration directory path.</value> + string ConfigurationDirectoryPath { get; } + + /// <summary> + /// Gets the path to the system configuration file + /// </summary> + /// <value>The system configuration file path.</value> + string SystemConfigurationFilePath { get; } + + /// <summary> + /// Gets the folder path to the cache directory + /// </summary> + /// <value>The cache directory.</value> + string CachePath { get; } + + /// <summary> + /// Gets the folder path to the temp directory within the cache folder + /// </summary> + /// <value>The temp directory.</value> + string TempDirectory { get; } + } + +} diff --git a/MediaBrowser.Common/Kernel/IKernel.cs b/MediaBrowser.Common/Kernel/IKernel.cs index 253368f4ff..fb629a24df 100644 --- a/MediaBrowser.Common/Kernel/IKernel.cs +++ b/MediaBrowser.Common/Kernel/IKernel.cs @@ -1,6 +1,5 @@ using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; -using MediaBrowser.Common.Serialization; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.System; using System; @@ -18,7 +17,7 @@ namespace MediaBrowser.Common.Kernel /// Gets the application paths. /// </summary> /// <value>The application paths.</value> - BaseApplicationPaths ApplicationPaths { get; } + IApplicationPaths ApplicationPaths { get; } /// <summary> /// Gets the configuration. @@ -33,12 +32,6 @@ namespace MediaBrowser.Common.Kernel KernelContext KernelContext { get; } /// <summary> - /// Gets the protobuf serializer. - /// </summary> - /// <value>The protobuf serializer.</value> - DynamicProtobufSerializer ProtobufSerializer { get; } - - /// <summary> /// Inits this instance. /// </summary> /// <returns>Task.</returns> @@ -156,5 +149,13 @@ namespace MediaBrowser.Common.Kernel /// Notifies the pending restart. /// </summary> void NotifyPendingRestart(); + + /// <summary> + /// Gets the XML configuration. + /// </summary> + /// <param name="type">The type.</param> + /// <param name="path">The path.</param> + /// <returns>System.Object.</returns> + object GetXmlConfiguration(Type type, string path); } } diff --git a/MediaBrowser.Common/Kernel/TcpManager.cs b/MediaBrowser.Common/Kernel/TcpManager.cs index 9a998823f4..c04b775994 100644 --- a/MediaBrowser.Common/Kernel/TcpManager.cs +++ b/MediaBrowser.Common/Kernel/TcpManager.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Net; -using MediaBrowser.Common.Serialization; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; using System; @@ -14,6 +13,7 @@ using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Common.Kernel { @@ -36,6 +36,12 @@ namespace MediaBrowser.Common.Kernel private IHttpServer HttpServer { get; set; } /// <summary> + /// Gets or sets the json serializer. + /// </summary> + /// <value>The json serializer.</value> + private IJsonSerializer _jsonSerializer; + + /// <summary> /// This subscribes to HttpListener requests and finds the appropriate BaseHandler to process it /// </summary> /// <value>The HTTP listener.</value> @@ -96,8 +102,10 @@ namespace MediaBrowser.Common.Kernel /// <param name="applicationHost">The application host.</param> /// <param name="kernel">The kernel.</param> /// <param name="networkManager">The network manager.</param> + /// <param name="jsonSerializer">The json serializer.</param> /// <param name="logger">The logger.</param> - public TcpManager(IApplicationHost applicationHost, IKernel kernel, INetworkManager networkManager, ILogger logger) + /// <exception cref="System.ArgumentNullException">applicationHost</exception> + public TcpManager(IApplicationHost applicationHost, IKernel kernel, INetworkManager networkManager, IJsonSerializer jsonSerializer, ILogger logger) { if (applicationHost == null) { @@ -111,12 +119,17 @@ namespace MediaBrowser.Common.Kernel { throw new ArgumentNullException("networkManager"); } + if (jsonSerializer == null) + { + throw new ArgumentNullException("jsonSerializer"); + } if (logger == null) { throw new ArgumentNullException("logger"); } _logger = logger; + _jsonSerializer = jsonSerializer; _kernel = kernel; _applicationHost = applicationHost; _networkManager = networkManager; @@ -203,7 +216,7 @@ namespace MediaBrowser.Common.Kernel /// <param name="e">The <see cref="WebSocketConnectEventArgs" /> instance containing the event data.</param> void HttpServer_WebSocketConnected(object sender, WebSocketConnectEventArgs e) { - var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, ProcessWebSocketMessageReceived, _logger); + var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, ProcessWebSocketMessageReceived, _jsonSerializer, _logger); _webSocketConnections.Add(connection); } @@ -342,7 +355,7 @@ namespace MediaBrowser.Common.Kernel _logger.Info("Sending web socket message {0}", messageType); var message = new WebSocketMessage<T> { MessageType = messageType, Data = dataFunction() }; - var bytes = JsonSerializer.SerializeToBytes(message); + var bytes = _jsonSerializer.SerializeToBytes(message); var tasks = connections.Select(s => Task.Run(() => { diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 28789a816c..f9147141dd 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -38,10 +38,6 @@ </ApplicationIcon> </PropertyGroup> <ItemGroup> - <Reference Include="protobuf-net, Version=2.0.0.621, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\protobuf-net.2.0.0.621\lib\net40\protobuf-net.dll</HintPath> - </Reference> <Reference Include="ServiceStack, Version=3.9.37.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\ServiceStack.3.9.37\lib\net35\ServiceStack.dll</HintPath> @@ -75,14 +71,12 @@ <HintPath>..\packages\ServiceStack.Text.3.9.37\lib\net35\ServiceStack.Text.dll</HintPath> </Reference> <Reference Include="System" /> - <Reference Include="System.Configuration" /> <Reference Include="System.Core" /> <Reference Include="System.Net" /> <Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http.WebRequest" /> <Reference Include="System.Web" /> <Reference Include="Microsoft.CSharp" /> - <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="..\SharedVersion.cs"> @@ -98,8 +92,8 @@ <Compile Include="IO\IIsoMount.cs" /> <Compile Include="IO\ProgressStream.cs" /> <Compile Include="IO\StreamDefaults.cs" /> - <Compile Include="Kernel\BaseApplicationPaths.cs" /> <Compile Include="Kernel\BasePeriodicWebSocketListener.cs" /> + <Compile Include="Kernel\IApplicationPaths.cs" /> <Compile Include="Kernel\IWebSocketListener.cs" /> <Compile Include="Kernel\IApplicationHost.cs" /> <Compile Include="Kernel\IKernel.cs" /> @@ -116,7 +110,6 @@ <Compile Include="Net\IWebSocket.cs" /> <Compile Include="Net\IWebSocketServer.cs" /> <Compile Include="Net\MimeTypes.cs" /> - <Compile Include="Net\NativeWebSocket.cs" /> <Compile Include="Net\UdpMessageReceivedEventArgs.cs" /> <Compile Include="Net\WebSocketConnectEventArgs.cs" /> <Compile Include="Net\WebSocketConnection.cs" /> @@ -130,26 +123,18 @@ <DependentUpon>Resources.resx</DependentUpon> </Compile> <Compile Include="ScheduledTasks\ITaskManager.cs" /> - <Compile Include="ScheduledTasks\TaskManager.cs" /> - <Compile Include="ScheduledTasks\Tasks\ReloadLoggerTask.cs" /> + <Compile Include="ScheduledTasks\ITaskTrigger.cs" /> <Compile Include="ScheduledTasks\ScheduledTaskHelpers.cs" /> <Compile Include="ScheduledTasks\StartupTrigger.cs" /> <Compile Include="ScheduledTasks\SystemEventTrigger.cs" /> - <Compile Include="ScheduledTasks\Tasks\SystemUpdateTask.cs" /> - <Compile Include="Serialization\DynamicProtobufSerializer.cs" /> - <Compile Include="Serialization\JsonSerializer.cs" /> <Compile Include="Kernel\BaseKernel.cs" /> <Compile Include="Kernel\KernelContext.cs" /> <Compile Include="Net\Handlers\BaseHandler.cs" /> <Compile Include="Net\Handlers\BaseSerializationHandler.cs" /> <Compile Include="Plugins\BasePlugin.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="Serialization\XmlSerializer.cs" /> <Compile Include="ScheduledTasks\BaseScheduledTask.cs" /> - <Compile Include="ScheduledTasks\BaseTaskTrigger.cs" /> <Compile Include="ScheduledTasks\DailyTrigger.cs" /> - <Compile Include="ScheduledTasks\Tasks\DeleteCacheFileTask.cs" /> - <Compile Include="ScheduledTasks\Tasks\DeleteLogFileTask.cs" /> <Compile Include="ScheduledTasks\IntervalTrigger.cs" /> <Compile Include="ScheduledTasks\IScheduledTask.cs" /> <Compile Include="ScheduledTasks\WeeklyTrigger.cs" /> diff --git a/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs index 293cb6e98a..a00152d784 100644 --- a/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs +++ b/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs @@ -1,6 +1,5 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Kernel; -using MediaBrowser.Common.Serialization; using System; using System.IO; using System.Threading.Tasks; @@ -104,15 +103,15 @@ namespace MediaBrowser.Common.Net.Handlers { return Task.Run(() => { - switch (SerializationFormat) - { - case SerializationFormat.Protobuf: - Kernel.ProtobufSerializer.SerializeToStream(_objectToSerialize, stream); - break; - default: - JsonSerializer.SerializeToStream(_objectToSerialize, stream); - break; - } + //switch (SerializationFormat) + //{ + // case SerializationFormat.Protobuf: + // Kernel.ProtobufSerializer.SerializeToStream(_objectToSerialize, stream); + // break; + // default: + // JsonSerializer.SerializeToStream(_objectToSerialize, stream); + // break; + //} }); } } diff --git a/MediaBrowser.Common/Net/IWebSocket.cs b/MediaBrowser.Common/Net/IWebSocket.cs index 96299e3b2e..3fd4b1241c 100644 --- a/MediaBrowser.Common/Net/IWebSocket.cs +++ b/MediaBrowser.Common/Net/IWebSocket.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Common.Net /// Gets or sets the receive action. /// </summary> /// <value>The receive action.</value> - Action<WebSocketMessageInfo> OnReceiveDelegate { get; set; } + Action<byte[]> OnReceiveDelegate { get; set; } /// <summary> /// Sends the async. diff --git a/MediaBrowser.Common/Net/NativeWebSocket.cs b/MediaBrowser.Common/Net/NativeWebSocket.cs deleted file mode 100644 index 23f3d4be34..0000000000 --- a/MediaBrowser.Common/Net/NativeWebSocket.cs +++ /dev/null @@ -1,159 +0,0 @@ -using MediaBrowser.Common.Serialization; -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Net.WebSockets; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.Net -{ - /// <summary> - /// Class NativeWebSocket - /// </summary> - public class NativeWebSocket : IWebSocket - { - /// <summary> - /// The logger - /// </summary> - private readonly ILogger _logger; - - /// <summary> - /// Gets or sets the web socket. - /// </summary> - /// <value>The web socket.</value> - private WebSocket WebSocket { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="NativeWebSocket" /> class. - /// </summary> - /// <param name="socket">The socket.</param> - /// <param name="logger">The logger.</param> - /// <exception cref="System.ArgumentNullException">socket</exception> - public NativeWebSocket(WebSocket socket, ILogger logger) - { - if (socket == null) - { - throw new ArgumentNullException("socket"); - } - - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - - _logger = logger; - WebSocket = socket; - - Receive(); - } - - /// <summary> - /// Gets or sets the state. - /// </summary> - /// <value>The state.</value> - public WebSocketState State - { - get { return WebSocket.State; } - } - - /// <summary> - /// Receives this instance. - /// </summary> - private async void Receive() - { - while (true) - { - byte[] bytes; - - try - { - bytes = await ReceiveBytesAsync(CancellationToken.None).ConfigureAwait(false); - } - catch (WebSocketException ex) - { - _logger.ErrorException("Error reveiving web socket message", ex); - - break; - } - - if (OnReceiveDelegate != null) - { - using (var memoryStream = new MemoryStream(bytes)) - { - try - { - var messageResult = JsonSerializer.DeserializeFromStream<WebSocketMessageInfo>(memoryStream); - - OnReceiveDelegate(messageResult); - } - catch (Exception ex) - { - _logger.ErrorException("Error processing web socket message", ex); - } - } - } - } - } - - /// <summary> - /// Receives the async. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task{WebSocketMessageInfo}.</returns> - /// <exception cref="System.Net.WebSockets.WebSocketException">Connection closed</exception> - private async Task<byte[]> ReceiveBytesAsync(CancellationToken cancellationToken) - { - var bytes = new byte[4096]; - var buffer = new ArraySegment<byte>(bytes); - - var result = await WebSocket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false); - - if (result.CloseStatus.HasValue) - { - throw new WebSocketException("Connection closed"); - } - - return buffer.Array; - } - - /// <summary> - /// Sends the async. - /// </summary> - /// <param name="bytes">The bytes.</param> - /// <param name="type">The type.</param> - /// <param name="endOfMessage">if set to <c>true</c> [end of message].</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task SendAsync(byte[] bytes, WebSocketMessageType type, bool endOfMessage, CancellationToken cancellationToken) - { - return WebSocket.SendAsync(new ArraySegment<byte>(bytes), type, true, cancellationToken); - } - - /// <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) - { - if (dispose) - { - WebSocket.Dispose(); - } - } - - /// <summary> - /// Gets or sets the receive action. - /// </summary> - /// <value>The receive action.</value> - public Action<WebSocketMessageInfo> OnReceiveDelegate { get; set; } - } -} diff --git a/MediaBrowser.Common/Net/WebSocketConnection.cs b/MediaBrowser.Common/Net/WebSocketConnection.cs index ab691c823a..6b22ef78ec 100644 --- a/MediaBrowser.Common/Net/WebSocketConnection.cs +++ b/MediaBrowser.Common/Net/WebSocketConnection.cs @@ -1,7 +1,7 @@ -using MediaBrowser.Common.Serialization; +using System.IO; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; using System; -using System.Net; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; @@ -39,13 +39,20 @@ namespace MediaBrowser.Common.Net private readonly ILogger _logger; /// <summary> + /// The _json serializer + /// </summary> + private readonly IJsonSerializer _jsonSerializer; + + /// <summary> /// Initializes a new instance of the <see cref="WebSocketConnection" /> class. /// </summary> /// <param name="socket">The socket.</param> /// <param name="remoteEndPoint">The remote end point.</param> /// <param name="receiveAction">The receive action.</param> + /// <param name="jsonSerializer">The json serializer.</param> + /// <param name="logger">The logger.</param> /// <exception cref="System.ArgumentNullException">socket</exception> - public WebSocketConnection(IWebSocket socket, string remoteEndPoint, Action<WebSocketMessageInfo> receiveAction, ILogger logger) + public WebSocketConnection(IWebSocket socket, string remoteEndPoint, Action<WebSocketMessageInfo> receiveAction, IJsonSerializer jsonSerializer, ILogger logger) { if (socket == null) { @@ -59,11 +66,16 @@ namespace MediaBrowser.Common.Net { throw new ArgumentNullException("receiveAction"); } + if (jsonSerializer == null) + { + throw new ArgumentNullException("jsonSerializer"); + } if (logger == null) { throw new ArgumentNullException("logger"); } + _jsonSerializer = jsonSerializer; _socket = socket; _socket.OnReceiveDelegate = info => OnReceive(info, receiveAction); RemoteEndPoint = remoteEndPoint; @@ -73,12 +85,19 @@ namespace MediaBrowser.Common.Net /// <summary> /// Called when [receive]. /// </summary> - /// <param name="info">The info.</param> + /// <param name="bytes">The bytes.</param> /// <param name="callback">The callback.</param> - private void OnReceive(WebSocketMessageInfo info, Action<WebSocketMessageInfo> callback) + private void OnReceive(byte[] bytes, Action<WebSocketMessageInfo> callback) { try { + WebSocketMessageInfo info; + + using (var memoryStream = new MemoryStream(bytes)) + { + info = _jsonSerializer.DeserializeFromStream<WebSocketMessageInfo>(memoryStream); + } + info.Connection = this; callback(info); @@ -103,8 +122,8 @@ namespace MediaBrowser.Common.Net { throw new ArgumentNullException("message"); } - - var bytes = JsonSerializer.SerializeToBytes(message); + + var bytes = _jsonSerializer.SerializeToBytes(message); return SendAsync(bytes, cancellationToken); } diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index d089aa1b38..dad3867fcb 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Kernel; -using MediaBrowser.Common.Serialization; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Plugins; using System; @@ -7,6 +6,7 @@ using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Common.Plugins { @@ -188,7 +188,7 @@ namespace MediaBrowser.Common.Plugins get { // Lazy load - LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationInitialized, ref _configurationSyncLock, () => XmlSerializer.GetXmlConfiguration(ConfigurationType, ConfigurationFilePath, Logger) as TConfigurationType); + LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationInitialized, ref _configurationSyncLock, () => Kernel.GetXmlConfiguration(ConfigurationType, ConfigurationFilePath) as TConfigurationType); return _configuration; } protected set @@ -270,25 +270,37 @@ namespace MediaBrowser.Common.Plugins public ILogger Logger { get; private set; } /// <summary> + /// Gets the XML serializer. + /// </summary> + /// <value>The XML serializer.</value> + protected IXmlSerializer XmlSerializer { get; private set; } + + /// <summary> /// Starts the plugin. /// </summary> /// <param name="kernel">The kernel.</param> + /// <param name="xmlSerializer">The XML serializer.</param> /// <param name="logger">The logger.</param> /// <exception cref="System.ArgumentNullException">kernel</exception> - public void Initialize(IKernel kernel, ILogger logger) + public void Initialize(IKernel kernel, IXmlSerializer xmlSerializer, ILogger logger) { if (kernel == null) { throw new ArgumentNullException("kernel"); } + if (xmlSerializer == null) + { + throw new ArgumentNullException("xmlSerializer"); + } + if (logger == null) { throw new ArgumentNullException("logger"); } - + + XmlSerializer = xmlSerializer; Logger = logger; - Kernel = kernel; if (kernel.KernelContext == KernelContext.Server) diff --git a/MediaBrowser.Common/Plugins/IPlugin.cs b/MediaBrowser.Common/Plugins/IPlugin.cs index 198678491b..1b25cdcb18 100644 --- a/MediaBrowser.Common/Plugins/IPlugin.cs +++ b/MediaBrowser.Common/Plugins/IPlugin.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common.Kernel; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Plugins; +using MediaBrowser.Model.Serialization; using System; namespace MediaBrowser.Common.Plugins @@ -107,9 +108,10 @@ namespace MediaBrowser.Common.Plugins /// Starts the plugin. /// </summary> /// <param name="kernel">The kernel.</param> + /// <param name="xmlSerializer">The XML serializer.</param> /// <param name="logger">The logger.</param> /// <exception cref="System.ArgumentNullException">kernel</exception> - void Initialize(IKernel kernel, ILogger logger); + void Initialize(IKernel kernel, IXmlSerializer xmlSerializer, ILogger logger); /// <summary> /// Disposes the plugins. Undos all actions performed during Init. diff --git a/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs index 845faf31a7..09ceaa9aee 100644 --- a/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs @@ -1,6 +1,5 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Kernel; -using MediaBrowser.Common.Serialization; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Tasks; using System; @@ -90,7 +89,7 @@ namespace MediaBrowser.Common.ScheduledTasks { try { - return JsonSerializer.DeserializeFromFile<TaskResult>(HistoryFilePath); + return TaskManager.GetLastExecutionResult(this); } catch (IOException) { @@ -110,74 +109,6 @@ namespace MediaBrowser.Common.ScheduledTasks } /// <summary> - /// The _scheduled tasks data directory - /// </summary> - private string _scheduledTasksDataDirectory; - /// <summary> - /// Gets the scheduled tasks data directory. - /// </summary> - /// <value>The scheduled tasks data directory.</value> - private string ScheduledTasksDataDirectory - { - get - { - if (_scheduledTasksDataDirectory == null) - { - _scheduledTasksDataDirectory = Path.Combine(Kernel.ApplicationPaths.DataPath, "ScheduledTasks"); - - if (!Directory.Exists(_scheduledTasksDataDirectory)) - { - Directory.CreateDirectory(_scheduledTasksDataDirectory); - } - } - return _scheduledTasksDataDirectory; - } - } - - /// <summary> - /// The _scheduled tasks configuration directory - /// </summary> - private string _scheduledTasksConfigurationDirectory; - /// <summary> - /// Gets the scheduled tasks configuration directory. - /// </summary> - /// <value>The scheduled tasks configuration directory.</value> - private string ScheduledTasksConfigurationDirectory - { - get - { - if (_scheduledTasksConfigurationDirectory == null) - { - _scheduledTasksConfigurationDirectory = Path.Combine(Kernel.ApplicationPaths.ConfigurationDirectoryPath, "ScheduledTasks"); - - if (!Directory.Exists(_scheduledTasksConfigurationDirectory)) - { - Directory.CreateDirectory(_scheduledTasksConfigurationDirectory); - } - } - return _scheduledTasksConfigurationDirectory; - } - } - - /// <summary> - /// Gets the configuration file path. - /// </summary> - /// <value>The configuration file path.</value> - private string ConfigurationFilePath - { - get { return Path.Combine(ScheduledTasksConfigurationDirectory, Id + ".js"); } - } - - /// <summary> - /// Gets the history file path. - /// </summary> - /// <value>The history file path.</value> - private string HistoryFilePath - { - get { return Path.Combine(ScheduledTasksDataDirectory, Id + ".js"); } - } - - /// <summary> /// Gets the current cancellation token /// </summary> /// <value>The current cancellation token source.</value> @@ -217,7 +148,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// <summary> /// The _triggers /// </summary> - private IEnumerable<BaseTaskTrigger> _triggers; + private IEnumerable<ITaskTrigger> _triggers; /// <summary> /// The _triggers initialized /// </summary> @@ -231,24 +162,11 @@ namespace MediaBrowser.Common.ScheduledTasks /// </summary> /// <value>The triggers.</value> /// <exception cref="System.ArgumentNullException">value</exception> - public IEnumerable<BaseTaskTrigger> Triggers + public IEnumerable<ITaskTrigger> Triggers { get { - LazyInitializer.EnsureInitialized(ref _triggers, ref _triggersInitialized, ref _triggersSyncLock, () => - { - try - { - return JsonSerializer.DeserializeFromFile<IEnumerable<TaskTriggerInfo>>(ConfigurationFilePath) - .Select(ScheduledTaskHelpers.GetTrigger) - .ToList(); - } - catch (IOException) - { - // File doesn't exist. No biggie. Return defaults. - return GetDefaultTriggers(); - } - }); + LazyInitializer.EnsureInitialized(ref _triggers, ref _triggersInitialized, ref _triggersSyncLock, () => TaskManager.LoadTriggers(this)); return _triggers; } @@ -271,7 +189,7 @@ namespace MediaBrowser.Common.ScheduledTasks ReloadTriggerEvents(false); - JsonSerializer.SerializeToFile(_triggers.Select(ScheduledTaskHelpers.GetTriggerInfo), ConfigurationFilePath); + TaskManager.SaveTriggers(this, _triggers); } } @@ -279,7 +197,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// Creates the triggers that define when the task will run /// </summary> /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - protected abstract IEnumerable<BaseTaskTrigger> GetDefaultTriggers(); + public abstract IEnumerable<ITaskTrigger> GetDefaultTriggers(); /// <summary> /// Returns the task to be executed @@ -314,6 +232,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// The _id /// </summary> private Guid? _id; + /// <summary> /// Gets the unique id. /// </summary> @@ -352,13 +271,19 @@ namespace MediaBrowser.Common.ScheduledTasks /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> - void trigger_Triggered(object sender, EventArgs e) + async void trigger_Triggered(object sender, EventArgs e) { - var trigger = (BaseTaskTrigger)sender; + var trigger = (ITaskTrigger)sender; Logger.Info("{0} fired for task: {1}", trigger.GetType().Name, Name); + trigger.Stop(); + TaskManager.QueueScheduledTask(this); + + await Task.Delay(1000).ConfigureAwait(false); + + trigger.Start(false); } /// <summary> @@ -404,10 +329,9 @@ namespace MediaBrowser.Common.ScheduledTasks status = TaskCompletionStatus.Failed; } + var startTime = CurrentExecutionStartTime; var endTime = DateTime.UtcNow; - LogResult(endTime, status); - Kernel.TcpManager.SendWebSocketMessage("ScheduledTaskEndExecute", LastExecutionResult); progress.ProgressChanged -= progress_ProgressChanged; @@ -415,33 +339,7 @@ namespace MediaBrowser.Common.ScheduledTasks CurrentCancellationTokenSource = null; CurrentProgress = null; - TaskManager.OnTaskCompleted(this); - } - - /// <summary> - /// Logs the result. - /// </summary> - /// <param name="endTime">The end time.</param> - /// <param name="status">The status.</param> - private void LogResult(DateTime endTime, TaskCompletionStatus status) - { - var startTime = CurrentExecutionStartTime; - var elapsedTime = endTime - startTime; - - Logger.Info("{0} {1} after {2} minute(s) and {3} seconds", Name, status, Math.Truncate(elapsedTime.TotalMinutes), elapsedTime.Seconds); - - var result = new TaskResult - { - StartTimeUtc = startTime, - EndTimeUtc = endTime, - Status = status, - Name = Name, - Id = Id - }; - - JsonSerializer.SerializeToFile(result, HistoryFilePath); - - LastExecutionResult = result; + TaskManager.OnTaskCompleted(this, startTime, endTime, status); } /// <summary> @@ -501,7 +399,7 @@ namespace MediaBrowser.Common.ScheduledTasks if (State == TaskState.Running) { - LogResult(DateTime.UtcNow, TaskCompletionStatus.Aborted); + TaskManager.OnTaskCompleted(this, CurrentExecutionStartTime, DateTime.UtcNow, TaskCompletionStatus.Aborted); } if (CurrentCancellationTokenSource != null) @@ -519,7 +417,7 @@ namespace MediaBrowser.Common.ScheduledTasks foreach (var trigger in Triggers) { trigger.Triggered -= trigger_Triggered; - trigger.Dispose(); + trigger.Stop(); } } } diff --git a/MediaBrowser.Common/ScheduledTasks/BaseTaskTrigger.cs b/MediaBrowser.Common/ScheduledTasks/BaseTaskTrigger.cs deleted file mode 100644 index ed302ed394..0000000000 --- a/MediaBrowser.Common/ScheduledTasks/BaseTaskTrigger.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.ScheduledTasks -{ - /// <summary> - /// Use to indicate that a scheduled task should run - /// </summary> - public abstract class BaseTaskTrigger : IDisposable - { - /// <summary> - /// Fires when the trigger condition is satisfied and the task should run - /// </summary> - internal event EventHandler<EventArgs> Triggered; - - /// <summary> - /// Called when [triggered]. - /// </summary> - protected async void OnTriggered() - { - Stop(); - - if (Triggered != null) - { - Triggered(this, EventArgs.Empty); - } - - await Task.Delay(1000).ConfigureAwait(false); - - Start(false); - } - - /// <summary> - /// Stars waiting for the trigger action - /// </summary> - protected internal abstract void Start(bool isApplicationStartup); - - /// <summary> - /// Stops waiting for the trigger action - /// </summary> - protected internal abstract void Stop(); - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <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) - { - if (dispose) - { - Stop(); - } - } - } -} diff --git a/MediaBrowser.Common/ScheduledTasks/DailyTrigger.cs b/MediaBrowser.Common/ScheduledTasks/DailyTrigger.cs index fb749f77cf..bfecadee7c 100644 --- a/MediaBrowser.Common/ScheduledTasks/DailyTrigger.cs +++ b/MediaBrowser.Common/ScheduledTasks/DailyTrigger.cs @@ -6,7 +6,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// <summary> /// Represents a task trigger that fires everyday /// </summary> - public class DailyTrigger : BaseTaskTrigger + public class DailyTrigger : ITaskTrigger { /// <summary> /// Get the time of day to trigger the task to run @@ -24,7 +24,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// Stars waiting for the trigger action /// </summary> /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param> - protected internal override void Start(bool isApplicationStartup) + public void Start(bool isApplicationStartup) { DisposeTimer(); @@ -39,33 +39,35 @@ namespace MediaBrowser.Common.ScheduledTasks /// <summary> /// Stops waiting for the trigger action /// </summary> - protected internal override void Stop() + public void Stop() { DisposeTimer(); } /// <summary> - /// Disposes this instance. + /// Disposes the timer. /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected override void Dispose(bool dispose) + private void DisposeTimer() { - if (dispose) + if (Timer != null) { - DisposeTimer(); + Timer.Dispose(); } - - base.Dispose(dispose); } /// <summary> - /// Disposes the timer. + /// Occurs when [triggered]. /// </summary> - private void DisposeTimer() + public event EventHandler<EventArgs> Triggered; + + /// <summary> + /// Called when [triggered]. + /// </summary> + private void OnTriggered() { - if (Timer != null) + if (Triggered != null) { - Timer.Dispose(); + Triggered(this, EventArgs.Empty); } } } diff --git a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs index cba5fc5d00..6f3a3857fe 100644 --- a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// Gets the triggers. /// </summary> /// <value>The triggers.</value> - IEnumerable<BaseTaskTrigger> Triggers { get; set; } + IEnumerable<ITaskTrigger> Triggers { get; set; } /// <summary> /// Gets the last execution result. @@ -75,5 +75,11 @@ namespace MediaBrowser.Common.ScheduledTasks /// Cancels if running. /// </summary> void CancelIfRunning(); + + /// <summary> + /// Gets the default triggers. + /// </summary> + /// <returns>IEnumerable{BaseTaskTrigger}.</returns> + IEnumerable<ITaskTrigger> GetDefaultTriggers(); } }
\ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs index 430208869a..42d7020e60 100644 --- a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs +++ b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs @@ -1,4 +1,5 @@ -using System; +using MediaBrowser.Model.Tasks; +using System; using System.Collections.Generic; namespace MediaBrowser.Common.ScheduledTasks @@ -41,6 +42,30 @@ namespace MediaBrowser.Common.ScheduledTasks /// Called when [task completed]. /// </summary> /// <param name="task">The task.</param> - void OnTaskCompleted(IScheduledTask task); + /// <param name="startTime">The start time.</param> + /// <param name="endTime">The end time.</param> + /// <param name="status">The status.</param> + void OnTaskCompleted(IScheduledTask task, DateTime startTime, DateTime endTime, TaskCompletionStatus status); + + /// <summary> + /// Gets the last execution result. + /// </summary> + /// <param name="task">The task.</param> + /// <returns>TaskResult.</returns> + TaskResult GetLastExecutionResult(IScheduledTask task); + + /// <summary> + /// Loads the triggers. + /// </summary> + /// <param name="task">The task.</param> + /// <returns>IEnumerable{BaseTaskTrigger}.</returns> + IEnumerable<ITaskTrigger> LoadTriggers(IScheduledTask task); + + /// <summary> + /// Saves the triggers. + /// </summary> + /// <param name="task">The task.</param> + /// <param name="triggers">The triggers.</param> + void SaveTriggers(IScheduledTask task, IEnumerable<ITaskTrigger> triggers); } }
\ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/ITaskTrigger.cs b/MediaBrowser.Common/ScheduledTasks/ITaskTrigger.cs new file mode 100644 index 0000000000..66701650e1 --- /dev/null +++ b/MediaBrowser.Common/ScheduledTasks/ITaskTrigger.cs @@ -0,0 +1,26 @@ +using System; + +namespace MediaBrowser.Common.ScheduledTasks +{ + /// <summary> + /// Interface ITaskTrigger + /// </summary> + public interface ITaskTrigger + { + /// <summary> + /// Fires when the trigger condition is satisfied and the task should run + /// </summary> + event EventHandler<EventArgs> Triggered; + + /// <summary> + /// Stars waiting for the trigger action + /// </summary> + /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param> + void Start(bool isApplicationStartup); + + /// <summary> + /// Stops waiting for the trigger action + /// </summary> + void Stop(); + } +}
\ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs b/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs index 759447b10f..cac6d1fa35 100644 --- a/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs +++ b/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs @@ -6,7 +6,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// <summary> /// Represents a task trigger that runs repeatedly on an interval /// </summary> - public class IntervalTrigger : BaseTaskTrigger + public class IntervalTrigger : ITaskTrigger { /// <summary> /// Gets or sets the interval. @@ -24,7 +24,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// Stars waiting for the trigger action /// </summary> /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param> - protected internal override void Start(bool isApplicationStartup) + public void Start(bool isApplicationStartup) { DisposeTimer(); @@ -34,33 +34,35 @@ namespace MediaBrowser.Common.ScheduledTasks /// <summary> /// Stops waiting for the trigger action /// </summary> - protected internal override void Stop() + public void Stop() { DisposeTimer(); } /// <summary> - /// Disposes this instance. + /// Disposes the timer. /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected override void Dispose(bool dispose) + private void DisposeTimer() { - if (dispose) + if (Timer != null) { - DisposeTimer(); + Timer.Dispose(); } - - base.Dispose(dispose); } /// <summary> - /// Disposes the timer. + /// Occurs when [triggered]. /// </summary> - private void DisposeTimer() + public event EventHandler<EventArgs> Triggered; + + /// <summary> + /// Called when [triggered]. + /// </summary> + private void OnTriggered() { - if (Timer != null) + if (Triggered != null) { - Timer.Dispose(); + Triggered(this, EventArgs.Empty); } } } diff --git a/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs b/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs index 9942da17f9..e67eb36269 100644 --- a/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs +++ b/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// </summary> /// <param name="trigger">The trigger.</param> /// <returns>TaskTriggerInfo.</returns> - public static TaskTriggerInfo GetTriggerInfo(BaseTaskTrigger trigger) + public static TaskTriggerInfo GetTriggerInfo(ITaskTrigger trigger) { var info = new TaskTriggerInfo { @@ -81,7 +81,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// <returns>BaseTaskTrigger.</returns> /// <exception cref="System.ArgumentNullException"></exception> /// <exception cref="System.ArgumentException">Invalid trigger type: + info.Type</exception> - public static BaseTaskTrigger GetTrigger(TaskTriggerInfo info) + public static ITaskTrigger GetTrigger(TaskTriggerInfo info) { if (info.Type.Equals(typeof(DailyTrigger).Name, StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs b/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs index a254d2be9d..e48551425b 100644 --- a/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs +++ b/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs @@ -1,17 +1,18 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; namespace MediaBrowser.Common.ScheduledTasks { /// <summary> /// Class StartupTaskTrigger /// </summary> - public class StartupTrigger : BaseTaskTrigger + public class StartupTrigger : ITaskTrigger { /// <summary> /// Stars waiting for the trigger action /// </summary> /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param> - protected internal async override void Start(bool isApplicationStartup) + public async void Start(bool isApplicationStartup) { if (isApplicationStartup) { @@ -24,8 +25,24 @@ namespace MediaBrowser.Common.ScheduledTasks /// <summary> /// Stops waiting for the trigger action /// </summary> - protected internal override void Stop() + public void Stop() { } + + /// <summary> + /// Occurs when [triggered]. + /// </summary> + public event EventHandler<EventArgs> Triggered; + + /// <summary> + /// Called when [triggered]. + /// </summary> + private void OnTriggered() + { + if (Triggered != null) + { + Triggered(this, EventArgs.Empty); + } + } } } diff --git a/MediaBrowser.Common/ScheduledTasks/SystemEventTrigger.cs b/MediaBrowser.Common/ScheduledTasks/SystemEventTrigger.cs index 45d1fae8e6..751da0ca57 100644 --- a/MediaBrowser.Common/ScheduledTasks/SystemEventTrigger.cs +++ b/MediaBrowser.Common/ScheduledTasks/SystemEventTrigger.cs @@ -1,5 +1,6 @@ using MediaBrowser.Model.Tasks; using Microsoft.Win32; +using System; using System.Threading.Tasks; namespace MediaBrowser.Common.ScheduledTasks @@ -7,7 +8,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// <summary> /// Class SystemEventTrigger /// </summary> - public class SystemEventTrigger : BaseTaskTrigger + public class SystemEventTrigger : ITaskTrigger { /// <summary> /// Gets or sets the system event. @@ -19,7 +20,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// Stars waiting for the trigger action /// </summary> /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param> - protected internal override void Start(bool isApplicationStartup) + public void Start(bool isApplicationStartup) { switch (SystemEvent) { @@ -32,7 +33,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// <summary> /// Stops waiting for the trigger action /// </summary> - protected internal override void Stop() + public void Stop() { SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; } @@ -52,5 +53,21 @@ namespace MediaBrowser.Common.ScheduledTasks OnTriggered(); } } + + /// <summary> + /// Occurs when [triggered]. + /// </summary> + public event EventHandler<EventArgs> Triggered; + + /// <summary> + /// Called when [triggered]. + /// </summary> + private void OnTriggered() + { + if (Triggered != null) + { + Triggered(this, EventArgs.Empty); + } + } } } diff --git a/MediaBrowser.Common/ScheduledTasks/TaskManager.cs b/MediaBrowser.Common/ScheduledTasks/TaskManager.cs deleted file mode 100644 index 946c42d2e8..0000000000 --- a/MediaBrowser.Common/ScheduledTasks/TaskManager.cs +++ /dev/null @@ -1,159 +0,0 @@ -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Tasks; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MediaBrowser.Common.ScheduledTasks -{ - /// <summary> - /// Class TaskManager - /// </summary> - internal class TaskManager : ITaskManager - { - /// <summary> - /// Gets the list of Scheduled Tasks - /// </summary> - /// <value>The scheduled tasks.</value> - public IScheduledTask[] ScheduledTasks { get; private set; } - - /// <summary> - /// The _task queue - /// </summary> - private readonly List<Type> _taskQueue = new List<Type>(); - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - /// <summary> - /// Initializes a new instance of the <see cref="TaskManager" /> class. - /// </summary> - /// <param name="logger">The logger.</param> - public TaskManager(ILogger logger) - { - if (logger == null) - { - throw new ArgumentException("logger"); - } - - _logger = logger; - - ScheduledTasks = new IScheduledTask[] {}; - } - - /// <summary> - /// Cancels if running and queue. - /// </summary> - /// <typeparam name="T"></typeparam> - public void CancelIfRunningAndQueue<T>() - where T : IScheduledTask - { - ScheduledTasks.OfType<T>().First().CancelIfRunning(); - QueueScheduledTask<T>(); - } - - /// <summary> - /// Queues the scheduled task. - /// </summary> - /// <typeparam name="T"></typeparam> - public void QueueScheduledTask<T>() - where T : IScheduledTask - { - var scheduledTask = ScheduledTasks.OfType<T>().First(); - - QueueScheduledTask(scheduledTask); - } - - /// <summary> - /// Queues the scheduled task. - /// </summary> - /// <param name="task">The task.</param> - public void QueueScheduledTask(IScheduledTask task) - { - var type = task.GetType(); - - var scheduledTask = ScheduledTasks.First(t => t.GetType() == type); - - lock (_taskQueue) - { - // If it's idle just execute immediately - if (scheduledTask.State == TaskState.Idle) - { - scheduledTask.Execute(); - return; - } - - if (!_taskQueue.Contains(type)) - { - _logger.Info("Queueing task {0}", type.Name); - _taskQueue.Add(type); - } - else - { - _logger.Info("Task already queued: {0}", type.Name); - } - } - } - - /// <summary> - /// Called when [task completed]. - /// </summary> - /// <param name="task">The task.</param> - public void OnTaskCompleted(IScheduledTask task) - { - // Execute queued tasks - lock (_taskQueue) - { - var copy = _taskQueue.ToList(); - - foreach (var type in copy) - { - var scheduledTask = ScheduledTasks.First(t => t.GetType() == type); - - if (scheduledTask.State == TaskState.Idle) - { - scheduledTask.Execute(); - - _taskQueue.Remove(type); - } - } - } - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <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) - { - foreach (var task in ScheduledTasks) - { - task.Dispose(); - } - } - - /// <summary> - /// Adds the tasks. - /// </summary> - /// <param name="tasks">The tasks.</param> - public void AddTasks(IEnumerable<IScheduledTask> tasks) - { - var myTasks = ScheduledTasks.ToList(); - - myTasks.AddRange(tasks); - - ScheduledTasks = myTasks.ToArray(); - } - } -} diff --git a/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteCacheFileTask.cs deleted file mode 100644 index b06134ee28..0000000000 --- a/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ /dev/null @@ -1,118 +0,0 @@ -using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.ScheduledTasks.Tasks -{ - /// <summary> - /// Deletes old cache files - /// </summary> - public class DeleteCacheFileTask : BaseScheduledTask<IKernel> - { - /// <summary> - /// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class. - /// </summary> - /// <param name="kernel">The kernel.</param> - /// <param name="taskManager">The task manager.</param> - /// <param name="logger">The logger.</param> - public DeleteCacheFileTask(IKernel kernel, ITaskManager taskManager, ILogger logger) - : base(kernel, taskManager, logger) - { - } - - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - protected override IEnumerable<BaseTaskTrigger> GetDefaultTriggers() - { - var trigger = new DailyTrigger { TimeOfDay = TimeSpan.FromHours(2) }; //2am - - return new[] { trigger }; - } - - /// <summary> - /// Returns the task to be executed - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) - { - return Task.Run(() => - { - var minDateModified = DateTime.UtcNow.AddMonths(-2); - - DeleteCacheFilesFromDirectory(cancellationToken, Kernel.ApplicationPaths.CachePath, minDateModified, progress); - }); - } - - - /// <summary> - /// Deletes the cache files from directory with a last write time less than a given date - /// </summary> - /// <param name="cancellationToken">The task cancellation token.</param> - /// <param name="directory">The directory.</param> - /// <param name="minDateModified">The min date modified.</param> - /// <param name="progress">The progress.</param> - private void DeleteCacheFilesFromDirectory(CancellationToken cancellationToken, string directory, DateTime minDateModified, IProgress<double> progress) - { - var filesToDelete = new DirectoryInfo(directory).EnumerateFileSystemInfos("*", SearchOption.AllDirectories) - .Where(f => !f.Attributes.HasFlag(FileAttributes.Directory) && f.LastWriteTimeUtc < minDateModified) - .ToList(); - - var index = 0; - - foreach (var file in filesToDelete) - { - double percent = index; - percent /= filesToDelete.Count; - - progress.Report(100 * percent); - - cancellationToken.ThrowIfCancellationRequested(); - - File.Delete(file.FullName); - - index++; - } - - progress.Report(100); - } - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "Cache file cleanup"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public override string Description - { - get { return "Deletes cache files no longer needed by the system"; } - } - - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> - public override string Category - { - get - { - return "Maintenance"; - } - } - } -} diff --git a/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteLogFileTask.cs deleted file mode 100644 index 0b243cb108..0000000000 --- a/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteLogFileTask.cs +++ /dev/null @@ -1,106 +0,0 @@ -using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.ScheduledTasks.Tasks -{ - /// <summary> - /// Deletes old log files - /// </summary> - public class DeleteLogFileTask : BaseScheduledTask<IKernel> - { - /// <summary> - /// Initializes a new instance of the <see cref="DeleteLogFileTask" /> class. - /// </summary> - /// <param name="kernel">The kernel.</param> - /// <param name="taskManager">The task manager.</param> - /// <param name="logger">The logger.</param> - public DeleteLogFileTask(IKernel kernel, ITaskManager taskManager, ILogger logger) - : base(kernel, taskManager, logger) - { - } - - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - protected override IEnumerable<BaseTaskTrigger> GetDefaultTriggers() - { - var trigger = new DailyTrigger { TimeOfDay = TimeSpan.FromHours(2) }; //2am - - return new[] { trigger }; - } - - /// <summary> - /// Returns the task to be executed - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) - { - return Task.Run(() => - { - // Delete log files more than n days old - var minDateModified = DateTime.UtcNow.AddDays(-(Kernel.Configuration.LogFileRetentionDays)); - - var filesToDelete = new DirectoryInfo(Kernel.ApplicationPaths.LogDirectoryPath).EnumerateFileSystemInfos("*", SearchOption.AllDirectories) - .Where(f => f.LastWriteTimeUtc < minDateModified) - .ToList(); - - var index = 0; - - foreach (var file in filesToDelete) - { - double percent = index; - percent /= filesToDelete.Count; - - progress.Report(100 * percent); - - cancellationToken.ThrowIfCancellationRequested(); - - File.Delete(file.FullName); - - index++; - } - - progress.Report(100); - }); - } - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "Log file cleanup"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public override string Description - { - get { return string.Format("Deletes log files that are more than {0} days old.", Kernel.Configuration.LogFileRetentionDays); } - } - - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> - public override string Category - { - get - { - return "Maintenance"; - } - } - } -} diff --git a/MediaBrowser.Common/ScheduledTasks/Tasks/ReloadLoggerTask.cs b/MediaBrowser.Common/ScheduledTasks/Tasks/ReloadLoggerTask.cs deleted file mode 100644 index 35cbe98f10..0000000000 --- a/MediaBrowser.Common/ScheduledTasks/Tasks/ReloadLoggerTask.cs +++ /dev/null @@ -1,70 +0,0 @@ -using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.ScheduledTasks.Tasks -{ - /// <summary> - /// Class ReloadLoggerFileTask - /// </summary> - public class ReloadLoggerFileTask : BaseScheduledTask<IKernel> - { - /// <summary> - /// Initializes a new instance of the <see cref="ReloadLoggerFileTask" /> class. - /// </summary> - /// <param name="kernel">The kernel.</param> - /// <param name="taskManager">The task manager.</param> - /// <param name="logger">The logger.</param> - public ReloadLoggerFileTask(IKernel kernel, ITaskManager taskManager, ILogger logger) - : base(kernel, taskManager, logger) - { - } - - /// <summary> - /// Gets the default triggers. - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - protected override IEnumerable<BaseTaskTrigger> GetDefaultTriggers() - { - var trigger = new DailyTrigger { TimeOfDay = TimeSpan.FromHours(0) }; //12am - - return new[] { trigger }; - } - - /// <summary> - /// Executes the internal. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) - { - cancellationToken.ThrowIfCancellationRequested(); - - progress.Report(0); - - return Task.Run(() => Kernel.ReloadLogger()); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "Start new log file"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public override string Description - { - get { return "Moves logging to a new file to help reduce log file sizes."; } - } - } -} diff --git a/MediaBrowser.Common/ScheduledTasks/Tasks/SystemUpdateTask.cs b/MediaBrowser.Common/ScheduledTasks/Tasks/SystemUpdateTask.cs deleted file mode 100644 index f02293a5e1..0000000000 --- a/MediaBrowser.Common/ScheduledTasks/Tasks/SystemUpdateTask.cs +++ /dev/null @@ -1,121 +0,0 @@ -using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.ScheduledTasks.Tasks -{ - /// <summary> - /// Plugin Update Task - /// </summary> - public class SystemUpdateTask : BaseScheduledTask<IKernel> - { - /// <summary> - /// The _app host - /// </summary> - private readonly IApplicationHost _appHost; - - /// <summary> - /// Initializes a new instance of the <see cref="SystemUpdateTask" /> class. - /// </summary> - /// <param name="appHost">The app host.</param> - /// <param name="taskManager">The task manager.</param> - /// <param name="kernel">The kernel.</param> - /// <param name="logger">The logger.</param> - public SystemUpdateTask(IApplicationHost appHost, ITaskManager taskManager, IKernel kernel, ILogger logger) - : base(kernel, taskManager, logger) - { - _appHost = appHost; - } - - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - protected override IEnumerable<BaseTaskTrigger> GetDefaultTriggers() - { - return new BaseTaskTrigger[] { - - // 1am - new DailyTrigger { TimeOfDay = TimeSpan.FromHours(1) }, - - new IntervalTrigger { Interval = TimeSpan.FromHours(2)} - }; - } - - /// <summary> - /// Returns the task to be executed - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - protected override async Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) - { - if (!_appHost.CanSelfUpdate) return; - - EventHandler<double> innerProgressHandler = (sender, e) => progress.Report(e * .1); - - // Create a progress object for the update check - var innerProgress = new Progress<double>(); - innerProgress.ProgressChanged += innerProgressHandler; - - var updateInfo = await _appHost.CheckForApplicationUpdate(cancellationToken, innerProgress).ConfigureAwait(false); - - // Release the event handler - innerProgress.ProgressChanged -= innerProgressHandler; - - progress.Report(10); - - if (!updateInfo.IsUpdateAvailable) - { - progress.Report(100); - return; - } - - cancellationToken.ThrowIfCancellationRequested(); - - if (Kernel.Configuration.EnableAutoUpdate) - { - Logger.Info("Update Revision {0} available. Updating...", updateInfo.AvailableVersion); - - innerProgressHandler = (sender, e) => progress.Report((e * .9) + .1); - - innerProgress = new Progress<double>(); - innerProgress.ProgressChanged += innerProgressHandler; - - await _appHost.UpdateApplication(cancellationToken, innerProgress).ConfigureAwait(false); - - // Release the event handler - innerProgress.ProgressChanged -= innerProgressHandler; - - Kernel.OnApplicationUpdated(updateInfo.AvailableVersion); - } - else - { - Logger.Info("A new version of Media Browser is available."); - } - - progress.Report(100); - } - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "Check for application updates"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public override string Description - { - get { return "Downloads and installs application updates."; } - } - } -} diff --git a/MediaBrowser.Common/ScheduledTasks/WeeklyTrigger.cs b/MediaBrowser.Common/ScheduledTasks/WeeklyTrigger.cs index afeacc2b3d..cfb3f1fab3 100644 --- a/MediaBrowser.Common/ScheduledTasks/WeeklyTrigger.cs +++ b/MediaBrowser.Common/ScheduledTasks/WeeklyTrigger.cs @@ -6,7 +6,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// <summary> /// Represents a task trigger that fires on a weekly basis /// </summary> - public class WeeklyTrigger : BaseTaskTrigger + public class WeeklyTrigger : ITaskTrigger { /// <summary> /// Get the time of day to trigger the task to run @@ -30,7 +30,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// Stars waiting for the trigger action /// </summary> /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param> - protected internal override void Start(bool isApplicationStartup) + public void Start(bool isApplicationStartup) { DisposeTimer(); @@ -69,33 +69,35 @@ namespace MediaBrowser.Common.ScheduledTasks /// <summary> /// Stops waiting for the trigger action /// </summary> - protected internal override void Stop() + public void Stop() { DisposeTimer(); } /// <summary> - /// Disposes this instance. + /// Disposes the timer. /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected override void Dispose(bool dispose) + private void DisposeTimer() { - if (dispose) + if (Timer != null) { - DisposeTimer(); + Timer.Dispose(); } - - base.Dispose(dispose); } /// <summary> - /// Disposes the timer. + /// Occurs when [triggered]. /// </summary> - private void DisposeTimer() + public event EventHandler<EventArgs> Triggered; + + /// <summary> + /// Called when [triggered]. + /// </summary> + private void OnTriggered() { - if (Timer != null) + if (Triggered != null) { - Timer.Dispose(); + Triggered(this, EventArgs.Empty); } } } diff --git a/MediaBrowser.Common/Serialization/DynamicProtobufSerializer.cs b/MediaBrowser.Common/Serialization/DynamicProtobufSerializer.cs deleted file mode 100644 index 359cf9da06..0000000000 --- a/MediaBrowser.Common/Serialization/DynamicProtobufSerializer.cs +++ /dev/null @@ -1,157 +0,0 @@ -using ProtoBuf; -using ProtoBuf.Meta; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace MediaBrowser.Common.Serialization -{ - /// <summary> - /// Creates a compiled protobuf serializer based on a set of assemblies - /// </summary> - public class DynamicProtobufSerializer - { - /// <summary> - /// Gets or sets the type model. - /// </summary> - /// <value>The type model.</value> - public TypeModel TypeModel { get; set; } - - /// <summary> - /// Serializes to stream. - /// </summary> - /// <param name="obj">The obj.</param> - /// <param name="stream">The stream.</param> - /// <exception cref="System.ArgumentNullException">obj</exception> - public void SerializeToStream(object obj, Stream stream) - { - if (obj == null) - { - throw new ArgumentNullException("obj"); - } - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - TypeModel.Serialize(stream, obj); - } - - /// <summary> - /// Deserializes from stream. - /// </summary> - /// <param name="stream">The stream.</param> - /// <param name="type">The type.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">stream</exception> - public object DeserializeFromStream(Stream stream, Type type) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - return TypeModel.Deserialize(stream, null, type); - } - - /// <summary> - /// Deserializes from stream. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="stream">The stream.</param> - /// <returns>``0.</returns> - public T DeserializeFromStream<T>(Stream stream) - where T : class - { - return DeserializeFromStream(stream, typeof(T)) as T; - } - - /// <summary> - /// Serializes to file. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="obj">The obj.</param> - /// <param name="file">The file.</param> - /// <exception cref="System.ArgumentNullException">file</exception> - public void SerializeToFile<T>(T obj, string file) - { - if (string.IsNullOrEmpty(file)) - { - throw new ArgumentNullException("file"); - } - - using (Stream stream = File.Open(file, FileMode.Create)) - { - SerializeToStream(obj, stream); - } - } - - /// <summary> - /// Deserializes from file. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="file">The file.</param> - /// <returns>``0.</returns> - /// <exception cref="System.ArgumentNullException">file</exception> - public T DeserializeFromFile<T>(string file) - where T : class - { - if (string.IsNullOrEmpty(file)) - { - throw new ArgumentNullException("file"); - } - - using (Stream stream = File.OpenRead(file)) - { - return DeserializeFromStream<T>(stream); - } - } - - /// <summary> - /// Serializes to bytes. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="obj">The obj.</param> - /// <returns>System.Byte[][].</returns> - /// <exception cref="System.ArgumentNullException">obj</exception> - public byte[] SerializeToBytes<T>(T obj) - where T : class - { - if (obj == null) - { - throw new ArgumentNullException("obj"); - } - - using (var stream = new MemoryStream()) - { - SerializeToStream(obj, stream); - return stream.ToArray(); - } - } - - /// <summary> - /// Creates the specified assemblies. - /// </summary> - /// <returns>DynamicProtobufSerializer.</returns> - /// <exception cref="System.ArgumentNullException">assemblies</exception> - public static DynamicProtobufSerializer Create(IEnumerable<Type> types) - { - if (types == null) - { - throw new ArgumentNullException("types"); - } - - var model = TypeModel.Create(); - var attributeType = typeof(ProtoContractAttribute); - - // Find all ProtoContracts in the current assembly - foreach (var type in types.Where(t => Attribute.IsDefined(t, attributeType))) - { - model.Add(type, true); - } - - return new DynamicProtobufSerializer { TypeModel = model.Compile() }; - } - } -} diff --git a/MediaBrowser.Common/Serialization/JsonSerializer.cs b/MediaBrowser.Common/Serialization/JsonSerializer.cs deleted file mode 100644 index 5b6e354a8c..0000000000 --- a/MediaBrowser.Common/Serialization/JsonSerializer.cs +++ /dev/null @@ -1,259 +0,0 @@ -using System; -using System.IO; - -namespace MediaBrowser.Common.Serialization -{ - /// <summary> - /// Provides a wrapper around third party json serialization. - /// </summary> - public class JsonSerializer - { - /// <summary> - /// Serializes to stream. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="obj">The obj.</param> - /// <param name="stream">The stream.</param> - /// <exception cref="System.ArgumentNullException">obj</exception> - public static void SerializeToStream<T>(T obj, Stream stream) - where T : class - { - if (obj == null) - { - throw new ArgumentNullException("obj"); - } - - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - Configure(); - - ServiceStack.Text.JsonSerializer.SerializeToStream(obj, obj.GetType(), stream); - } - - /// <summary> - /// Serializes to file. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="obj">The obj.</param> - /// <param name="file">The file.</param> - /// <exception cref="System.ArgumentNullException">obj</exception> - public static void SerializeToFile<T>(T obj, string file) - where T : class - { - if (obj == null) - { - throw new ArgumentNullException("obj"); - } - - if (string.IsNullOrEmpty(file)) - { - throw new ArgumentNullException("file"); - } - - Configure(); - - using (Stream stream = File.Open(file, FileMode.Create)) - { - SerializeToStream(obj, stream); - } - } - - /// <summary> - /// Deserializes from file. - /// </summary> - /// <param name="type">The type.</param> - /// <param name="file">The file.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">type</exception> - public static object DeserializeFromFile(Type type, string file) - { - if (type == null) - { - throw new ArgumentNullException("type"); - } - - if (string.IsNullOrEmpty(file)) - { - throw new ArgumentNullException("file"); - } - - Configure(); - - using (Stream stream = File.OpenRead(file)) - { - return ServiceStack.Text.JsonSerializer.DeserializeFromStream(type, stream); - } - } - - /// <summary> - /// Deserializes from file. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="file">The file.</param> - /// <returns>``0.</returns> - /// <exception cref="System.ArgumentNullException">file</exception> - public static T DeserializeFromFile<T>(string file) - where T : class - { - if (string.IsNullOrEmpty(file)) - { - throw new ArgumentNullException("file"); - } - - Configure(); - - using (Stream stream = File.OpenRead(file)) - { - return ServiceStack.Text.JsonSerializer.DeserializeFromStream<T>(stream); - } - } - - /// <summary> - /// Deserializes from stream. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="stream">The stream.</param> - /// <returns>``0.</returns> - /// <exception cref="System.ArgumentNullException">stream</exception> - public static T DeserializeFromStream<T>(Stream stream) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - Configure(); - - return ServiceStack.Text.JsonSerializer.DeserializeFromStream<T>(stream); - } - - /// <summary> - /// Deserializes from string. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="text">The text.</param> - /// <returns>``0.</returns> - /// <exception cref="System.ArgumentNullException">text</exception> - public static T DeserializeFromString<T>(string text) - { - if (string.IsNullOrEmpty(text)) - { - throw new ArgumentNullException("text"); - } - - Configure(); - - return ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(text); - } - - /// <summary> - /// Deserializes from stream. - /// </summary> - /// <param name="stream">The stream.</param> - /// <param name="type">The type.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">stream</exception> - public static object DeserializeFromStream(Stream stream, Type type) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - if (type == null) - { - throw new ArgumentNullException("type"); - } - - Configure(); - - return ServiceStack.Text.JsonSerializer.DeserializeFromStream(type, stream); - } - - /// <summary> - /// The _is configured - /// </summary> - private static bool _isConfigured; - /// <summary> - /// Configures this instance. - /// </summary> - internal static void Configure() - { - if (!_isConfigured) - { - ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.JsonDateHandler.ISO8601; - ServiceStack.Text.JsConfig.ExcludeTypeInfo = true; - ServiceStack.Text.JsConfig.IncludeNullValues = false; - _isConfigured = true; - } - } - - /// <summary> - /// Deserializes from string. - /// </summary> - /// <param name="json">The json.</param> - /// <param name="type">The type.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">json</exception> - public static object DeserializeFromString(string json, Type type) - { - if (string.IsNullOrEmpty(json)) - { - throw new ArgumentNullException("json"); - } - - if (type == null) - { - throw new ArgumentNullException("type"); - } - - Configure(); - - return ServiceStack.Text.JsonSerializer.DeserializeFromString(json, type); - } - - /// <summary> - /// Serializes to string. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="obj">The obj.</param> - /// <returns>System.String.</returns> - /// <exception cref="System.ArgumentNullException">obj</exception> - public static string SerializeToString<T>(T obj) - where T : class - { - if (obj == null) - { - throw new ArgumentNullException("obj"); - } - - Configure(); - return ServiceStack.Text.JsonSerializer.SerializeToString(obj, obj.GetType()); - } - - /// <summary> - /// Serializes to bytes. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="obj">The obj.</param> - /// <returns>System.Byte[][].</returns> - /// <exception cref="System.ArgumentNullException">obj</exception> - public static byte[] SerializeToBytes<T>(T obj) - where T : class - { - if (obj == null) - { - throw new ArgumentNullException("obj"); - } - - using (var stream = new MemoryStream()) - { - SerializeToStream(obj, stream); - return stream.ToArray(); - } - } - } -} diff --git a/MediaBrowser.Common/Serialization/XmlSerializer.cs b/MediaBrowser.Common/Serialization/XmlSerializer.cs deleted file mode 100644 index 07010a5d25..0000000000 --- a/MediaBrowser.Common/Serialization/XmlSerializer.cs +++ /dev/null @@ -1,212 +0,0 @@ -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Linq; -using System.Xml; - -namespace MediaBrowser.Common.Serialization -{ - /// <summary> - /// Provides a wrapper around third party xml serialization. - /// </summary> - public class XmlSerializer - { - /// <summary> - /// Serializes to writer. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="obj">The obj.</param> - /// <param name="writer">The writer.</param> - public static void SerializeToWriter<T>(T obj, XmlTextWriter writer) - { - writer.Formatting = Formatting.Indented; - var netSerializer = new System.Xml.Serialization.XmlSerializer(typeof(T)); - netSerializer.Serialize(writer, obj); - } - - /// <summary> - /// Serializes to writer. - /// </summary> - /// <param name="obj">The obj.</param> - /// <param name="writer">The writer.</param> - public static void SerializeToWriter(object obj, XmlTextWriter writer) - { - writer.Formatting = Formatting.Indented; - var netSerializer = new System.Xml.Serialization.XmlSerializer(obj.GetType()); - netSerializer.Serialize(writer, obj); - } - - /// <summary> - /// Deserializes from stream. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="stream">The stream.</param> - /// <returns>``0.</returns> - public static T DeserializeFromStream<T>(Stream stream) - { - using (var reader = new XmlTextReader(stream)) - { - var netSerializer = new System.Xml.Serialization.XmlSerializer(typeof(T)); - - return (T)netSerializer.Deserialize(reader); - } - } - - /// <summary> - /// Deserializes from stream. - /// </summary> - /// <param name="type">The type.</param> - /// <param name="stream">The stream.</param> - /// <returns>System.Object.</returns> - public static object DeserializeFromStream(Type type, Stream stream) - { - using (var reader = new XmlTextReader(stream)) - { - var netSerializer = new System.Xml.Serialization.XmlSerializer(type); - - return netSerializer.Deserialize(reader); - } - } - - /// <summary> - /// Serializes to stream. - /// </summary> - /// <param name="obj">The obj.</param> - /// <param name="stream">The stream.</param> - public static void SerializeToStream(object obj, Stream stream) - { - using (var writer = new XmlTextWriter(stream, null)) - { - SerializeToWriter(obj, writer); - } - } - - /// <summary> - /// Deserializes from file. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="file">The file.</param> - /// <returns>``0.</returns> - public static T DeserializeFromFile<T>(string file) - { - using (var stream = File.OpenRead(file)) - { - return DeserializeFromStream<T>(stream); - } - } - - /// <summary> - /// Serializes to file. - /// </summary> - /// <param name="obj">The obj.</param> - /// <param name="file">The file.</param> - public static void SerializeToFile(object obj, string file) - { - using (var stream = new FileStream(file, FileMode.Create)) - { - SerializeToStream(obj, stream); - } - } - - /// <summary> - /// Deserializes from file. - /// </summary> - /// <param name="type">The type.</param> - /// <param name="file">The file.</param> - /// <returns>System.Object.</returns> - public static object DeserializeFromFile(Type type, string file) - { - using (var stream = File.OpenRead(file)) - { - return DeserializeFromStream(type, stream); - } - } - - /// <summary> - /// Deserializes from bytes. - /// </summary> - /// <param name="type">The type.</param> - /// <param name="buffer">The buffer.</param> - /// <returns>System.Object.</returns> - public static object DeserializeFromBytes(Type type, byte[] buffer) - { - using (var stream = new MemoryStream(buffer)) - { - return DeserializeFromStream(type, stream); - } - } - - /// <summary> - /// Serializes to bytes. - /// </summary> - /// <param name="obj">The obj.</param> - /// <returns>System.Byte[][].</returns> - public static byte[] SerializeToBytes(object obj) - { - using (var stream = new MemoryStream()) - { - SerializeToStream(obj, stream); - - return stream.ToArray(); - } - } - - /// <summary> - /// Reads an xml configuration file from the file system - /// It will immediately re-serialize and save if new serialization data is available due to property changes - /// </summary> - /// <param name="type">The type.</param> - /// <param name="path">The path.</param> - /// <param name="logger">The logger.</param> - /// <returns>System.Object.</returns> - public static object GetXmlConfiguration(Type type, string path, ILogger logger) - { - logger.Info("Loading {0} at {1}", type.Name, path); - - object configuration; - - byte[] buffer = null; - - // Use try/catch to avoid the extra file system lookup using File.Exists - try - { - buffer = File.ReadAllBytes(path); - - configuration = DeserializeFromBytes(type, buffer); - } - catch (FileNotFoundException) - { - configuration = Activator.CreateInstance(type); - } - - // Take the object we just got and serialize it back to bytes - var newBytes = SerializeToBytes(configuration); - - // If the file didn't exist before, or if something has changed, re-save - if (buffer == null || !buffer.SequenceEqual(newBytes)) - { - logger.Info("Saving {0} to {1}", type.Name, path); - - // Save it after load in case we got new items - File.WriteAllBytes(path, newBytes); - } - - return configuration; - } - - /// <summary> - /// Reads an xml configuration file from the file system - /// It will immediately save the configuration after loading it, just - /// in case there are new serializable properties - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="path">The path.</param> - /// <param name="logger">The logger.</param> - /// <returns>``0.</returns> - public static T GetXmlConfiguration<T>(string path, ILogger logger) - where T : class - { - return GetXmlConfiguration(typeof(T), path, logger) as T; - } - } -} diff --git a/MediaBrowser.Common/packages.config b/MediaBrowser.Common/packages.config index 0ebaf62975..ea25110aae 100644 --- a/MediaBrowser.Common/packages.config +++ b/MediaBrowser.Common/packages.config @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="protobuf-net" version="2.0.0.621" targetFramework="net45" /> <package id="ServiceStack" version="3.9.37" targetFramework="net45" /> <package id="ServiceStack.Common" version="3.9.37" targetFramework="net45" /> <package id="ServiceStack.OrmLite.SqlServer" version="3.9.37" targetFramework="net45" /> |
