/// <summary> /// Attempts to select a compatible adapter that is capable of identifying files. /// </summary> /// <param name="file">The file to be selected against.</param> /// <returns>Returns a working ILoadFiles plugin or null.</returns> private ILoadFiles SelectAdapter(KoreLoadInfo kli) { // Return an adapter that can Identify, whose extension matches that of our filename and successfully identifies the file. return(PluginLoader.GetAdapters <ILoadFiles>(). Where(x => PluginLoader.GetMetadata <PluginExtensionInfoAttribute>(x).Extension. ToLower().TrimEnd(';').Split(';').Any(s => kli.FileName.ToLower().EndsWith(s.TrimStart('*'))) ).Select(x => { if (x is IMultipleFiles y) { y.FileSystem = kli.FileSystem; } return x; }).FirstOrDefault(adapter => CheckAdapter(adapter, kli))); }
/// <summary> /// Does the actual identification with IIdentifyFiles and checks the availablity of the data stream. /// </summary> /// <param name="adapter">Adapter to identify with.</param> /// <param name="kli">Kore information for identification.</param> /// <returns>Returns if the adapter was capable of identifying the file.</returns> private bool CheckAdapter(ILoadFiles adapter, KoreLoadInfo kli) { if (!(adapter is IIdentifyFiles)) { return(false); } adapter.LeaveOpen = true; kli.FileData.Position = 0; var info = new StreamInfo { FileData = kli.FileData, FileName = kli.FileName }; var res = ((IIdentifyFiles)adapter).Identify(info); if (!kli.FileData.CanRead) { throw new InvalidOperationException($"Plugin with ID '{PluginLoader.GetMetadata<PluginInfoAttribute>(adapter).ID}' closed the stream(s) while identifying the file(s)."); } return(res); }
// TODO: We want to somehow reflect these names and also possibly return a class holding the Type and a DisplayName vs. the plain interface name. /// <summary> /// Load a file using Kore. /// </summary> /// <param name="kli"></param> /// <returns></returns> public KoreFileInfo LoadFile(KoreLoadInfo kli) { if (kli.Adapter == null) { // Select adapter automatically var adapter = SelectAdapter(kli); // Ask the user to select a plugin directly. adapter = adapter ?? SelectAdapterManually(); if (adapter == null) { return(null); } kli.Adapter = adapter; } // Instantiate a new instance of the adapter kli.Adapter = PluginLoader.CreateAdapter <ILoadFiles>(PluginLoader.GetMetadata <PluginInfoAttribute>(kli.Adapter).ID); // Load files(s) kli.FileData.Position = 0; var streamInfo = new StreamInfo { FileData = kli.FileData, FileName = kli.FileName }; try { if (kli.Adapter is IMultipleFiles multiFileAdapter) { multiFileAdapter.FileSystem = kli.FileSystem; } kli.Adapter.LeaveOpen = kli.LeaveOpen; kli.Adapter.Load(streamInfo); } catch (Exception ex) { var pi = PluginLoader.GetMetadata <PluginInfoAttribute>(kli.Adapter); throw new LoadFileException($"The {pi?.Name} plugin failed to load \"{Path.GetFileName(kli.FileName)}\".{Environment.NewLine}{Environment.NewLine}" + $"{ex.Message}{Environment.NewLine}{Environment.NewLine}" + $"{ex.StackTrace}"); } // Check if the stream still follows the LeaveOpen restriction if (!kli.FileData.CanRead && kli.LeaveOpen) { throw new InvalidOperationException($"Plugin with ID {PluginLoader.GetMetadata<PluginInfoAttribute>(kli.Adapter).ID} closed the streams while loading the file."); } // Create a KoreFileInfo to keep track of the now open file. var kfi = new KoreFileInfo { StreamFileInfo = streamInfo, HasChanges = false, Adapter = kli.Adapter }; if (kli.TrackFile) { OpenFiles.Add(kfi); } return(kfi); }