BaseConfigurationManager.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. using MediaBrowser.Common.Configuration;
  2. using MediaBrowser.Common.Events;
  3. using MediaBrowser.Model.Configuration;
  4. using MediaBrowser.Model.Logging;
  5. using MediaBrowser.Model.Serialization;
  6. using System;
  7. using System.Collections.Concurrent;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Threading;
  12. namespace MediaBrowser.Common.Implementations.Configuration
  13. {
  14. /// <summary>
  15. /// Class BaseConfigurationManager
  16. /// </summary>
  17. public abstract class BaseConfigurationManager : IConfigurationManager
  18. {
  19. /// <summary>
  20. /// Gets the type of the configuration.
  21. /// </summary>
  22. /// <value>The type of the configuration.</value>
  23. protected abstract Type ConfigurationType { get; }
  24. /// <summary>
  25. /// Occurs when [configuration updated].
  26. /// </summary>
  27. public event EventHandler<EventArgs> ConfigurationUpdated;
  28. /// <summary>
  29. /// Occurs when [named configuration updated].
  30. /// </summary>
  31. public event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdated;
  32. /// <summary>
  33. /// Gets the logger.
  34. /// </summary>
  35. /// <value>The logger.</value>
  36. protected ILogger Logger { get; private set; }
  37. /// <summary>
  38. /// Gets the XML serializer.
  39. /// </summary>
  40. /// <value>The XML serializer.</value>
  41. protected IXmlSerializer XmlSerializer { get; private set; }
  42. /// <summary>
  43. /// Gets or sets the application paths.
  44. /// </summary>
  45. /// <value>The application paths.</value>
  46. public IApplicationPaths CommonApplicationPaths { get; private set; }
  47. /// <summary>
  48. /// The _configuration loaded
  49. /// </summary>
  50. private bool _configurationLoaded;
  51. /// <summary>
  52. /// The _configuration sync lock
  53. /// </summary>
  54. private object _configurationSyncLock = new object();
  55. /// <summary>
  56. /// The _configuration
  57. /// </summary>
  58. private BaseApplicationConfiguration _configuration;
  59. /// <summary>
  60. /// Gets the system configuration
  61. /// </summary>
  62. /// <value>The configuration.</value>
  63. public BaseApplicationConfiguration CommonConfiguration
  64. {
  65. get
  66. {
  67. // Lazy load
  68. LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer));
  69. return _configuration;
  70. }
  71. protected set
  72. {
  73. _configuration = value;
  74. _configurationLoaded = value != null;
  75. }
  76. }
  77. private ConfigurationStore[] _configurationStores = {};
  78. private IConfigurationFactory[] _configurationFactories;
  79. /// <summary>
  80. /// Initializes a new instance of the <see cref="BaseConfigurationManager" /> class.
  81. /// </summary>
  82. /// <param name="applicationPaths">The application paths.</param>
  83. /// <param name="logManager">The log manager.</param>
  84. /// <param name="xmlSerializer">The XML serializer.</param>
  85. protected BaseConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer)
  86. {
  87. CommonApplicationPaths = applicationPaths;
  88. XmlSerializer = xmlSerializer;
  89. Logger = logManager.GetLogger(GetType().Name);
  90. UpdateCachePath();
  91. }
  92. public void AddParts(IEnumerable<IConfigurationFactory> factories)
  93. {
  94. _configurationFactories = factories.ToArray();
  95. _configurationStores = _configurationFactories
  96. .SelectMany(i => i.GetConfigurations())
  97. .ToArray();
  98. }
  99. /// <summary>
  100. /// Saves the configuration.
  101. /// </summary>
  102. public void SaveConfiguration()
  103. {
  104. var path = CommonApplicationPaths.SystemConfigurationFilePath;
  105. Directory.CreateDirectory(Path.GetDirectoryName(path));
  106. lock (_configurationSyncLock)
  107. {
  108. XmlSerializer.SerializeToFile(CommonConfiguration, path);
  109. }
  110. OnConfigurationUpdated();
  111. }
  112. /// <summary>
  113. /// Called when [configuration updated].
  114. /// </summary>
  115. protected virtual void OnConfigurationUpdated()
  116. {
  117. UpdateCachePath();
  118. EventHelper.QueueEventIfNotNull(ConfigurationUpdated, this, EventArgs.Empty, Logger);
  119. }
  120. /// <summary>
  121. /// Replaces the configuration.
  122. /// </summary>
  123. /// <param name="newConfiguration">The new configuration.</param>
  124. /// <exception cref="System.ArgumentNullException">newConfiguration</exception>
  125. public virtual void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
  126. {
  127. if (newConfiguration == null)
  128. {
  129. throw new ArgumentNullException("newConfiguration");
  130. }
  131. ValidateCachePath(newConfiguration);
  132. CommonConfiguration = newConfiguration;
  133. SaveConfiguration();
  134. }
  135. /// <summary>
  136. /// Updates the items by name path.
  137. /// </summary>
  138. private void UpdateCachePath()
  139. {
  140. ((BaseApplicationPaths)CommonApplicationPaths).CachePath = string.IsNullOrEmpty(CommonConfiguration.CachePath) ?
  141. null :
  142. CommonConfiguration.CachePath;
  143. }
  144. /// <summary>
  145. /// Replaces the cache path.
  146. /// </summary>
  147. /// <param name="newConfig">The new configuration.</param>
  148. /// <exception cref="System.IO.DirectoryNotFoundException"></exception>
  149. private void ValidateCachePath(BaseApplicationConfiguration newConfig)
  150. {
  151. var newPath = newConfig.CachePath;
  152. if (!string.IsNullOrWhiteSpace(newPath)
  153. && !string.Equals(CommonConfiguration.CachePath ?? string.Empty, newPath))
  154. {
  155. // Validate
  156. if (!Directory.Exists(newPath))
  157. {
  158. throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
  159. }
  160. }
  161. }
  162. private readonly ConcurrentDictionary<string, object> _configurations = new ConcurrentDictionary<string, object>();
  163. private string GetConfigurationFile(string key)
  164. {
  165. return Path.Combine(CommonApplicationPaths.ConfigurationDirectoryPath, key.ToLower() + ".xml");
  166. }
  167. public object GetConfiguration(string key)
  168. {
  169. return _configurations.GetOrAdd(key, k =>
  170. {
  171. var file = GetConfigurationFile(key);
  172. var configurationType = _configurationStores
  173. .First(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase))
  174. .ConfigurationType;
  175. lock (_configurationSyncLock)
  176. {
  177. return ConfigurationHelper.GetXmlConfiguration(configurationType, file, XmlSerializer);
  178. }
  179. });
  180. }
  181. public void SaveConfiguration(string key, object configuration)
  182. {
  183. var configurationType = GetConfigurationType(key);
  184. if (configuration.GetType() != configurationType)
  185. {
  186. throw new ArgumentException("Expected configuration type is " + configurationType.Name);
  187. }
  188. _configurations.AddOrUpdate(key, configuration, (k, v) => configuration);
  189. var path = GetConfigurationFile(key);
  190. Directory.CreateDirectory(Path.GetDirectoryName(path));
  191. lock (_configurationSyncLock)
  192. {
  193. XmlSerializer.SerializeToFile(configuration, path);
  194. }
  195. EventHelper.FireEventIfNotNull(NamedConfigurationUpdated, this, new ConfigurationUpdateEventArgs
  196. {
  197. Key = key,
  198. NewConfiguration = configuration
  199. }, Logger);
  200. }
  201. public Type GetConfigurationType(string key)
  202. {
  203. return _configurationStores
  204. .First(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase))
  205. .ConfigurationType;
  206. }
  207. }
  208. }