Beispiel #1
0
        /// <summary>
        /// Sometimes a "file" actually exists as multiple files in a directory.  This method will open a "file" using the given directory.
        /// </summary>
        /// <param name="path">Path of the directory to open</param>
        /// <param name="duplicateFileTypeSelector">Resolves duplicate file type detections</param>
        /// <param name="manager">Instance of the current plugin manager</param>
        /// <returns>An object representing the given directory, or null if no such object could be found</returns>
        /// <exception cref="ArgumentNullException">Thrown if <see cref="file"/>, <paramref name="duplicateDirectoryTypeSelector"/>, or <paramref name="manager"/> is null.</exception>
        public static async Task <object> OpenDirectory(string path, DuplicateMatchSelector duplicateDirectoryTypeSelector, PluginManager manager)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (duplicateDirectoryTypeSelector == null)
            {
                throw new ArgumentNullException(nameof(duplicateDirectoryTypeSelector));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var type = await GetDirectoryType(path, duplicateDirectoryTypeSelector, manager);

            var openers = manager.GetRegisteredObjects <IFileOpener>().Where(x => x.SupportsType(type));

            if (type == null || !openers.Any())
            {
                // Nothing can model the file
                return(null);
            }
            else
            {
                return(await openers.OrderBy(x => x.GetUsagePriority(type)).First().OpenFile(type, path, manager.CurrentFileSystem));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Using the given file, auto-detects the file type and creates an instance of an appropriate object to model it.
        /// If no such class could be found, will return the original file
        /// </summary>
        /// <param name="file">The file for which to find a better class</param>
        /// <param name="duplicateFileTypeSelector">Resolves duplicate file type detections</param>
        /// <param name="manager">Instance of the current plugin manager</param>
        /// <returns>An object that represents the given file, or <paramref name="file"/> if no such class could be found.</returns>
        /// <exception cref="ArgumentNullException">Thrown if <see cref="file"/>, <paramref name="duplicateFileTypeSelector"/>, or <paramref name="manager"/> is null.</exception>
        public static async Task <object> OpenFile(GenericFile file, DuplicateMatchSelector duplicateFileTypeSelector, PluginManager manager)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            if (duplicateFileTypeSelector == null)
            {
                throw new ArgumentNullException(nameof(duplicateFileTypeSelector));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var type = await GetFileType(file, duplicateFileTypeSelector, manager);

            var fileOpeners        = manager.GetRegisteredObjects <IFileOpener>().Where(x => x.SupportsType(type));
            var genericFileOpeners = manager.GetRegisteredObjects <IFileFromGenericFileOpener>().Where(x => x.SupportsType(type));

            if (type == null
                ||
                !(fileOpeners.Any() || genericFileOpeners.Any())
                )
            {
                // Nothing can model the file
                // Re-open GenericFile so it's not readonly
                var newFile = new GenericFile();
                await newFile.OpenFile(file.Filename, manager.CurrentFileSystem);

                return(newFile);
            }
            else
            {
                var openers = new List <IBaseFileOpener>();
                openers.AddRange(fileOpeners);
                openers.AddRange(genericFileOpeners);
                var fileOpener = openers.OrderByDescending(x => x.GetUsagePriority(type)).First();
                if (fileOpener is IFileOpener fromFileOpener)
                {
                    return(await fromFileOpener.OpenFile(type, file.Filename, manager.CurrentFileSystem));
                }
                else if (fileOpener is IFileFromGenericFileOpener fromGenericFileOpener)
                {
                    return(await fromGenericFileOpener.OpenFile(type, file));
                }
                else
                {
                    throw new Exception("Unsupported IBaseFileOpener type: " + fileOpener.GetType().Name);
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Gets a type that can represent the given directory
        /// </summary>
        /// <param name="path">Directory for which to detect the type</param>
        /// <param name="duplicateDirectoryTypeSelector">Resolves duplicate file type detections</param>
        /// <param name="manager">Instance of the current plugin manager</param>
        /// <returns>A type that can represent the given file</returns>
        /// <exception cref="ArgumentNullException">Thrown if <see cref="path"/>, <paramref name="duplicateDirectoryTypeSelector"/>, or <paramref name="manager"/> is null.</exception>
        public static async Task <TypeInfo> GetDirectoryType(string path, DuplicateMatchSelector duplicateDirectoryTypeSelector, PluginManager manager)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (duplicateDirectoryTypeSelector == null)
            {
                throw new ArgumentNullException(nameof(duplicateDirectoryTypeSelector));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var resultSetTasks = new List <Task <IEnumerable <FileTypeDetectionResult> > >();

            foreach (var detector in manager.GetRegisteredObjects <IDirectoryTypeDetector>())
            {
                // Start the file type detection
                var detectTask = detector.DetectDirectoryType(path, manager);

                // Add the task to a list of running detection tasks, so there is the option of running them asynchronously.
                resultSetTasks.Add(detectTask);
            }

            var matches = new List <FileTypeDetectionResult>();

            // Merge all results into one list
            foreach (var item in await Task.WhenAll(resultSetTasks))
            {
                matches.AddRange(item);
            }

            return(GetCorrectFileTypeDetectionResult(matches, duplicateDirectoryTypeSelector)?.FileType);
        }
Beispiel #4
0
        /// <summary>
        /// Opens a file, auto-detecting the correct type
        /// </summary>
        /// <param name="path">Path of the file to open</param>
        /// <param name="duplicateFileTypeSelector">Resolves duplicate file type detections</param>
        /// <param name="manager">Instance of the current plugin manager</param>
        /// <returns>An object that represents the file at the given path</returns>
        /// <exception cref="ArgumentNullException">Thrown if <see cref="file"/>, <paramref name="duplicateFileTypeSelector"/>, or <paramref name="manager"/> is null.</exception>
        /// <exception cref="FileNotFoundException">Thrown if no file or directory could be found at the given path</exception>
        public static async Task <object> OpenFile(string path, DuplicateMatchSelector duplicateFileTypeSelector, PluginManager manager)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (duplicateFileTypeSelector == null)
            {
                throw new ArgumentNullException(nameof(duplicateFileTypeSelector));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            if (manager.CurrentFileSystem.FileExists(path))
            {
                using (var file = new GenericFile())
                {
                    file.IsReadOnly = true;
                    await file.OpenFile(path, manager.CurrentFileSystem);

                    return(await OpenFile(file, duplicateFileTypeSelector, manager));
                }
            }
            else if (manager.CurrentFileSystem.DirectoryExists(path))
            {
                return(OpenDirectory(path, duplicateFileTypeSelector, manager));
            }
            else
            {
                throw new FileNotFoundException(Properties.Resources.IO_FileNotFound, path);
            }
        }
Beispiel #5
0
 /// <summary>
 /// Gets the correct file type detection result
 /// </summary>
 /// <param name="results">The results from which to select</param>
 /// <param name="duplicateMatchSelector">A function that can select between duplicate types</param>
 /// <returns>The correct file type detection result, or null if there are no results</returns>
 private static FileTypeDetectionResult GetCorrectFileTypeDetectionResult(IEnumerable <FileTypeDetectionResult> results, DuplicateMatchSelector duplicateMatchSelector)
 {
     if (!results.Any())
     {
         return(null);
     }
     else if (results.Count() == 1)
     {
         return(results.First());
     }
     else
     {
         // Multiple matches exist.  Find the one with the highest chance of being the correct one.
         var maxChance  = results.Max(x => x.MatchChance);
         var topMatches = results.Where(x => x.MatchChance == maxChance);
         if (!topMatches.Any())
         {
             // Nothing matches the maximum.  Should be unreachable.
             throw new Exception("Could not find results that match the maximum.  This exception should have been unreachable and likely indicates an error in implementation.");
         }
         else if (topMatches.Count() == 1)
         {
             return(topMatches.First());
         }
         else
         {
             return(duplicateMatchSelector(topMatches));
         }
     }
 }
Beispiel #6
0
        /// <summary>
        /// Gets a type that can represent the given file
        /// </summary>
        /// <param name="file">File for which to detect the type</param>
        /// <param name="duplicateFileTypeSelector">Resolves duplicate file type detections</param>
        /// <param name="manager">Instance of the current plugin manager</param>
        /// <returns>A type that can represent the given file</returns>
        /// <exception cref="ArgumentNullException">Thrown if <see cref="file"/>, <paramref name="duplicateFileTypeSelector"/>, or <paramref name="manager"/> is null.</exception>
        public static async Task <TypeInfo> GetFileType(GenericFile file, DuplicateMatchSelector duplicateFileTypeSelector, PluginManager manager)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            if (duplicateFileTypeSelector == null)
            {
                throw new ArgumentNullException(nameof(duplicateFileTypeSelector));
            }

            if (manager == null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            var resultSetTasks = new List <Task <IEnumerable <FileTypeDetectionResult> > >();

            foreach (var detector in manager.GetRegisteredObjects <IFileTypeDetector>())
            {
                // Start the file type detection
                var detectTask = Task.Run(async() => {
                    try
                    {
                        return(await detector.DetectFileType(file, manager));
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"Encountered exception when using {detector.GetType().Name} to detect a file type: {ex.ToString()}");
                        return(new FileTypeDetectionResult[] { });
                    }
                });

                // Add the task to a list of running detection tasks, so there is the option of running them asynchronously.
                resultSetTasks.Add(detectTask);

                // However, the file isn't necessarily thread-safe, so if it isn't, only one should be run at any one time
                if (!file.IsThreadSafe)
                {
                    try
                    {
                        await detectTask;
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"Encountered exception when using {detector.GetType().Name} to detect a file type: {ex.ToString()}");
                        continue;
                    }
                }
            }

            var matches = new List <FileTypeDetectionResult>();

            // Merge all results into one list
            foreach (var item in await Task.WhenAll(resultSetTasks))
            {
                matches.AddRange(item);
            }

            return(GetCorrectFileTypeDetectionResult(matches, duplicateFileTypeSelector)?.FileType);
        }