public void TestReflect1() { using (var stream = new MemoryStream()) { using (var packer = PluginPacker.Create(stream, true)) { var builder = new PluginBuilder("Kittyfisto", "UniquePluginId", "My very own plugin", "Simon", "http://google.com", "get of my lawn"); builder.ImplementInterface <ILogEntryParserPlugin>("Plugin.FileFormatPlugin"); builder.Save(); packer.AddPluginAssembly(builder.FileName); } stream.Position = 0; _filesystem.Write(Path.Combine(Constants.PluginPath, "Kittyfisto.UniquePluginId.2.0.tvp"), stream); using (var loader = new PluginArchiveLoader(_filesystem, Constants.PluginPath)) { loader.Plugins.Should().HaveCount(1, "because one plugin should've been loaded"); var description = loader.Plugins.First(); description.Should().NotBeNull(); description.Id.Should().Be(new PluginId("Kittyfisto.UniquePluginId")); description.Name.Should().Be("My very own plugin"); description.Version.Should().Be(new Version(0, 0, 0), "because the plugin version should default to 0.0.0 when none has been specified"); description.Author.Should().Be("Simon"); description.Website.Should().Be(new Uri("http://google.com")); description.Description.Should().Be("get of my lawn"); } } }
public void TestReflect1() { using (var stream = new MemoryStream()) { using (var packer = PluginPacker.Create(stream, true)) { var builder = new PluginBuilder("Kittyfisto", "UniquePluginId", "My very own plugin", "Simon", "http://google.com", "get of my lawn"); builder.ImplementInterface <IFileFormatPlugin>("Plugin.FileFormatPlugin"); builder.Save(); packer.AddPluginAssembly(builder.FileName); } stream.Position = 0; using (var loader = new PluginArchiveLoader(null)) { var description = loader.ReflectPlugin(stream, true); description.Should().NotBeNull(); description.Id.Should().Be(new PluginId("Kittyfisto.UniquePluginId")); description.Name.Should().Be("My very own plugin"); description.Version.Should().Be(new Version(0, 0, 0), "because the plugin version should default to 0.0.0 when none has been specified"); description.Author.Should().Be("Simon"); description.Website.Should().Be(new Uri("http://google.com")); description.Description.Should().Be("get of my lawn"); } } }
public void TestLoadAllOfType1() { using (var stream = new MemoryStream()) { using (var packer = PluginPacker.Create(stream, true)) { var builder = new PluginBuilder("Kittyfisto", "SomePlugin", "none of your business", "get of my lawn"); builder.ImplementInterface <ILogEntryParserPlugin>("Plugin.FileFormatPlugin"); builder.Save(); packer.AddPluginAssembly(builder.FileName); } stream.Position = 0; _filesystem.Write(Path.Combine(Constants.PluginPath, "Kittyfisto.SomePlugin.1.tvp"), stream); using (var loader = new PluginArchiveLoader(_filesystem, Constants.PluginPath)) { var plugins = loader.LoadAllOfType <ILogEntryParserPlugin>()?.ToList(); plugins.Should().NotBeNull(); plugins.Should().HaveCount(1); plugins[0].Should().NotBeNull(); plugins[0].GetType().FullName.Should().Be("Plugin.FileFormatPlugin"); } } }
public void TestLoadAllOfTypeWithDescription() { using (var stream = new MemoryStream()) { using (var packer = PluginPacker.Create(stream, true)) { var builder = new PluginBuilder("Kittyfisto", "Simon", "none of your business", "get of my lawn"); builder.ImplementInterface <ILogEntryParserPlugin>("Plugin.FileFormatPlugin"); builder.Save(); packer.AddPluginAssembly(builder.FileName); } stream.Position = 0; var path = Path.Combine(Constants.PluginPath, "Kittyfisto.Simon.1.0.tvp"); _filesystem.WriteAllBytes(path, stream.ToArray()); using (var loader = new PluginArchiveLoader(_filesystem, Constants.PluginPath)) { var pluginsWithDescription = loader.LoadAllOfTypeWithDescription <ILogEntryParserPlugin>(); pluginsWithDescription.Should().HaveCount(1, "because we've added one plugin which implements the IFileFormatPlugin interface"); var description = pluginsWithDescription[0].Description; description.Should().NotBeNull(); description.Id.Should().Be(new PluginId("Kittyfisto.Simon")); description.Author.Should().Be("get of my lawn"); } } }
public void TestLoadAllOfType1() { using (var stream = new MemoryStream()) { using (var packer = PluginPacker.Create(stream, true)) { var builder = new PluginBuilder("Kittyfisto", "SomePlugin", "none of your business", "get of my lawn"); builder.ImplementInterface <IFileFormatPlugin>("Plugin.FileFormatPlugin"); builder.Save(); packer.AddPluginAssembly(builder.FileName); } stream.Position = 0; using (var loader = new PluginArchiveLoader(null)) { var description = loader.ReflectPlugin(stream, true); var plugins = loader.LoadAllOfType <IFileFormatPlugin>()?.ToList(); plugins.Should().NotBeNull(); plugins.Should().HaveCount(1); plugins[0].Should().NotBeNull(); plugins[0].GetType().FullName.Should().Be("Plugin.FileFormatPlugin"); } } }
public void TestUsePluginIdFromArchive() { CreatePlugin <ILogEntryParserPlugin>(new PluginId("Kittyfisto.Simon"), new Version(4, 3, 2), fakeId: new PluginId("Another.Plugin"), fakeVersion: new Version(2, 5, 42, 421)); CreatePlugin <ILogEntryParserPlugin>(new PluginId("Another.Plugin"), new Version(2, 4, 12)); using (var loader = new PluginArchiveLoader(_filesystem, Constants.PluginPath)) { var pluginsWithDescription = loader.LoadAllOfTypeWithDescription <ILogEntryParserPlugin>(); pluginsWithDescription.Should().HaveCount(2, "because there a two different plugins implementing that interface"); var plugin1 = pluginsWithDescription.FirstOrDefault(x => x.Description.Id == new PluginId("Another.Plugin")); plugin1.Should().NotBeNull(); plugin1.Description.Version.Should().Be(new Version(2, 4, 12)); var plugin2 = pluginsWithDescription.FirstOrDefault(x => x.Description.Id == new PluginId("Kittyfisto.Simon")); plugin2.Should().NotBeNull(); plugin2.Description.Version.Should().Be(new Version(4, 3, 2)); } }
public void TestReflectTwoPluginImplementations() { var stream = new MemoryStream(); using (var packer = PluginPacker.Create(stream, true)) { var builder = new PluginBuilder("Kittyfisto", "UniquePluginId", "MyAwesomePlugin"); builder.ImplementInterface <ILogEntryParserPlugin>("A"); builder.ImplementInterface <ILogEntryParserPlugin>("B"); builder.Save(); packer.AddPluginAssembly(builder.FileName); } stream.Position = 0; _filesystem.Write(Path.Combine(Constants.PluginPath, "Kittyfisto.UniquePluginId.2.0.tvp"), stream); using (var loader = new PluginArchiveLoader(_filesystem, Constants.PluginPath)) { loader.Plugins.Should().HaveCount(1, "because one plugin should've been loaded"); var description = loader.Plugins.First(); description.PluginImplementations.Should().HaveCount(2, "because we've implemented the IFileFormatPlugin twice"); description.PluginImplementations[0].InterfaceType.Should().Be <ILogEntryParserPlugin>(); description.PluginImplementations[0].FullTypeName.Should().Be("A"); description.PluginImplementations[1].InterfaceType.Should().Be <ILogEntryParserPlugin>(); description.PluginImplementations[1].FullTypeName.Should().Be("B"); } }
public void TestLoadDifferentVersions() { CreatePlugin("Kittyfisto", "Foobar", new Version(1, 0)); CreatePlugin("Kittyfisto", "Foobar", new Version(1, 1)); using (var loader = new PluginArchiveLoader(_filesystem, Constants.PluginPath)) { loader.Plugins.Should().HaveCount(1); loader.Plugins.First().Version.Should().Be(new Version(1, 1)); var plugins = loader.LoadAllOfType <ILogEntryParserPlugin>(); plugins.Should().HaveCount(1); } }
public void TestGetPluginStatusForNonPlugin() { using (var loader = new PluginArchiveLoader(_filesystem, Constants.PluginPath)) { var status = loader.GetStatus(null); status.Should().NotBeNull(); status.IsInstalled.Should().BeFalse(); status.IsLoaded.Should().BeFalse(); status = loader.GetStatus(new PluginId("dawawd")); status.Should().NotBeNull(); status.IsInstalled.Should().BeFalse(); status.IsLoaded.Should().BeFalse(); } }
public void TestLoadDifferentVersions() { var plugin1 = CreatePlugin("Kittyfisto", "Foobar", new Version(1, 0)); var plugin2 = CreatePlugin("Kittyfisto", "Foobar", new Version(1, 1)); using (var loader = new PluginArchiveLoader(null)) { loader.ReflectPlugin(plugin1); loader.ReflectPlugin(plugin2); loader.Plugins.Should().HaveCount(1); loader.Plugins.First().Version.Should().Be(new Version(1, 1)); var plugins = loader.LoadAllOfType <IFileFormatPlugin>(); plugins.Should().HaveCount(1); } }
public void TestGetPluginStatusForInstalledPlugin() { using (var stream = new MemoryStream()) { CreatePlugin(stream); using (var loader = new PluginArchiveLoader(null)) { var description = loader.ReflectPlugin(stream, true); var status = loader.GetStatus(description); status.Should().NotBeNull(); status.IsInstalled.Should().BeTrue("because we've just installed that plugin"); status.IsLoaded.Should().BeFalse("because we haven't tried to load the plugin just yet"); status.LoadException.Should().BeNull("because we haven't tried to load the plugin just yet"); } } }
public void TestGetPluginStatusForNonPlugin() { using (var loader = new PluginArchiveLoader(null)) { var status = loader.GetStatus(null); status.Should().NotBeNull(); status.IsInstalled.Should().BeFalse(); status.IsLoaded.Should().BeFalse(); var description = new Mock <IPluginDescription>(); status = loader.GetStatus(description.Object); status.Should().NotBeNull(); status.IsInstalled.Should().BeFalse(); status.IsLoaded.Should().BeFalse(); } }
public void TestReflect2() { using (var loader = new PluginArchiveLoader(null)) { var description = loader.ReflectPlugin("C:\\BrokenPlugin.1.0.2.4.tvp"); description.Should().NotBeNull(); description.Author.Should().BeNull("because the author cannot be known"); description.Description.Should().BeNull("because we couldn't extract a description from the plugin"); description.FilePath.Should().Be("C:\\BrokenPlugin.1.0.2.4.tvp"); description.Id.Should().Be(new PluginId("BrokenPlugin"), "because the id should've been extracted from the path"); description.Error.Should().NotBeNull("because the plugin couldn't be loaded"); description.Plugins.Should().NotBeNull(); description.Plugins.Should().BeEmpty(); description.Version.Should().Be(new Version(1, 0, 2, 4), "because the version should've been extracted from the path"); description.Icon.Should().BeNull(); description.Website.Should().BeNull(); } }
public void TestGetPluginStatusForInstalledPlugin() { using (var stream = new MemoryStream()) { var id = CreatePlugin(stream); _filesystem.Write(Path.Combine(Constants.PluginPath, $"{id}.2.tvp"), stream); using (var loader = new PluginArchiveLoader(_filesystem, Constants.PluginPath)) { loader.Plugins.Should().HaveCount(1, "because one plugin should've been loaded"); var status = loader.GetStatus(id); status.Should().NotBeNull(); status.IsInstalled.Should().BeTrue("because we've just installed that plugin"); status.IsLoaded.Should().BeTrue("because we successfully loaded the plugin"); status.LoadException.Should().BeNull("because we successfully loaded the plugin"); } } }
private static IPluginLoader CreatePluginSystem(PluginArchiveLoader pluginScanner) { // Currently, we deploy some well known "plugins" via the installer and they're // not available as *.tvp files just yet (which means the PluginArchiveLoader won't find them). // Therefore we register those at a PluginRegistry. var wellKnownPlugins = LoadWellKnownPlugins(); // Even though we're dealing with the limitation above, the rest of the application should not need // to care, which is why we make both of those types of plugin accessible from one loader var pluginLoader = new AggregatedPluginLoader(pluginScanner, wellKnownPlugins); // Last but not least, the PluginArchiveLoader doesn't cache anything which means // that multiple Load requests would result in the same plugin being loaded many times. // we don't want that (unnecessary work, waste of CPU time, etc..), so that's why there's a cache. var pluginCache = new PluginCache(pluginLoader); return(pluginCache); }
private static int TestLoadPlugin(string pluginToLoad, string pluginInterfaceToLoad) { InstallConsoleLogger(); var pluginInterface = typeof(IPlugin).Assembly.GetType(pluginInterfaceToLoad); if (pluginToLoad.EndsWith(".tvp", StringComparison.InvariantCultureIgnoreCase)) { var taskScheduler = new DefaultTaskScheduler(); var filesystem = new Filesystem(taskScheduler); using (var loader = new PluginArchiveLoader(filesystem)) { var group = loader.OpenPlugin(pluginToLoad); group.Load(); if (!group.Status.IsLoaded) { return(-1); } var plugins = group.LoadAllOfType(pluginInterface); if (plugins.Count == 0) { Log.ErrorFormat("The plugin '{0}' doesn't appear to implement '{1}' or there was a problem loading it", pluginToLoad, pluginInterfaceToLoad); return(-2); } if (!group.TryLoadAllTypes()) { return(-3); } return(0); } } else { throw new NotImplementedException(); } }
public void TestReflect2() { var path = Path.Combine(Constants.PluginPath, "BrokenPlugin.1.0.2.4.tvp"); _filesystem.CreateFile(path); using (var loader = new PluginArchiveLoader(_filesystem, Constants.PluginPath)) { loader.Plugins.Should().HaveCount(1, "because we've created one plugin"); var description = loader.Plugins.First(); description.Should().NotBeNull(); description.Author.Should().BeNull("because the author cannot be known"); description.Description.Should().BeNull("because we couldn't extract a description from the plugin"); description.FilePath.Should().Be(path); description.Id.Should().Be(new PluginId("BrokenPlugin"), "because the id should've been extracted from the path"); description.Error.Should().NotBeNull("because the plugin couldn't be loaded"); description.PluginImplementations.Should().NotBeNull(); description.PluginImplementations.Should().BeEmpty(); description.Version.Should().Be(new Version(1, 0, 2, 4), "because the version should've been extracted from the path"); description.Icon.Should().BeNull(); description.Website.Should().BeNull(); } }
public void TestLoad1() { using (var stream = new MemoryStream()) { using (var packer = PluginPacker.Create(stream, true)) { var builder = new PluginBuilder("Kittyfisto", "Simon", "none of your business", "get of my lawn"); builder.ImplementInterface <IFileFormatPlugin>("Plugin.FileFormatPlugin"); builder.Save(); packer.AddPluginAssembly(builder.FileName); } stream.Position = 0; using (var loader = new PluginArchiveLoader(null)) { var description = loader.ReflectPlugin(stream, true); var plugin = loader.Load <IFileFormatPlugin>(description); plugin.Should().NotBeNull(); } } }
public void TestIgnoreIdenticalPlugin() { var id = new PluginId("Kittyfisto.Simon"); var version = new Version(4, 3, 2); CreatePlugin <ILogEntryParserPlugin>(Constants.PluginPath, id, version); CreatePlugin <ILogEntryParserPlugin>(Constants.DownloadedPluginsPath, id, version); using (var loader = new PluginArchiveLoader(_filesystem, new [] { Constants.PluginPath, Constants.DownloadedPluginsPath })) { var pluginsWithDescription = loader.LoadAllOfTypeWithDescription <ILogEntryParserPlugin>(); pluginsWithDescription.Should().HaveCount(1, "because only one instance of that plugin should've been loaded"); var plugin1 = pluginsWithDescription.FirstOrDefault(x => x.Description.Id == new PluginId("Kittyfisto.Simon")); plugin1.Should().NotBeNull(); plugin1.Description.Version.Should().Be(new Version(4, 3, 2)); } }
private static int StartInternal(SingleApplicationHelper.IMutex mutex, string[] args) { InstallExceptionHandlers(); Log.InfoFormat("Starting tailviewer..."); Log.InfoFormat("Commandline arguments: {0}", string.Join(" ", args)); LogEnvironment(); ApplicationSettings settings = ApplicationSettings.Create(); settings.Restore(out var neededPatching); if (neededPatching) { // TODO: Save settings right again to complete the upgrade // (maybe we should preserve an old version) } var actionCenter = new ActionCenter(); using (var taskScheduler = new DefaultTaskScheduler()) using (var serialTaskScheduler = new SerialTaskScheduler()) { var filesystem = new Filesystem(serialTaskScheduler); using (var pluginArchiveLoader = new PluginArchiveLoader(filesystem, Constants.PluginPath)) { var pluginSystem = CreatePluginSystem(pluginArchiveLoader); var fileFormatPlugins = pluginSystem.LoadAllOfType <IFileFormatPlugin>(); var logFileFactory = new PluginLogFileFactory(taskScheduler, fileFormatPlugins); using (var dataSources = new DataSources(logFileFactory, taskScheduler, settings.DataSources)) using (var updater = new AutoUpdater(actionCenter, settings.AutoUpdate)) using (var logAnalyserEngine = new LogAnalyserEngine(taskScheduler, pluginSystem)) using (var dataSourceAnalyserEngine = new DataSourceAnalyserEngine(taskScheduler, logAnalyserEngine, pluginSystem)) using (var analysisStorage = new AnalysisStorage(taskScheduler, filesystem, dataSourceAnalyserEngine, CreateTypeFactory(pluginSystem))) { var arguments = ArgumentParser.TryParse(args); if (arguments.FileToOpen != null) { if (File.Exists(arguments.FileToOpen)) { // Not only do we want to add this file to the list of data sources, // but we also want to select it so the user can view it immediately, regardless // of what was selected previously. var dataSource = dataSources.AddDataSource(arguments.FileToOpen); settings.DataSources.SelectedItem = dataSource.Id; } else { Log.ErrorFormat("File '{0}' does not exist, won't open it!", arguments.FileToOpen); } } if (settings.AutoUpdate.CheckForUpdates) { // Our initial check for updates is not due to a user action // and therefore we don't need to show a notification when the // application is up-to-date. updater.CheckForUpdates(addNotificationWhenUpToDate: false); } var quickFilters = new QuickFilters(settings.QuickFilters); actionCenter.Add(Build.Current); actionCenter.Add(Change.Merge(Changelog.MostRecentPatches)); var application = new App(); var dispatcher = Dispatcher.CurrentDispatcher; var uiDispatcher = new UiDispatcher(dispatcher); dispatcher.UnhandledException += actionCenter.ReportUnhandledException; TaskScheduler.UnobservedTaskException += actionCenter.ReportUnhandledException; var window = new MainWindow(settings) { DataContext = new MainWindowViewModel(settings, dataSources, quickFilters, actionCenter, updater, taskScheduler, analysisStorage, uiDispatcher, pluginSystem) }; settings.MainWindow.RestoreTo(window); window.Show(); mutex.SetListener(window); return(application.Run()); } } } }
private static int StartApplication(SingleApplicationHelper.IMutex mutex, string fileToOpen, Stopwatch stopwatch) { ApplicationSettings settings = ApplicationSettings.Create(); settings.Restore(out var neededPatching); settings.AllowSave = false; //< We will allow saving once the app is fully booted if (neededPatching) { // TODO: Save settings right again to complete the upgrade // (maybe we should preserve an old version) } var bookmarks = Bookmarks.Create(); bookmarks.Restore(); var services = new ServiceContainer(); services.RegisterInstance <ILogFileSettings>(settings.LogFile); var actionCenter = new ActionCenter(); using (var taskScheduler = new DefaultTaskScheduler()) using (var serialTaskScheduler = new SerialTaskScheduler()) { services.RegisterInstance <ITaskScheduler>(taskScheduler); services.RegisterInstance <ISerialTaskScheduler>(serialTaskScheduler); var navigationService = new NavigationService(); services.RegisterInstance <INavigationService>(navigationService); var filesystem = new Filesystem(taskScheduler); services.RegisterInstance <IFilesystem>(filesystem); using (var pluginArchiveLoader = new PluginArchiveLoader(filesystem, Constants.PluginPath, Constants.DownloadedPluginsPath)) { var pluginUpdater = new PluginUpdater(pluginArchiveLoader); services.RegisterInstance <IPluginUpdater>(pluginUpdater); var pluginSystem = CreatePluginSystem(pluginArchiveLoader); services.RegisterInstance <IPluginLoader>(pluginSystem); var logFileFormatRegistry = new LogFileFormatRegistry(pluginSystem, settings.CustomFormats); services.RegisterInstance <ILogFileFormatRepository>(logFileFormatRegistry); services.RegisterInstance <ILogFileFormatRegistry>(logFileFormatRegistry); var logFileFormatMatcher = new LogFileFormatMatcher(services); services.RegisterInstance <ILogFileFormatMatcher>(logFileFormatMatcher); var textLogFileParserPlugin = new LogEntryParserFactory(services); services.RegisterInstance <ILogEntryParserPlugin>(textLogFileParserPlugin); var propertyPresenter = new PropertyPresenterRegistry(pluginSystem); services.RegisterInstance <IPropertyPresenterPlugin>(propertyPresenter); var fileLogSourceFactory = new StreamingTextLogSourceFactory(filesystem, taskScheduler); services.RegisterInstance <IRawFileLogSourceFactory>(fileLogSourceFactory); var parsingLogSourceFactory = new ParsingLogSourceFactory(services); services.RegisterInstance <ILogSourceParserPlugin>(parsingLogSourceFactory); var customDataSourcePlugins = pluginSystem.LoadAllOfTypeWithDescription <ICustomDataSourcePlugin>(); var logFileFactory = new PluginLogSourceFactory(services, customDataSourcePlugins); using (var dataSources = new DataSources(logFileFactory, taskScheduler, filesystem, settings.DataSources, bookmarks)) using (var updater = new AutoUpdater(actionCenter, settings.AutoUpdate)) { if (fileToOpen != null) { if (File.Exists(fileToOpen)) { // Not only do we want to add this file to the list of data sources, // but we also want to select it so the user can view it immediately, regardless // of what was selected previously. var dataSource = dataSources.AddFile(fileToOpen); settings.DataSources.SelectedItem = dataSource.Id; } else { Log.ErrorFormat("File '{0}' does not exist, won't open it!", fileToOpen); } } if (settings.AutoUpdate.CheckForUpdates) { // Our initial check for updates is not due to a user action // and therefore we don't need to show a notification when the // application is up-to-date. updater.CheckForUpdates(addNotificationWhenUpToDate: false); } var quickFilters = new QuickFilters(settings.QuickFilters); var highlighters = new HighlighterCollection(); services.RegisterInstance <IHighlighters>(highlighters); actionCenter.Add(Build.Current); actionCenter.Add(Change.Merge(Changelog.MostRecentPatches)); var application = new App(); var dispatcher = Dispatcher.CurrentDispatcher; var uiDispatcher = new UiDispatcher(dispatcher); services.RegisterInstance <IDispatcher>(uiDispatcher); dispatcher.UnhandledException += actionCenter.ReportUnhandledException; TaskScheduler.UnobservedTaskException += actionCenter.ReportUnhandledException; var windowViewModel = new MainWindowViewModel(services, settings, dataSources, quickFilters, actionCenter, updater); navigationService.MainWindow = windowViewModel; var window = new MainWindow(settings, windowViewModel); settings.MainWindow.ClipToBounds(Desktop.Current); settings.MainWindow.RestoreTo(window); settings.AllowSave = true; stopwatch.Stop(); Log.InfoFormat("Tailviewer started (took {0}ms), showing window...", stopwatch.ElapsedMilliseconds); window.Show(); mutex?.SetListener(window); return(application.Run()); } } } }
public void TestExtractIdAndVersion1() { PluginArchiveLoader.ExtractIdAndVersion("SamplePlugin.1.2.3.tvp", out var id, out var version); id.Should().Be(new PluginId("SamplePlugin")); version.Should().Be(new Version(1, 2, 3)); }
public void TestExtractIdAndVersion2() { PluginArchiveLoader.ExtractIdAndVersion("Tailviewer.BrokenPlugin.3.2.tvp", out var id, out var version); id.Should().Be(new PluginId("Tailviewer.BrokenPlugin")); version.Should().Be(new Version(3, 2)); }