// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // Filename : PluginRegister.cs // Author(s) : Natalia Portillo // // Component : Common types. // // --[ Description ] ---------------------------------------------------------- // // Gets lists of all known plugins. // // --[ License ] -------------------------------------------------------------- // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2023 Natalia Portillo // ****************************************************************************/ using System; using System.Collections.Generic; using System.IO; using System.Linq; using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Interfaces; using Microsoft.Extensions.DependencyInjection; namespace Aaru.CommonTypes; public class PluginRegister { static PluginRegister _instance; /// List of byte addressable image plugins public readonly SortedDictionary ByteAddressableImages; /// List of all filesystem plugins public readonly SortedDictionary Filesystems; /// List of floppy image plugins public readonly SortedDictionary FloppyImages; /// List of all media image plugins public readonly SortedDictionary MediaImages; /// List of read-only filesystem plugins public readonly SortedDictionary ReadOnlyFilesystems; /// List of writable floppy image plugins public readonly SortedDictionary WritableFloppyImages; /// List of writable media image plugins public readonly SortedDictionary WritableImages; IServiceProvider _serviceProvider; IServiceCollection _services; PluginRegister() { Filesystems = new SortedDictionary(); ReadOnlyFilesystems = new SortedDictionary(); MediaImages = new SortedDictionary(); WritableImages = new SortedDictionary(); FloppyImages = new SortedDictionary(); WritableFloppyImages = new SortedDictionary(); ByteAddressableImages = new SortedDictionary(); } /// List of all archive formats public SortedDictionary Archives { get { SortedDictionary archives = new(); foreach(IArchive plugin in _serviceProvider.GetServices()) archives.Add(plugin.Name.ToLower(), plugin); return archives; } } /// List of all partition plugins public SortedDictionary Partitions { get { SortedDictionary partitions = new(); foreach(IPartition plugin in _serviceProvider.GetServices()) partitions.Add(plugin.Name.ToLower(), plugin); return partitions; } } /// List of filter plugins public SortedDictionary Filters { get { SortedDictionary filters = new(); foreach(IFilter plugin in _serviceProvider.GetServices()) filters.Add(plugin.Name.ToLower(), plugin); return filters; } } /// List of checksum plugins public SortedDictionary Checksums { get { SortedDictionary checksums = new(); foreach(IChecksum plugin in _serviceProvider.GetServices()) checksums.Add(plugin.Name.ToLower(), plugin); return checksums; } } /// Gets a singleton with all the known plugins public static PluginRegister Singleton { get { if(_instance != null) return _instance; _instance = new PluginRegister { _services = new ServiceCollection() }; _instance._serviceProvider = _instance._services.BuildServiceProvider(); return _instance; } } /// /// Replaces registered plugins list of this instance with the new ones provided by the providen registrators. /// /// List of plugin registrators as obtained from the assemblies that implement them. public void InitPlugins(IEnumerable registrators) { _services = new ServiceCollection(); foreach(IPluginRegister registrator in registrators) AddPlugins(registrator); _instance._serviceProvider = _instance._services.BuildServiceProvider(); } /// Adds plugins to the central plugin register /// Plugin register void AddPlugins(IPluginRegister pluginRegister) { pluginRegister.RegisterChecksumPlugins(_services); foreach(Type type in pluginRegister.GetAllFilesystemPlugins() ?? Enumerable.Empty()) { if(Activator.CreateInstance(type) is IFilesystem plugin && !Filesystems.ContainsKey(plugin.Name.ToLower())) Filesystems.Add(plugin.Name.ToLower(), type); } pluginRegister.RegisterFilterPlugins(_services); foreach(Type type in pluginRegister.GetAllFloppyImagePlugins() ?? Enumerable.Empty()) { if(Activator.CreateInstance(type) is IFloppyImage plugin && !FloppyImages.ContainsKey(plugin.Name.ToLower())) FloppyImages.Add(plugin.Name.ToLower(), type); } foreach(Type type in pluginRegister.GetAllMediaImagePlugins() ?? Enumerable.Empty()) { if(Activator.CreateInstance(type) is IMediaImage plugin && !MediaImages.ContainsKey(plugin.Name.ToLower())) MediaImages.Add(plugin.Name.ToLower(), type); } pluginRegister.RegisterPartitionPlugins(_services); foreach(Type type in pluginRegister.GetAllReadOnlyFilesystemPlugins() ?? Enumerable.Empty()) { if(Activator.CreateInstance(type) is IReadOnlyFilesystem plugin && !ReadOnlyFilesystems.ContainsKey(plugin.Name.ToLower())) ReadOnlyFilesystems.Add(plugin.Name.ToLower(), type); } foreach(Type type in pluginRegister.GetAllWritableFloppyImagePlugins() ?? Enumerable.Empty()) { if(Activator.CreateInstance(type) is IWritableFloppyImage plugin && !WritableFloppyImages.ContainsKey(plugin.Name.ToLower())) WritableFloppyImages.Add(plugin.Name.ToLower(), type); } foreach(Type type in pluginRegister.GetAllWritableImagePlugins() ?? Enumerable.Empty()) { if(Activator.CreateInstance(type) is IBaseWritableImage plugin && !WritableImages.ContainsKey(plugin.Name.ToLower())) WritableImages.Add(plugin.Name.ToLower(), type); } pluginRegister.RegisterArchivePlugins(_services); foreach(Type type in pluginRegister.GetAllByteAddressablePlugins() ?? Enumerable.Empty()) { if(Activator.CreateInstance(type) is IByteAddressableImage plugin && !ByteAddressableImages.ContainsKey(plugin.Name.ToLower())) ByteAddressableImages.Add(plugin.Name.ToLower(), type); } } /// Gets the filter that allows to read the specified path /// Path /// The filter that allows reading the specified path public IFilter GetFilter(string path) { IFilter noFilter = null; foreach(IFilter filter in Filters.Values) { try { if(filter.Id != new Guid("12345678-AAAA-BBBB-CCCC-123456789000")) { if(!filter.Identify(path)) continue; var foundFilter = (IFilter)filter.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(Array.Empty()); if(foundFilter?.Open(path) == ErrorNumber.NoError) return foundFilter; } else noFilter = filter; } catch(IOException) { // Ignore and continue } } if(!noFilter?.Identify(path) == true) return null; noFilter?.Open(path); return noFilter; } }