123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- using MediaBrowser.Common.Configuration;
- using MediaBrowser.Common.Events;
- using MediaBrowser.Model.Configuration;
- using MediaBrowser.Model.Logging;
- using MediaBrowser.Model.Serialization;
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Threading;
- using MediaBrowser.Model.IO;
- using MediaBrowser.Common.Extensions;
- namespace MediaBrowser.Common.Implementations.Configuration
- {
- /// <summary>
- /// Class BaseConfigurationManager
- /// </summary>
- public abstract class BaseConfigurationManager : IConfigurationManager
- {
- /// <summary>
- /// Gets the type of the configuration.
- /// </summary>
- /// <value>The type of the configuration.</value>
- protected abstract Type ConfigurationType { get; }
- /// <summary>
- /// Occurs when [configuration updated].
- /// </summary>
- public event EventHandler<EventArgs> ConfigurationUpdated;
- /// <summary>
- /// Occurs when [configuration updating].
- /// </summary>
- public event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdating;
- /// <summary>
- /// Occurs when [named configuration updated].
- /// </summary>
- public event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdated;
- /// <summary>
- /// Gets the logger.
- /// </summary>
- /// <value>The logger.</value>
- protected ILogger Logger { get; private set; }
- /// <summary>
- /// Gets the XML serializer.
- /// </summary>
- /// <value>The XML serializer.</value>
- protected IXmlSerializer XmlSerializer { get; private set; }
- /// <summary>
- /// Gets or sets the application paths.
- /// </summary>
- /// <value>The application paths.</value>
- public IApplicationPaths CommonApplicationPaths { get; private set; }
- public readonly IFileSystem FileSystem;
- /// <summary>
- /// The _configuration loaded
- /// </summary>
- private bool _configurationLoaded;
- /// <summary>
- /// The _configuration sync lock
- /// </summary>
- private object _configurationSyncLock = new object();
- /// <summary>
- /// The _configuration
- /// </summary>
- private BaseApplicationConfiguration _configuration;
- /// <summary>
- /// Gets the system configuration
- /// </summary>
- /// <value>The configuration.</value>
- public BaseApplicationConfiguration CommonConfiguration
- {
- get
- {
- // Lazy load
- LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer, FileSystem));
- return _configuration;
- }
- protected set
- {
- _configuration = value;
- _configurationLoaded = value != null;
- }
- }
- private ConfigurationStore[] _configurationStores = { };
- private IConfigurationFactory[] _configurationFactories = { };
- /// <summary>
- /// Initializes a new instance of the <see cref="BaseConfigurationManager" /> class.
- /// </summary>
- /// <param name="applicationPaths">The application paths.</param>
- /// <param name="logManager">The log manager.</param>
- /// <param name="xmlSerializer">The XML serializer.</param>
- protected BaseConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer, IFileSystem fileSystem)
- {
- CommonApplicationPaths = applicationPaths;
- XmlSerializer = xmlSerializer;
- FileSystem = fileSystem;
- Logger = logManager.GetLogger(GetType().Name);
- UpdateCachePath();
- }
- public virtual void AddParts(IEnumerable<IConfigurationFactory> factories)
- {
- _configurationFactories = factories.ToArray();
- _configurationStores = _configurationFactories
- .SelectMany(i => i.GetConfigurations())
- .ToArray();
- }
- /// <summary>
- /// Saves the configuration.
- /// </summary>
- public void SaveConfiguration()
- {
- Logger.Info("Saving system configuration");
- var path = CommonApplicationPaths.SystemConfigurationFilePath;
- FileSystem.CreateDirectory(Path.GetDirectoryName(path));
- lock (_configurationSyncLock)
- {
- XmlSerializer.SerializeToFile(CommonConfiguration, path);
- }
- OnConfigurationUpdated();
- }
- /// <summary>
- /// Called when [configuration updated].
- /// </summary>
- protected virtual void OnConfigurationUpdated()
- {
- UpdateCachePath();
- EventHelper.QueueEventIfNotNull(ConfigurationUpdated, this, EventArgs.Empty, Logger);
- }
- /// <summary>
- /// Replaces the configuration.
- /// </summary>
- /// <param name="newConfiguration">The new configuration.</param>
- /// <exception cref="System.ArgumentNullException">newConfiguration</exception>
- public virtual void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
- {
- if (newConfiguration == null)
- {
- throw new ArgumentNullException("newConfiguration");
- }
- ValidateCachePath(newConfiguration);
- CommonConfiguration = newConfiguration;
- SaveConfiguration();
- }
- /// <summary>
- /// Updates the items by name path.
- /// </summary>
- private void UpdateCachePath()
- {
- string cachePath;
- if (string.IsNullOrWhiteSpace(CommonConfiguration.CachePath))
- {
- cachePath = null;
- }
- else
- {
- cachePath = Path.Combine(CommonConfiguration.CachePath, "cache");
- }
- ((BaseApplicationPaths)CommonApplicationPaths).CachePath = cachePath;
- }
- /// <summary>
- /// Replaces the cache path.
- /// </summary>
- /// <param name="newConfig">The new configuration.</param>
- /// <exception cref="System.IO.DirectoryNotFoundException"></exception>
- private void ValidateCachePath(BaseApplicationConfiguration newConfig)
- {
- var newPath = newConfig.CachePath;
- if (!string.IsNullOrWhiteSpace(newPath)
- && !string.Equals(CommonConfiguration.CachePath ?? string.Empty, newPath))
- {
- // Validate
- if (!FileSystem.DirectoryExists(newPath))
- {
- throw new FileNotFoundException(string.Format("{0} does not exist.", newPath));
- }
- EnsureWriteAccess(newPath);
- }
- }
- protected void EnsureWriteAccess(string path)
- {
- var file = Path.Combine(path, Guid.NewGuid().ToString());
- FileSystem.WriteAllText(file, string.Empty);
- FileSystem.DeleteFile(file);
- }
- private readonly ConcurrentDictionary<string, object> _configurations = new ConcurrentDictionary<string, object>();
- private string GetConfigurationFile(string key)
- {
- return Path.Combine(CommonApplicationPaths.ConfigurationDirectoryPath, key.ToLower() + ".xml");
- }
- public object GetConfiguration(string key)
- {
- return _configurations.GetOrAdd(key, k =>
- {
- var file = GetConfigurationFile(key);
- var configurationInfo = _configurationStores
- .FirstOrDefault(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase));
- if (configurationInfo == null)
- {
- throw new ResourceNotFoundException("Configuration with key " + key + " not found.");
- }
- var configurationType = configurationInfo.ConfigurationType;
- lock (_configurationSyncLock)
- {
- return LoadConfiguration(file, configurationType);
- }
- });
- }
- private object LoadConfiguration(string path, Type configurationType)
- {
- try
- {
- return XmlSerializer.DeserializeFromFile(configurationType, path);
- }
- catch (FileNotFoundException)
- {
- return Activator.CreateInstance(configurationType);
- }
- catch (IOException)
- {
- return Activator.CreateInstance(configurationType);
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error loading configuration file: {0}", ex, path);
- return Activator.CreateInstance(configurationType);
- }
- }
- public void SaveConfiguration(string key, object configuration)
- {
- var configurationStore = GetConfigurationStore(key);
- var configurationType = configurationStore.ConfigurationType;
- if (configuration.GetType() != configurationType)
- {
- throw new ArgumentException("Expected configuration type is " + configurationType.Name);
- }
- var validatingStore = configurationStore as IValidatingConfiguration;
- if (validatingStore != null)
- {
- var currentConfiguration = GetConfiguration(key);
- validatingStore.Validate(currentConfiguration, configuration);
- }
- EventHelper.FireEventIfNotNull(NamedConfigurationUpdating, this, new ConfigurationUpdateEventArgs
- {
- Key = key,
- NewConfiguration = configuration
- }, Logger);
- _configurations.AddOrUpdate(key, configuration, (k, v) => configuration);
- var path = GetConfigurationFile(key);
- FileSystem.CreateDirectory(Path.GetDirectoryName(path));
- lock (_configurationSyncLock)
- {
- XmlSerializer.SerializeToFile(configuration, path);
- }
- OnNamedConfigurationUpdated(key, configuration);
- }
- protected virtual void OnNamedConfigurationUpdated(string key, object configuration)
- {
- EventHelper.FireEventIfNotNull(NamedConfigurationUpdated, this, new ConfigurationUpdateEventArgs
- {
- Key = key,
- NewConfiguration = configuration
- }, Logger);
- }
- public Type GetConfigurationType(string key)
- {
- return GetConfigurationStore(key)
- .ConfigurationType;
- }
- private ConfigurationStore GetConfigurationStore(string key)
- {
- return _configurationStores
- .First(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase));
- }
- }
- }
|