| | 1 | | #nullable disable |
| | 2 | | #pragma warning disable SA1649 // File name should match first type name |
| | 3 | |
|
| | 4 | | using System; |
| | 5 | | using System.IO; |
| | 6 | | using System.Runtime.InteropServices; |
| | 7 | | using MediaBrowser.Common.Configuration; |
| | 8 | | using MediaBrowser.Model.Plugins; |
| | 9 | | using MediaBrowser.Model.Serialization; |
| | 10 | |
|
| | 11 | | namespace MediaBrowser.Common.Plugins |
| | 12 | | { |
| | 13 | | /// <summary> |
| | 14 | | /// Provides a common base class for all plugins. |
| | 15 | | /// </summary> |
| | 16 | | /// <typeparam name="TConfigurationType">The type of the T configuration type.</typeparam> |
| | 17 | | public abstract class BasePlugin<TConfigurationType> : BasePlugin, IHasPluginConfiguration |
| | 18 | | where TConfigurationType : BasePluginConfiguration |
| | 19 | | { |
| | 20 | | /// <summary> |
| | 21 | | /// The configuration sync lock. |
| | 22 | | /// </summary> |
| 154 | 23 | | private readonly object _configurationSyncLock = new object(); |
| | 24 | |
|
| | 25 | | /// <summary> |
| | 26 | | /// The configuration save lock. |
| | 27 | | /// </summary> |
| 154 | 28 | | private readonly object _configurationSaveLock = new object(); |
| | 29 | |
|
| | 30 | | /// <summary> |
| | 31 | | /// The configuration. |
| | 32 | | /// </summary> |
| | 33 | | private TConfigurationType _configuration; |
| | 34 | |
|
| | 35 | | /// <summary> |
| | 36 | | /// Initializes a new instance of the <see cref="BasePlugin{TConfigurationType}" /> class. |
| | 37 | | /// </summary> |
| | 38 | | /// <param name="applicationPaths">The application paths.</param> |
| | 39 | | /// <param name="xmlSerializer">The XML serializer.</param> |
| 154 | 40 | | protected BasePlugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer) |
| | 41 | | { |
| 154 | 42 | | ApplicationPaths = applicationPaths; |
| 154 | 43 | | XmlSerializer = xmlSerializer; |
| | 44 | |
|
| | 45 | | var assembly = GetType().Assembly; |
| 154 | 46 | | var assemblyName = assembly.GetName(); |
| 154 | 47 | | var assemblyFilePath = assembly.Location; |
| | 48 | |
|
| 154 | 49 | | var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFil |
| 154 | 50 | | if (Version is not null && !Directory.Exists(dataFolderPath)) |
| | 51 | | { |
| | 52 | | // Try again with the version number appended to the folder name. |
| 0 | 53 | | dataFolderPath += "_" + Version; |
| | 54 | | } |
| | 55 | |
|
| 154 | 56 | | SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version); |
| | 57 | |
|
| 154 | 58 | | var idAttributes = assembly.GetCustomAttributes(typeof(GuidAttribute), true); |
| 154 | 59 | | if (idAttributes.Length > 0) |
| | 60 | | { |
| 0 | 61 | | var attribute = (GuidAttribute)idAttributes[0]; |
| 0 | 62 | | var assemblyId = new Guid(attribute.Value); |
| | 63 | |
|
| 0 | 64 | | SetId(assemblyId); |
| | 65 | | } |
| 154 | 66 | | } |
| | 67 | |
|
| | 68 | | /// <summary> |
| | 69 | | /// Gets the application paths. |
| | 70 | | /// </summary> |
| | 71 | | /// <value>The application paths.</value> |
| | 72 | | protected IApplicationPaths ApplicationPaths { get; private set; } |
| | 73 | |
|
| | 74 | | /// <summary> |
| | 75 | | /// Gets the XML serializer. |
| | 76 | | /// </summary> |
| | 77 | | /// <value>The XML serializer.</value> |
| | 78 | | protected IXmlSerializer XmlSerializer { get; private set; } |
| | 79 | |
|
| | 80 | | /// <summary> |
| | 81 | | /// Gets the type of configuration this plugin uses. |
| | 82 | | /// </summary> |
| | 83 | | /// <value>The type of the configuration.</value> |
| 0 | 84 | | public Type ConfigurationType => typeof(TConfigurationType); |
| | 85 | |
|
| | 86 | | /// <summary> |
| | 87 | | /// Gets or sets the event handler that is triggered when this configuration changes. |
| | 88 | | /// </summary> |
| | 89 | | public EventHandler<BasePluginConfiguration> ConfigurationChanged { get; set; } |
| | 90 | |
|
| | 91 | | /// <summary> |
| | 92 | | /// Gets the name the assembly file. |
| | 93 | | /// </summary> |
| | 94 | | /// <value>The name of the assembly file.</value> |
| 2 | 95 | | protected string AssemblyFileName => Path.GetFileName(AssemblyFilePath); |
| | 96 | |
|
| | 97 | | /// <summary> |
| | 98 | | /// Gets or sets the plugin configuration. |
| | 99 | | /// </summary> |
| | 100 | | /// <value>The configuration.</value> |
| | 101 | | public TConfigurationType Configuration |
| | 102 | | { |
| | 103 | | get |
| | 104 | | { |
| | 105 | | // Lazy load |
| 110 | 106 | | if (_configuration is null) |
| | 107 | | { |
| 44 | 108 | | lock (_configurationSyncLock) |
| | 109 | | { |
| 44 | 110 | | _configuration ??= LoadConfiguration(); |
| 44 | 111 | | } |
| | 112 | | } |
| | 113 | |
|
| 110 | 114 | | return _configuration; |
| | 115 | | } |
| | 116 | |
|
| 0 | 117 | | protected set => _configuration = value; |
| | 118 | | } |
| | 119 | |
|
| | 120 | | /// <summary> |
| | 121 | | /// Gets the name of the configuration file. Subclasses should override. |
| | 122 | | /// </summary> |
| | 123 | | /// <value>The name of the configuration file.</value> |
| 2 | 124 | | public virtual string ConfigurationFileName => Path.ChangeExtension(AssemblyFileName, ".xml"); |
| | 125 | |
|
| | 126 | | /// <summary> |
| | 127 | | /// Gets the full path to the configuration file. |
| | 128 | | /// </summary> |
| | 129 | | /// <value>The configuration file path.</value> |
| 132 | 130 | | public string ConfigurationFilePath => Path.Combine(ApplicationPaths.PluginConfigurationsPath, ConfigurationFile |
| | 131 | |
|
| | 132 | | /// <summary> |
| | 133 | | /// Gets the plugin configuration. |
| | 134 | | /// </summary> |
| | 135 | | /// <value>The configuration.</value> |
| 0 | 136 | | BasePluginConfiguration IHasPluginConfiguration.Configuration => Configuration; |
| | 137 | |
|
| | 138 | | /// <summary> |
| | 139 | | /// Saves the current configuration to the file system. |
| | 140 | | /// </summary> |
| | 141 | | /// <param name="config">Configuration to save.</param> |
| | 142 | | public virtual void SaveConfiguration(TConfigurationType config) |
| | 143 | | { |
| 44 | 144 | | lock (_configurationSaveLock) |
| | 145 | | { |
| 44 | 146 | | var folder = Path.GetDirectoryName(ConfigurationFilePath); |
| 44 | 147 | | if (!Directory.Exists(folder)) |
| | 148 | | { |
| 22 | 149 | | Directory.CreateDirectory(folder); |
| | 150 | | } |
| | 151 | |
|
| 44 | 152 | | XmlSerializer.SerializeToFile(config, ConfigurationFilePath); |
| 44 | 153 | | } |
| 44 | 154 | | } |
| | 155 | |
|
| | 156 | | /// <summary> |
| | 157 | | /// Saves the current configuration to the file system. |
| | 158 | | /// </summary> |
| | 159 | | public virtual void SaveConfiguration() |
| | 160 | | { |
| 0 | 161 | | SaveConfiguration(Configuration); |
| 0 | 162 | | } |
| | 163 | |
|
| | 164 | | /// <inheritdoc /> |
| | 165 | | public virtual void UpdateConfiguration(BasePluginConfiguration configuration) |
| | 166 | | { |
| 0 | 167 | | ArgumentNullException.ThrowIfNull(configuration); |
| | 168 | |
|
| 0 | 169 | | Configuration = (TConfigurationType)configuration; |
| | 170 | |
|
| 0 | 171 | | SaveConfiguration(Configuration); |
| | 172 | |
|
| 0 | 173 | | ConfigurationChanged?.Invoke(this, configuration); |
| 0 | 174 | | } |
| | 175 | |
|
| | 176 | | /// <inheritdoc /> |
| | 177 | | public override PluginInfo GetPluginInfo() |
| | 178 | | { |
| 7 | 179 | | var info = base.GetPluginInfo(); |
| | 180 | |
|
| 7 | 181 | | info.ConfigurationFileName = ConfigurationFileName; |
| | 182 | |
|
| 7 | 183 | | return info; |
| | 184 | | } |
| | 185 | |
|
| | 186 | | private TConfigurationType LoadConfiguration() |
| | 187 | | { |
| 44 | 188 | | var path = ConfigurationFilePath; |
| | 189 | |
|
| | 190 | | try |
| | 191 | | { |
| 44 | 192 | | return (TConfigurationType)XmlSerializer.DeserializeFromFile(typeof(TConfigurationType), path); |
| | 193 | | } |
| 44 | 194 | | catch |
| | 195 | | { |
| 44 | 196 | | var config = (TConfigurationType)Activator.CreateInstance(typeof(TConfigurationType)); |
| 44 | 197 | | SaveConfiguration(config); |
| 44 | 198 | | return config; |
| | 199 | | } |
| 44 | 200 | | } |
| | 201 | | } |
| | 202 | | } |