using System; using System.IO; using MediaBrowser.Common.Configuration; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; namespace MediaBrowser.Common.Plugins { public abstract class BasePlugin : IPlugin, IPluginAssembly { /// /// Gets the name of the plugin /// /// The name. public abstract string Name { get; } /// /// Gets the description. /// /// The description. public virtual string Description => string.Empty; /// /// Gets the unique id. /// /// The unique id. public virtual Guid Id { get; private set; } /// /// Gets the plugin version /// /// The version. public Version Version { get; private set; } /// /// Gets the path to the assembly file /// /// The assembly file path. public string AssemblyFilePath { get; private set; } /// /// Gets the plugin info. /// /// PluginInfo. public virtual PluginInfo GetPluginInfo() { var info = new PluginInfo { Name = Name, Version = Version.ToString(), Description = Description, Id = Id.ToString() }; return info; } /// /// Called when just before the plugin is uninstalled from the server. /// public virtual void OnUninstalling() { } public void SetAttributes(string assemblyFilePath, string dataFolderPath, Version assemblyVersion) { AssemblyFilePath = assemblyFilePath; DataFolderPath = dataFolderPath; Version = assemblyVersion; } public void SetId(Guid assemblyId) { Id = assemblyId; } /// /// Gets the full path to the data folder, where the plugin can store any miscellaneous files needed /// /// The data folder path. public string DataFolderPath { get; private set; } } /// /// Provides a common base class for all plugins /// /// The type of the T configuration type. public abstract class BasePlugin : BasePlugin, IHasPluginConfiguration where TConfigurationType : BasePluginConfiguration { /// /// Gets the application paths. /// /// The application paths. protected IApplicationPaths ApplicationPaths { get; private set; } /// /// Gets the XML serializer. /// /// The XML serializer. protected IXmlSerializer XmlSerializer { get; private set; } /// /// Gets the type of configuration this plugin uses /// /// The type of the configuration. public Type ConfigurationType => typeof(TConfigurationType); private Action _directoryCreateFn; public void SetStartupInfo(Action directoryCreateFn) { // hack alert, until the .net core transition is complete _directoryCreateFn = directoryCreateFn; } /// /// Gets the name the assembly file /// /// The name of the assembly file. protected string AssemblyFileName => Path.GetFileName(AssemblyFilePath); /// /// The _configuration sync lock /// private readonly object _configurationSyncLock = new object(); /// /// The _configuration /// private TConfigurationType _configuration; /// /// Gets the plugin's configuration /// /// The configuration. public TConfigurationType Configuration { get { // Lazy load if (_configuration == null) { lock (_configurationSyncLock) { if (_configuration == null) { _configuration = LoadConfiguration(); } } } return _configuration; } protected set => _configuration = value; } private TConfigurationType LoadConfiguration() { var path = ConfigurationFilePath; try { return (TConfigurationType)XmlSerializer.DeserializeFromFile(typeof(TConfigurationType), path); } catch { return (TConfigurationType)Activator.CreateInstance(typeof(TConfigurationType)); } } /// /// Gets the name of the configuration file. Subclasses should override /// /// The name of the configuration file. public virtual string ConfigurationFileName => Path.ChangeExtension(AssemblyFileName, ".xml"); /// /// Gets the full path to the configuration file /// /// The configuration file path. public string ConfigurationFilePath => Path.Combine(ApplicationPaths.PluginConfigurationsPath, ConfigurationFileName); /// /// Initializes a new instance of the class. /// /// The application paths. /// The XML serializer. protected BasePlugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer) { ApplicationPaths = applicationPaths; XmlSerializer = xmlSerializer; } /// /// The _save lock /// private readonly object _configurationSaveLock = new object(); /// /// Saves the current configuration to the file system /// public virtual void SaveConfiguration() { lock (_configurationSaveLock) { _directoryCreateFn(Path.GetDirectoryName(ConfigurationFilePath)); XmlSerializer.SerializeToFile(Configuration, ConfigurationFilePath); } } /// /// Completely overwrites the current configuration with a new copy /// Returns true or false indicating success or failure /// /// The configuration. /// configuration public virtual void UpdateConfiguration(BasePluginConfiguration configuration) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } Configuration = (TConfigurationType)configuration; SaveConfiguration(); } /// /// Gets the plugin's configuration /// /// The configuration. BasePluginConfiguration IHasPluginConfiguration.Configuration => Configuration; public override PluginInfo GetPluginInfo() { var info = base.GetPluginInfo(); info.ConfigurationFileName = ConfigurationFileName; return info; } } public interface IPluginAssembly { void SetAttributes(string assemblyFilePath, string dataFolderPath, Version assemblyVersion); void SetId(Guid assemblyId); } }