public void AddBetterPlugins()
        {
            DiscoverDoneEventArgs lastDiscoverEventArgs = null;

            PluginDiscoverer discoverer = new PluginDiscoverer();

            discoverer.DiscoverDone += (sender, e) => lastDiscoverEventArgs = e;

            TestBase.CopyPluginToTestDir("ServiceA.Old.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(lastDiscoverEventArgs.NewPlugins.Count, Is.EqualTo(1));
            Assert.That(lastDiscoverEventArgs.NewOldPlugins.Count, Is.EqualTo(0));

            IPluginInfo bestVersion = discoverer.FindPlugin(new System.Guid("{12A9FCC0-ECDC-4049-8DBF-8961E49A9EDE}"));

            Assert.That(bestVersion.Version == new Version("1.0.0"));

            TestBase.CopyPluginToTestDir("ServiceA.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(lastDiscoverEventArgs.NewPlugins.Count, Is.EqualTo(0));
            Assert.That(lastDiscoverEventArgs.NewOldPlugins.Count, Is.EqualTo(1));

            IPluginInfo newBestVersion = discoverer.FindPlugin(new System.Guid("{12A9FCC0-ECDC-4049-8DBF-8961E49A9EDE}"));

            Assert.That(newBestVersion.Version == new Version("1.1.0"));

            Assert.That(bestVersion.GetHashCode() == newBestVersion.GetHashCode());
        }
        public void AddRemoveMissingReferences()
        {
            DiscoverDoneEventArgs lastDiscoverEventArgs = null;

            PluginDiscoverer discoverer = new PluginDiscoverer();

            discoverer.DiscoverDone += (sender, e) => lastDiscoverEventArgs = e;

            TestBase.CopyPluginToTestDir("ServiceC.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);
            Assert.That(lastDiscoverEventArgs.NewAssemblies.Count, Is.EqualTo(1));
            IAssemblyInfo pAss = lastDiscoverEventArgs.NewAssemblies[0];

            Assert.That(pAss.HasError, Is.True);
            Assert.That(lastDiscoverEventArgs.NewPlugins.Count, Is.EqualTo(0));
            Assert.That(lastDiscoverEventArgs.NewServices.Count, Is.EqualTo(0));
            Assert.That(lastDiscoverEventArgs.NewDisappearedAssemblies.Count, Is.EqualTo(0));

            TestBase.CopyPluginToTestDir("ServiceC.Model.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);
            Assert.That(lastDiscoverEventArgs.NewPlugins.Count, Is.EqualTo(1));
            Assert.That(lastDiscoverEventArgs.NewServices.Count, Is.EqualTo(1));
            Assert.That(pAss.HasError, Is.False, "The assembly info reference is updated.");

            Assert.That(lastDiscoverEventArgs.ChangedAssemblies.Count, Is.EqualTo(1));
            Assert.That(lastDiscoverEventArgs.ChangedAssemblies[0], Is.SameAs(pAss));

            Assert.That(lastDiscoverEventArgs.NewDisappearedAssemblies.Count, Is.EqualTo(0));
            Assert.That(lastDiscoverEventArgs.DeletedDisappearedAssemblies.Count, Is.EqualTo(0));
        }
        public void AddRemoveAssemblies()
        {
            DiscoverDoneEventArgs lastDiscoverEventArgs = null;

            PluginDiscoverer discoverer = new PluginDiscoverer();

            discoverer.DiscoverDone += (sender, e) => lastDiscoverEventArgs = e;

            // Add 3 assemblies
            TestBase.CopyPluginToTestDir("ServiceA.dll");
            TestBase.CopyPluginToTestDir("ServiceB.dll");
            TestBase.CopyPluginToTestDir("ServiceC.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(lastDiscoverEventArgs.NewAssemblies.Count, Is.EqualTo(3));


            // Remove all assmeblies, add the first two then add a new one.
            TestBase.CleanupTestDir();
            TestBase.CopyPluginToTestDir("ServiceA.dll");
            TestBase.CopyPluginToTestDir("ServiceB.dll");
            TestBase.CopyPluginToTestDir("EditorsOfPlugins.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(lastDiscoverEventArgs.NewAssemblies.Count, Is.EqualTo(1));
            Assert.That(lastDiscoverEventArgs.DeletedAssemblies.Count, Is.EqualTo(1));
        }
        public void AddRemovePluginsAndService()
        {
            DiscoverDoneEventArgs lastDiscoverEventArgs = null;

            PluginDiscoverer discoverer = new PluginDiscoverer();

            discoverer.DiscoverDone += (sender, e) => lastDiscoverEventArgs = e;

            // Add 2 assemblies : 2 plugins & 2 services
            TestBase.CopyPluginToTestDir("ServiceA.dll");
            TestBase.CopyPluginToTestDir("ServiceB.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(lastDiscoverEventArgs.NewPlugins.Count, Is.EqualTo(2));
            Assert.That(lastDiscoverEventArgs.NewServices.Count, Is.EqualTo(2));

            // Clear and add previous plugins, and add a new service
            TestBase.CleanupTestDir();
            TestBase.CopyPluginToTestDir("ServiceA.dll");
            TestBase.CopyPluginToTestDir("ServiceC.Model.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(lastDiscoverEventArgs.NewPlugins.Count, Is.EqualTo(0));
            Assert.That(lastDiscoverEventArgs.NewServices.Count, Is.EqualTo(1));
            Assert.That(lastDiscoverEventArgs.DeletedServices.Count, Is.EqualTo(1));
            Assert.That(lastDiscoverEventArgs.DeletedPlugins.Count, Is.EqualTo(1));
        }
Exemple #5
0
        public void TestRequireConfiguration()
        {
            int passed = 0;

            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir("ServiceA.dll");
            TestBase.CopyPluginToTestDir("ServiceB.dll");
            TestBase.CopyPluginToTestDir("EditorsOfPlugins.dll");
            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(discoverer.Plugins.Count, Is.EqualTo(6));
            foreach (IPluginInfo plugin in discoverer.Plugins)
            {
                if (plugin.PluginId == new Guid("{8BE8C487-4052-46b0-9225-708BC2A1E033}"))    //EditorOfPlugin01
                {
                    Assert.That(plugin.EditorsInfo.Count, Is.EqualTo(1));
                    Assert.That(plugin.EditorsInfo[0].ConfigurationPropertyName == "EditedPluginConfiguration");
                    Assert.IsTrue(plugin.EditorsInfo[0].IsConfigurationPropertyValid);
                    passed++;
                }
                else if (plugin.PluginId == new Guid("{EDA76E35-30C2-449e-817C-91CB24D38763}"))    //EditorOfPlugin02
                {
                    Assert.That(plugin.EditorsInfo.Count, Is.EqualTo(1));
                    Assert.IsTrue(plugin.EditorsInfo[0].IsConfigurationPropertyValid);
                    passed++;
                }
            }

            Assert.That(passed, Is.EqualTo(2));
        }
Exemple #6
0
        public void TestDiscoverOnePlugin()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir( "ServiceA.dll" );

            discoverer.Discover( TestBase.TestFolderDir, true );

            Assert.That( discoverer.AllAssemblies.Count == 1 );
            Assert.That( discoverer.PluginOrServiceAssemblies.Count == 1 );
            Assert.That( discoverer.Plugins.Count == 1 );
            Assert.That( discoverer.Services.Count == 1 );

            //Test methods, events and properties info :
            IReadOnlyCollection<ISimpleEventInfo> events = discoverer.Services.First().EventsInfoCollection;
            IReadOnlyCollection<ISimpleMethodInfo> methods = discoverer.Services.First().MethodsInfoCollection;
            IReadOnlyCollection<ISimplePropertyInfo> properties = discoverer.Services.First().PropertiesInfoCollection;

            Assert.That( events.Count, Is.EqualTo( 1 ) );
            Assert.That( methods.Count, Is.EqualTo( 2 ) );
            Assert.That( properties.Count, Is.EqualTo( 1 ) );

            Assert.That( events.First().Name, Is.EqualTo( "HasStarted" ) );

            Assert.That( methods.First().Name, Is.EqualTo( "Add" ) );
            Assert.That( methods.First().Parameters.Count, Is.EqualTo( 2 ) );
            Assert.That( methods.First().Parameters.First().ParameterName, Is.EqualTo( "a" ) );
            Assert.That( methods.First().Parameters.Last().ParameterName, Is.EqualTo( "b" ) );
            Assert.That( methods.First().ReturnType, Is.EqualTo( "System.Int32" ) );

            Assert.That( properties.First().Name, Is.EqualTo( "HasBeenStarted" ) );
            Assert.That( properties.First().PropertyType, Is.EqualTo( "System.Boolean" ) );
        }
Exemple #7
0
        public void RefExternalNonDynamicService()
        {
            {
                // Missing ServiceC.Model.dll assembly: the interface has no definition.
                PluginDiscoverer discoverer = new PluginDiscoverer();
                TestBase.CopyPluginToTestDir("RefExternalNonDynamicService.dll");

                discoverer.Discover(TestBase.TestFolderDir, true);

                Assert.That(discoverer.AllAssemblies.Count, Is.EqualTo(1));
                Assert.That(discoverer.AllAssemblies.First().HasError, Is.True);

                Assert.That(discoverer.AllPlugins.Count, Is.EqualTo(0));
                Assert.That(discoverer.AllServices.Count, Is.EqualTo(0));
            }
            {
                PluginDiscoverer discoverer = new PluginDiscoverer();
                TestBase.CopyPluginToTestDir("ServiceC.Model.dll");

                discoverer.Discover(TestBase.TestFolderDir, true);

                Assert.That(discoverer.Plugins.Count, Is.EqualTo(2), "There are 2 runnable plugins.");
                Assert.That(discoverer.Plugins.Select(x => x.PublicName).OrderBy(Util.FuncIdentity).SequenceEqual(new[] { "PluginSuccess", "PluginSuccessAlso" }));

                Assert.That(discoverer.AllPlugins.Count, Is.EqualTo(3), "There are 2 runnable plugins and 1 in error.");
                Assert.That(discoverer.AllPlugins.Any(p => p.PublicName == "PluginFailed"));
            }
        }
Exemple #8
0
        public void TestDiscoverOnePlugin()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir("ServiceA.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(discoverer.AllAssemblies.Count == 1);
            Assert.That(discoverer.PluginOrServiceAssemblies.Count == 1);
            Assert.That(discoverer.Plugins.Count == 1);
            Assert.That(discoverer.Services.Count == 1);

            //Test methods, events and properties info :
            IReadOnlyCollection <ISimpleEventInfo>    events     = discoverer.Services.First().EventsInfoCollection;
            IReadOnlyCollection <ISimpleMethodInfo>   methods    = discoverer.Services.First().MethodsInfoCollection;
            IReadOnlyCollection <ISimplePropertyInfo> properties = discoverer.Services.First().PropertiesInfoCollection;

            Assert.That(events.Count, Is.EqualTo(1));
            Assert.That(methods.Count, Is.EqualTo(2));
            Assert.That(properties.Count, Is.EqualTo(1));

            Assert.That(events.First().Name, Is.EqualTo("HasStarted"));

            Assert.That(methods.First().Name, Is.EqualTo("Add"));
            Assert.That(methods.First().Parameters.Count, Is.EqualTo(2));
            Assert.That(methods.First().Parameters.First().ParameterName, Is.EqualTo("a"));
            Assert.That(methods.First().Parameters.Last().ParameterName, Is.EqualTo("b"));
            Assert.That(methods.First().ReturnType, Is.EqualTo("System.Int32"));

            Assert.That(properties.First().Name, Is.EqualTo("HasBeenStarted"));
            Assert.That(properties.First().PropertyType, Is.EqualTo("System.Boolean"));
        }
Exemple #9
0
        public static IReadOnlyCollection <PluginMetadata> DiscoverPlugins()
        {
            var pluginPaths   = GetPluginPaths();
            var pluginLoaders = Bootstrapper.LoadPlugins(pluginPaths);

            return(PluginDiscoverer.Discover(pluginLoaders.Assemblies));
        }
Exemple #10
0
        public void TestDiscoverEditors()
        {
            int nbEditors = 0;

            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir("ServiceA.dll");
            TestBase.CopyPluginToTestDir("ServiceB.dll");
            TestBase.CopyPluginToTestDir("EditorsOfPlugins.dll");
            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(discoverer.AllAssemblies.Count == 3);
            Assert.That(discoverer.PluginOrServiceAssemblies.Count == 3);
            Assert.That(discoverer.Plugins.Count, Is.EqualTo(6));

            foreach (IPluginInfo plugin in discoverer.Plugins)
            {
                nbEditors += plugin.EditorsInfo.Count;
            }

            Assert.That(nbEditors, Is.EqualTo(6));     // 6 because ServiceA get an accessor to its configuration.

            IPluginInfo editorOfTwoPlugins = discoverer.FindPlugin(new Guid("{BC7E641B-E4EE-47f5-833B-0AFFFAA2A683}"));

            Assert.That(editorOfTwoPlugins.EditorsInfo.Any((a) => { return((a.ConfigurationPropertyName == "ConfigPlugin01") && (a.IsConfigurationPropertyValid)); }));
            Assert.That(editorOfTwoPlugins.EditorsInfo.Any((a) => { return((a.ConfigurationPropertyName == "ConfigPlugin02") && (a.IsConfigurationPropertyValid)); }));
        }
        public void AddRemoveEditors()
        {
            DiscoverDoneEventArgs lastDiscoverEventArgs = null;

            PluginDiscoverer discoverer = new PluginDiscoverer();

            discoverer.DiscoverDone += (sender, e) => lastDiscoverEventArgs = e;

            TestBase.CopyPluginToTestDir("ServiceA.dll");
            TestBase.CopyPluginToTestDir("ServiceB.dll");
            TestBase.CopyPluginToTestDir("EditorsOfPlugins.dll");
            discoverer.Discover(TestBase.TestFolderDir, true);
            Assert.That(lastDiscoverEventArgs.NewEditors.Count, Is.EqualTo(6));

            TestBase.CleanupTestDir();
            discoverer.Discover(TestBase.TestFolderDir, true);
            Assert.That(lastDiscoverEventArgs.NewEditors.Count, Is.EqualTo(0));
            Assert.That(lastDiscoverEventArgs.DeletedEditors.Count, Is.EqualTo(6));
        }
Exemple #12
0
        public void DiscoverMultiServicesPlugin()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir("ServiceD.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(discoverer.AllPlugins.Count == 1);
            Assert.That(discoverer.AllPlugins.ElementAt(0).HasError);
        }
Exemple #13
0
        public PluginDiscoverer GetFooBarPluginDiscoverer(String ckAssemblieFolder)
        {
            PluginDiscoverer discoverer   = new PluginDiscoverer();
            bool             discoverDone = false;

            discoverer.DiscoverDone += (object sender, DiscoverDoneEventArgs e) => discoverDone = true;

            ckAssemblieFolder = ckAssemblieFolder.Replace('|', System.IO.Path.DirectorySeparatorChar);
            discoverer.Discover(new DirectoryInfo(ckAssemblieFolder), true);

            Contract.Assert(discoverDone);
            return(discoverer);
        }
        public void Build(BuildContext context)
        {
            DirectoryCopy(Path.GetDirectoryName(context.PathToFunctionAssembly), context.PathToTargetFolder, true, true);
            DirectoryCopy(Path.GetDirectoryName(context.PathToFunctionEntryAssembly), context.PathToTargetFolder, true, false);

            var pathToFunctionAssembly      = Path.Combine(context.PathToTargetFolder, Path.GetFileName(context.PathToFunctionAssembly));
            var pathToFunctionEntryAssembly = Path.Combine(context.PathToTargetFolder, Path.GetFileName(context.PathToFunctionEntryAssembly));

            var pluginLoaders = Bootstrapper.LoadPlugins(new[] { pathToFunctionAssembly });
            var plugins       = PluginDiscoverer.Discover(pluginLoaders.Assemblies);

            FunctionDependencyMerger.Merge(pathToFunctionEntryAssembly, pathToFunctionAssembly);
            FunctionImplementor.Implement(pathToFunctionEntryAssembly, plugins);
        }
        public void AddWorstPlugins()
        {
            DiscoverDoneEventArgs lastDiscoverEventArgs = null;

            PluginDiscoverer discoverer = new PluginDiscoverer();

            discoverer.DiscoverDone += (sender, e) => lastDiscoverEventArgs = e;

            TestBase.CopyPluginToTestDir("ServiceA.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(lastDiscoverEventArgs.NewPlugins.Count, Is.EqualTo(1));
            Assert.That(lastDiscoverEventArgs.NewServices.Count, Is.EqualTo(1));

            TestBase.CopyPluginToTestDir("ServiceA.Old.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(lastDiscoverEventArgs.NewPlugins.Count, Is.EqualTo(0));
            Assert.That(lastDiscoverEventArgs.NewServices.Count, Is.EqualTo(0));
            Assert.That(lastDiscoverEventArgs.NewOldPlugins.Count, Is.EqualTo(1));
        }
        public void TestConsumers()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir("ServiceProducer.Model.dll");
            TestBase.CopyPluginToTestDir("ServiceProducer.dll");
            TestBase.CopyPluginToTestDir("ServiceConsumer.dll");
            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(discoverer.AllAssemblies.Count, Is.EqualTo(3));
            Assert.That(discoverer.AllPlugins.Count, Is.EqualTo(3));

            IPluginInfo c0 = discoverer.FindPlugin(new Guid("{2294F5BD-C511-456F-8E6B-A39A84FBAE51}"));
        }
Exemple #17
0
        public void RefInternalNonDynamicService()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir("RefInternalNonDynamicService.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(discoverer.Plugins.Count, Is.EqualTo(2), "There are 2 runnable plugins.");
            Assert.That(discoverer.Plugins.Select(x => x.PublicName).OrderBy(Util.FuncIdentity).SequenceEqual(new[] { "PluginSuccess", "PluginSuccessAlso" }));

            Assert.That(discoverer.AllPlugins.Count, Is.EqualTo(3), "There are 2 runnable plugins and 1 in error.");
            Assert.That(discoverer.AllPlugins.Any(p => p.PublicName == "PluginFailed"));
        }
        public void TestConsumers()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir( "ServiceProducer.Model.dll" );
            TestBase.CopyPluginToTestDir( "ServiceProducer.dll" );
            TestBase.CopyPluginToTestDir( "ServiceConsumer.dll" );
            discoverer.Discover( TestBase.TestFolderDir, true );

            Assert.That( discoverer.AllAssemblies.Count, Is.EqualTo( 3 ) );
            Assert.That( discoverer.AllPlugins.Count, Is.EqualTo( 3 ) );

            IPluginInfo c0 = discoverer.FindPlugin( new Guid("{2294F5BD-C511-456F-8E6B-A39A84FBAE51}") );

        }
        private void AddServices(YamlMappingNode functions, YamlMappingNode resources)
        {
            var services      = ServiceDiscoverer.Discover(_serviceDiscoveryOptions);
            var pluginLoaders = Bootstrapper.LoadPlugins(services.Select(x => x.AssemblyPath));

            foreach (var service in services)
            {
                var assembly = pluginLoaders.Assemblies.Single(x => x.GetName().Name == service.Name);
                var plugins  = PluginDiscoverer.Discover(assembly);

                foreach (var plugin in plugins)
                {
                    AddService(functions, resources, service, plugin);
                }
            }
        }
Exemple #20
0
		public void TestDiscoverNothing()
		{
            PluginDiscoverer discoverer = new PluginDiscoverer();

            bool discoverBegin = false;
            bool discoverDone = false;

            discoverer.DiscoverBegin += ( object sender, EventArgs e ) => discoverBegin = true;
            discoverer.DiscoverDone += ( object sender, DiscoverDoneEventArgs e ) => discoverDone = true;

            discoverer.Discover( TestBase.TestFolderDir, true );

            Assert.IsTrue( discoverDone && discoverBegin );

            Assert.That( discoverer.AllAssemblies.Count == 0 );
            Assert.That( discoverer.PluginOrServiceAssemblies.Count == 0 );
		}
Exemple #21
0
        public RouterConfig Build()
        {
            var services      = ServiceDiscoverer.Discover(_serviceDiscoveryOptions);
            var pluginLoaders = Bootstrapper.LoadPlugins(services.Select(x => x.AssemblyPath));

            var routes = new List <RouterEntry>();

            foreach (var assembly in pluginLoaders.Assemblies)
            {
                var assemblyRoutes = PluginDiscoverer.Discover(assembly)
                                     .SelectMany(plugin => RouteDiscoverer.Discover(plugin).Select(route => ToRouterEntry(plugin, route)));

                routes.AddRange(assemblyRoutes);
            }

            return(new RouterConfig(routes));
        }
Exemple #22
0
        public void TestDiscoverNothing()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();

            bool discoverBegin = false;
            bool discoverDone  = false;

            discoverer.DiscoverBegin += (object sender, EventArgs e) => discoverBegin = true;
            discoverer.DiscoverDone  += (object sender, DiscoverDoneEventArgs e) => discoverDone = true;

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.IsTrue(discoverDone && discoverBegin);

            Assert.That(discoverer.AllAssemblies.Count == 0);
            Assert.That(discoverer.PluginOrServiceAssemblies.Count == 0);
        }
Exemple #23
0
        public void TestDiscoverOldVersionnedPlugins()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir("VersionedPlugins.dll");
            TestBase.CopyPluginToTestDir("VersionedPluginWithService.dll");

            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(discoverer.AllAssemblies.Count, Is.EqualTo(2));
            Assert.That(discoverer.AllPlugins.Count, Is.EqualTo(4));
            Assert.That(discoverer.AllServices.Count, Is.EqualTo(1));
            Assert.That(discoverer.Services.Count, Is.EqualTo(1));
            Assert.That(discoverer.OldVersionnedPlugins.Count, Is.EqualTo(2));
            Assert.That(discoverer.Plugins.Count == 2);

            Assert.That(discoverer.Services.ElementAt(0).Implementations.Count, Is.EqualTo(1));       // the best version of the implementation
            Assert.That(!discoverer.Services.ElementAt(0).Implementations.Any((p) => discoverer.OldVersionnedPlugins.Contains(p)));
        }
Exemple #24
0
        public void TestCollectionEditableBy()
        {
            int passed = 0;
            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir("ServiceA.dll");
            TestBase.CopyPluginToTestDir("ServiceB.dll");
            TestBase.CopyPluginToTestDir("EditorsOfPlugins.dll");
            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(discoverer.Plugins.Count, Is.EqualTo(6));
            foreach (IPluginInfo plugin in discoverer.Plugins)
            {
                if (plugin.PluginId == new Guid("{12A9FCC0-ECDC-4049-8DBF-8961E49A9EDE}"))    //Plugin01
                {
                    Assert.That(plugin.EditableBy.Count, Is.EqualTo(3));
                    // Edited by EditorOfPlugin01
                    Assert.That(plugin.EditableBy.Any(
                                    (editor) => { return(editor.Plugin.PluginId == new Guid("{8BE8C487-4052-46b0-9225-708BC2A1E033}")); }));
                    // Edited by EditorOfPlugin01And02
                    Assert.That(plugin.EditableBy.Any(
                                    (editor) => { return(editor.Plugin.PluginId == new Guid("{BC7E641B-E4EE-47f5-833B-0AFFFAA2A683}")); }));
                    // Edited by itself
                    Assert.That(plugin.EditableBy.Any(
                                    (editor) => { return(editor.Plugin.PluginId == new Guid("{12A9FCC0-ECDC-4049-8DBF-8961E49A9EDE}")); }));

                    passed++;
                }
                else if (plugin.PluginId == new Guid("{E64F17D5-DCAB-4a07-8CEE-901A87D8295E}"))    //Plugin02
                {
                    Assert.That(plugin.EditableBy.Count, Is.EqualTo(2));
                    // Edited by EditorOfPlugin02
                    Assert.That(plugin.EditableBy.Any(
                                    (editor) => { return(editor.Plugin.PluginId == new Guid("{EDA76E35-30C2-449e-817C-91CB24D38763}")); }));
                    // Edited by EditorOfPlugin01And02
                    Assert.That(plugin.EditableBy.Any(
                                    (editor) => { return(editor.Plugin.PluginId == new Guid("{BC7E641B-E4EE-47f5-833B-0AFFFAA2A683}")); }));
                    passed++;
                }
            }
            Assert.That(passed, Is.EqualTo(2));
        }
        private static async Task Run(Options opts)
        {
            var wellKnownBases = new WellKnownBases(opts.BaseAddresses);

            var pluginLoader = Bootstrapper.LoadPlugins(new[] { opts.AssemblyPath });
            var plugins      = PluginDiscoverer.Discover(pluginLoader.Assemblies);

            var models = new List <RoutingModel>();

            foreach (var plugin in plugins)
            {
                var model = new RoutingModel(plugin.ServiceKey, wellKnownBases, new RoutingModelOptions());
                models.Add(model);

                switch (plugin.ServiceType)
                {
                case ServiceType.MessageHandler:
                    await Bootstrapper.RegisterPluginAsync(model, model, plugin);

                    break;

                case ServiceType.Http:
                    StartWebServer(plugin, model);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            Thread.Sleep(TimeSpan.FromMilliseconds(1500));

            foreach (var model in models)
            {
                await model.StartAsync();
            }

            Console.WriteLine($"Running {string.Join(", ", plugins.Select(x => x.ServiceKey))}... press enter to exit!");
            Console.ReadLine();
        }
Exemple #26
0
        static async Task Main(string[] args)
        {
            var log = new LoggerConfiguration()
                      .WriteTo.Console()
                      .CreateLogger();

            AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) =>
            {
                log.Error((Exception)eventArgs.ExceptionObject, "Unhandled error!");
            };

            var pluginPaths = Discover(Environment.CurrentDirectory);

            var pluginLoaders = Bootstrapper.LoadPlugins(pluginPaths);
            var plugins       = PluginDiscoverer.Discover(pluginLoaders.Assemblies);

            var model = new LocalModel(log);

            foreach (var plugin in plugins)
            {
                switch (plugin.ServiceType)
                {
                case ServiceType.MessageHandler:
                    await Bootstrapper.RegisterPluginAsync(model, model, plugin);

                    break;

                case ServiceType.Http:
                    var host = StartWebServer(plugin, model);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            Console.WriteLine($"Running {string.Join(", ", plugins.Select(x => x.ServiceKey))}... press enter to exit!");
            Console.ReadLine();
        }
Exemple #27
0
        private void PackageService(ServiceProject service, Assembly assembly, string tempRoot, string serviceEntryAssembly, string httpEntryAssembly, string artifactsFolder)
        {
            var plugins = PluginDiscoverer.Discover(assembly);

            if (!plugins.Any())
            {
                return;
            }

            var serviceFolder   = RunPublish(tempRoot, service.ProjectPath, service.Name, false);
            var serviceAssembly = Path.Combine(serviceFolder.Path, Path.GetFileName(assembly.Location));

            var builder = new FunctionBuilder.Builder();

            if (plugins.Any(x => x.ServiceType == ServiceType.MessageHandler))
            {
                using (var buildTargetFolder = new TempDirectory(tempRoot, service.Name + "-service"))
                {
                    var buildContext = new FunctionBuilder.BuildContext(ServiceType.MessageHandler, serviceEntryAssembly, serviceAssembly, buildTargetFolder.Path);
                    builder.Build(buildContext);

                    var packagePath = Path.Combine(artifactsFolder, $"{service.Name}-service.zip");
                    CreateZip(buildTargetFolder, packagePath);
                }
            }

            if (plugins.Any(x => x.ServiceType == ServiceType.Http))
            {
                using (var buildTargetFolder = new TempDirectory(tempRoot, service.Name + "-http"))
                {
                    var buildContext = new FunctionBuilder.BuildContext(ServiceType.Http, httpEntryAssembly, serviceAssembly, buildTargetFolder.Path);
                    builder.Build(buildContext);

                    var packagePath = Path.Combine(artifactsFolder, $"{service.Name}-http.zip");
                    CreateZip(buildTargetFolder, packagePath);
                }
            }
        }
Exemple #28
0
        public void RefExternalNonDynamicService()
        {
            {
                // Missing ServiceC.Model.dll assembly: the interface has no definition.
                PluginDiscoverer discoverer = new PluginDiscoverer();
                TestBase.CopyPluginToTestDir( "RefExternalNonDynamicService.dll" );

                discoverer.Discover( TestBase.TestFolderDir, true );

                Assert.That( discoverer.AllAssemblies.Count, Is.EqualTo( 1 ) );
                Assert.That( discoverer.AllAssemblies.First().HasError, Is.True );

                Assert.That( discoverer.AllPlugins.Count, Is.EqualTo( 0 ) );
                Assert.That( discoverer.AllServices.Count, Is.EqualTo( 0 ) );
            }
            {
                PluginDiscoverer discoverer = new PluginDiscoverer();
                TestBase.CopyPluginToTestDir( "ServiceC.Model.dll" );

                discoverer.Discover( TestBase.TestFolderDir, true );

                Assert.That( discoverer.Plugins.Count, Is.EqualTo( 2 ), "There are 2 runnable plugins." );
                Assert.That( discoverer.Plugins.Select( x => x.PublicName ).OrderBy( Util.FuncIdentity ).SequenceEqual( new[] { "PluginSuccess", "PluginSuccessAlso" } ) );

                Assert.That( discoverer.AllPlugins.Count, Is.EqualTo( 3 ), "There are 2 runnable plugins and 1 in error." );
                Assert.That( discoverer.AllPlugins.Any( p => p.PublicName == "PluginFailed" ) );
            }

        }
Exemple #29
0
        public void RefInternalNonDynamicService()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir( "RefInternalNonDynamicService.dll" );

            discoverer.Discover( TestBase.TestFolderDir, true );

            Assert.That( discoverer.Plugins.Count, Is.EqualTo( 2 ), "There are 2 runnable plugins." );
            Assert.That( discoverer.Plugins.Select( x => x.PublicName ).OrderBy( Util.FuncIdentity ).SequenceEqual( new[] { "PluginSuccess", "PluginSuccessAlso" } ) );

            Assert.That( discoverer.AllPlugins.Count, Is.EqualTo( 3 ), "There are 2 runnable plugins and 1 in error." );
            Assert.That( discoverer.AllPlugins.Any( p => p.PublicName == "PluginFailed" ) );
        }
Exemple #30
0
        public void DiscoverMultiServicesPlugin()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();            

            TestBase.CopyPluginToTestDir( "ServiceD.dll" );

            discoverer.Discover( TestBase.TestFolderDir, true );

            Assert.That( discoverer.AllPlugins.Count == 1 );
            Assert.That( discoverer.AllPlugins.ElementAt( 0 ).HasError );
        }
Exemple #31
0
        public void TestDiscoverOldVersionnedPlugins()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();
            
            TestBase.CopyPluginToTestDir( "VersionedPlugins.dll" );
            TestBase.CopyPluginToTestDir( "VersionedPluginWithService.dll" );

            discoverer.Discover( TestBase.TestFolderDir, true );

            Assert.That( discoverer.AllAssemblies.Count, Is.EqualTo( 2 ) );
            Assert.That( discoverer.AllPlugins.Count, Is.EqualTo( 4 ) );
            Assert.That( discoverer.AllServices.Count, Is.EqualTo( 1 ) );
            Assert.That( discoverer.Services.Count, Is.EqualTo( 1 ) );
            Assert.That( discoverer.OldVersionnedPlugins.Count, Is.EqualTo( 2 ) );
            Assert.That( discoverer.Plugins.Count == 2 );

            Assert.That( discoverer.Services.ElementAt( 0 ).Implementations.Count, Is.EqualTo( 1 ) ); // the best version of the implementation
            Assert.That( !discoverer.Services.ElementAt( 0 ).Implementations.Any( ( p ) => discoverer.OldVersionnedPlugins.Contains( p ) ) );
        }
Exemple #32
0
        public void TestCollectionEditableBy()
        {
            int passed = 0;
            PluginDiscoverer discoverer = new PluginDiscoverer();
            
            TestBase.CopyPluginToTestDir( "ServiceA.dll" );
            TestBase.CopyPluginToTestDir( "ServiceB.dll" );
            TestBase.CopyPluginToTestDir( "EditorsOfPlugins.dll" );
            discoverer.Discover( TestBase.TestFolderDir, true );

            Assert.That( discoverer.Plugins.Count, Is.EqualTo( 6 ) );
            foreach( IPluginInfo plugin in discoverer.Plugins )
            {
                if( plugin.PluginId == new Guid( "{12A9FCC0-ECDC-4049-8DBF-8961E49A9EDE}" ) ) //Plugin01
                {
                    Assert.That( plugin.EditableBy.Count, Is.EqualTo( 3 ) );
                    // Edited by EditorOfPlugin01
                    Assert.That( plugin.EditableBy.Any(
                        ( editor ) => { return editor.Plugin.PluginId == new Guid( "{8BE8C487-4052-46b0-9225-708BC2A1E033}" ); } ) );
                    // Edited by EditorOfPlugin01And02
                    Assert.That( plugin.EditableBy.Any(
                        ( editor ) => { return editor.Plugin.PluginId == new Guid( "{BC7E641B-E4EE-47f5-833B-0AFFFAA2A683}" ); } ) );
                    // Edited by itself
                    Assert.That( plugin.EditableBy.Any(
                        ( editor ) => { return editor.Plugin.PluginId == new Guid( "{12A9FCC0-ECDC-4049-8DBF-8961E49A9EDE}" ); } ) );
                    
                    passed++;
                }
                else if( plugin.PluginId == new Guid( "{E64F17D5-DCAB-4a07-8CEE-901A87D8295E}" ) ) //Plugin02
                {
                    Assert.That( plugin.EditableBy.Count, Is.EqualTo( 2 ) );
                    // Edited by EditorOfPlugin02
                    Assert.That( plugin.EditableBy.Any(
                        ( editor ) => { return editor.Plugin.PluginId == new Guid( "{EDA76E35-30C2-449e-817C-91CB24D38763}" ); } ) );
                    // Edited by EditorOfPlugin01And02
                    Assert.That( plugin.EditableBy.Any(
                        ( editor ) => { return editor.Plugin.PluginId == new Guid( "{BC7E641B-E4EE-47f5-833B-0AFFFAA2A683}" ); } ) );
                    passed++;
                }
            }
            Assert.That( passed, Is.EqualTo( 2 ) );
        }
Exemple #33
0
        public void TestDiscoverEditors()
        {
            int nbEditors = 0;

            PluginDiscoverer discoverer = new PluginDiscoverer();
            
            TestBase.CopyPluginToTestDir( "ServiceA.dll" );
            TestBase.CopyPluginToTestDir( "ServiceB.dll" );
            TestBase.CopyPluginToTestDir( "EditorsOfPlugins.dll" );
            discoverer.Discover( TestBase.TestFolderDir, true );

            Assert.That( discoverer.AllAssemblies.Count == 3 );
            Assert.That( discoverer.PluginOrServiceAssemblies.Count == 3 );
            Assert.That( discoverer.Plugins.Count, Is.EqualTo( 6 ) );

            foreach( IPluginInfo plugin in discoverer.Plugins )
            {
                nbEditors += plugin.EditorsInfo.Count;
            }

            Assert.That( nbEditors, Is.EqualTo( 6 ) ); // 6 because ServiceA get an accessor to its configuration.

            IPluginInfo editorOfTwoPlugins = discoverer.FindPlugin( new Guid( "{BC7E641B-E4EE-47f5-833B-0AFFFAA2A683}" ) );
            Assert.That( editorOfTwoPlugins.EditorsInfo.Any( ( a ) => { return (a.ConfigurationPropertyName == "ConfigPlugin01") && (a.IsConfigurationPropertyValid); } ) );
            Assert.That( editorOfTwoPlugins.EditorsInfo.Any( ( a ) => { return (a.ConfigurationPropertyName == "ConfigPlugin02") && (a.IsConfigurationPropertyValid); } ) );
        }
Exemple #34
0
        public void TestDiscoverTwoPlugins()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();
            
            TestBase.CopyPluginToTestDir( "ServiceA.dll" );
            TestBase.CopyPluginToTestDir( "ServiceB.dll" );
            discoverer.Discover( TestBase.TestFolderDir, true );

            Assert.That( discoverer.AllAssemblies.Count == 2 );
            Assert.That( discoverer.PluginOrServiceAssemblies.Count == 2 );
            Assert.That( discoverer.Plugins.Count == 2 );
            Assert.That( discoverer.Services.Count == 2 );

            foreach( IServiceInfo s in discoverer.Services )
            {
                if( s.IsDynamicService )
                {
                    Assert.That( s.AssemblyInfo != null );
                    Assert.That( s.AssemblyQualifiedName != "" );
                }
            }

            //Test methods, events and properties info of service A
            IReadOnlyCollection<ISimpleEventInfo> eventsA = discoverer.Services.First().EventsInfoCollection;
            IReadOnlyCollection<ISimpleMethodInfo> methodsA = discoverer.Services.First().MethodsInfoCollection;
            IReadOnlyCollection<ISimplePropertyInfo> propertiesA = discoverer.Services.First().PropertiesInfoCollection;

            Assert.That( eventsA.Count, Is.EqualTo( 1 ) );
            Assert.That( methodsA.Count, Is.EqualTo( 2 ) );
            Assert.That( propertiesA.Count, Is.EqualTo( 1 ) );

            Assert.That( eventsA.First().Name, Is.EqualTo( "HasStarted" ) );

            Assert.That( methodsA.First().Name, Is.EqualTo( "Add" ) );
            Assert.That( methodsA.First().Parameters.Count, Is.EqualTo( 2 ) );
            Assert.That( methodsA.First().Parameters.First().ParameterName, Is.EqualTo( "a" ) );
            Assert.That( methodsA.First().Parameters.Last().ParameterName, Is.EqualTo( "b" ) );
            Assert.That( methodsA.First().ReturnType, Is.EqualTo( "System.Int32" ) );

            Assert.That( propertiesA.First().Name, Is.EqualTo( "HasBeenStarted" ) );
            Assert.That( propertiesA.First().PropertyType, Is.EqualTo( "System.Boolean" ) );


            //Test methods, events and properties info of service B
            IReadOnlyCollection<ISimpleEventInfo> eventsB = discoverer.Services.ElementAt( 1 ).EventsInfoCollection;
            IReadOnlyCollection<ISimpleMethodInfo> methodsB = discoverer.Services.ElementAt( 1 ).MethodsInfoCollection;
            IReadOnlyCollection<ISimplePropertyInfo> propertiesB = discoverer.Services.ElementAt( 1 ).PropertiesInfoCollection;

            Assert.That( eventsB.Count, Is.EqualTo( 0 ) );
            Assert.That( methodsB.Count, Is.EqualTo( 2 ) );
            Assert.That( propertiesA.Count, Is.EqualTo( 1 ) );

            Assert.That( methodsB.First().Name, Is.EqualTo( "Mult" ) );
            Assert.That( methodsB.First().Parameters.Count, Is.EqualTo( 2 ) );
            Assert.That( methodsB.First().Parameters.First().ParameterName, Is.EqualTo( "a" ) );
            Assert.That( methodsB.First().Parameters.Last().ParameterName, Is.EqualTo( "b" ) );
            Assert.That( methodsB.First().ReturnType, Is.EqualTo( "System.Int32" ) );

            Assert.That( methodsB.ElementAt( 1 ).Name, Is.EqualTo( "Substract" ) );
            Assert.That( methodsB.ElementAt( 1 ).Parameters.Count, Is.EqualTo( 3 ) );
            Assert.That( methodsB.ElementAt( 1 ).Parameters.First().ParameterName, Is.EqualTo( "a" ) );
            Assert.That( methodsB.ElementAt( 1 ).Parameters.ElementAt( 1 ).ParameterName, Is.EqualTo( "b" ) );
            Assert.That( methodsB.ElementAt( 1 ).Parameters.Last().ParameterName, Is.EqualTo( "isAboveZero" ) );
            Assert.That( methodsB.ElementAt( 1 ).ReturnType, Is.EqualTo( "System.Int32" ) );

            Assert.That( propertiesB.First().Name, Is.EqualTo( "HasBeenStarted" ) );
            Assert.That( propertiesB.First().PropertyType, Is.EqualTo( "System.Boolean" ) );
        }
Exemple #35
0
        public void TestRequireConfiguration()
        {
            int passed = 0;

            PluginDiscoverer discoverer = new PluginDiscoverer();
            
            TestBase.CopyPluginToTestDir( "ServiceA.dll" );
            TestBase.CopyPluginToTestDir( "ServiceB.dll" );
            TestBase.CopyPluginToTestDir( "EditorsOfPlugins.dll" );
            discoverer.Discover( TestBase.TestFolderDir, true );

            Assert.That( discoverer.Plugins.Count, Is.EqualTo( 6 ) );
            foreach( IPluginInfo plugin in discoverer.Plugins )
            {
                if( plugin.PluginId == new Guid( "{8BE8C487-4052-46b0-9225-708BC2A1E033}" ) ) //EditorOfPlugin01
                {
                    Assert.That( plugin.EditorsInfo.Count, Is.EqualTo( 1 ) );
                    Assert.That( plugin.EditorsInfo[0].ConfigurationPropertyName == "EditedPluginConfiguration" );
                    Assert.IsTrue( plugin.EditorsInfo[0].IsConfigurationPropertyValid );
                    passed++;
                }
                else if( plugin.PluginId == new Guid( "{EDA76E35-30C2-449e-817C-91CB24D38763}" ) ) //EditorOfPlugin02
                {
                    Assert.That( plugin.EditorsInfo.Count, Is.EqualTo( 1 ) );
                    Assert.IsTrue( plugin.EditorsInfo[0].IsConfigurationPropertyValid );
                    passed++;
                }
            }

            Assert.That( passed, Is.EqualTo( 2 ) );
        }
Exemple #36
0
        public void TestDiscoverTwoPlugins()
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();

            TestBase.CopyPluginToTestDir("ServiceA.dll");
            TestBase.CopyPluginToTestDir("ServiceB.dll");
            discoverer.Discover(TestBase.TestFolderDir, true);

            Assert.That(discoverer.AllAssemblies.Count == 2);
            Assert.That(discoverer.PluginOrServiceAssemblies.Count == 2);
            Assert.That(discoverer.Plugins.Count == 2);
            Assert.That(discoverer.Services.Count == 2);

            foreach (IServiceInfo s in discoverer.Services)
            {
                if (s.IsDynamicService)
                {
                    Assert.That(s.AssemblyInfo != null);
                    Assert.That(s.AssemblyQualifiedName != "");
                }
            }

            //Test methods, events and properties info of service A
            IReadOnlyCollection <ISimpleEventInfo>    eventsA     = discoverer.Services.First().EventsInfoCollection;
            IReadOnlyCollection <ISimpleMethodInfo>   methodsA    = discoverer.Services.First().MethodsInfoCollection;
            IReadOnlyCollection <ISimplePropertyInfo> propertiesA = discoverer.Services.First().PropertiesInfoCollection;

            Assert.That(eventsA.Count, Is.EqualTo(1));
            Assert.That(methodsA.Count, Is.EqualTo(2));
            Assert.That(propertiesA.Count, Is.EqualTo(1));

            Assert.That(eventsA.First().Name, Is.EqualTo("HasStarted"));

            Assert.That(methodsA.First().Name, Is.EqualTo("Add"));
            Assert.That(methodsA.First().Parameters.Count, Is.EqualTo(2));
            Assert.That(methodsA.First().Parameters.First().ParameterName, Is.EqualTo("a"));
            Assert.That(methodsA.First().Parameters.Last().ParameterName, Is.EqualTo("b"));
            Assert.That(methodsA.First().ReturnType, Is.EqualTo("System.Int32"));

            Assert.That(propertiesA.First().Name, Is.EqualTo("HasBeenStarted"));
            Assert.That(propertiesA.First().PropertyType, Is.EqualTo("System.Boolean"));


            //Test methods, events and properties info of service B
            IReadOnlyCollection <ISimpleEventInfo>    eventsB     = discoverer.Services.ElementAt(1).EventsInfoCollection;
            IReadOnlyCollection <ISimpleMethodInfo>   methodsB    = discoverer.Services.ElementAt(1).MethodsInfoCollection;
            IReadOnlyCollection <ISimplePropertyInfo> propertiesB = discoverer.Services.ElementAt(1).PropertiesInfoCollection;

            Assert.That(eventsB.Count, Is.EqualTo(0));
            Assert.That(methodsB.Count, Is.EqualTo(2));
            Assert.That(propertiesA.Count, Is.EqualTo(1));

            Assert.That(methodsB.First().Name, Is.EqualTo("Mult"));
            Assert.That(methodsB.First().Parameters.Count, Is.EqualTo(2));
            Assert.That(methodsB.First().Parameters.First().ParameterName, Is.EqualTo("a"));
            Assert.That(methodsB.First().Parameters.Last().ParameterName, Is.EqualTo("b"));
            Assert.That(methodsB.First().ReturnType, Is.EqualTo("System.Int32"));

            Assert.That(methodsB.ElementAt(1).Name, Is.EqualTo("Substract"));
            Assert.That(methodsB.ElementAt(1).Parameters.Count, Is.EqualTo(3));
            Assert.That(methodsB.ElementAt(1).Parameters.First().ParameterName, Is.EqualTo("a"));
            Assert.That(methodsB.ElementAt(1).Parameters.ElementAt(1).ParameterName, Is.EqualTo("b"));
            Assert.That(methodsB.ElementAt(1).Parameters.Last().ParameterName, Is.EqualTo("isAboveZero"));
            Assert.That(methodsB.ElementAt(1).ReturnType, Is.EqualTo("System.Int32"));

            Assert.That(propertiesB.First().Name, Is.EqualTo("HasBeenStarted"));
            Assert.That(propertiesB.First().PropertyType, Is.EqualTo("System.Boolean"));
        }
Exemple #37
0
        public PluginDiscoverer GetFooBarPluginDiscoverer(String ckAssemblieFolder)
        {
            PluginDiscoverer discoverer = new PluginDiscoverer();
            bool discoverDone = false;

            discoverer.DiscoverDone += (object sender, DiscoverDoneEventArgs e) => discoverDone = true;

            ckAssemblieFolder = ckAssemblieFolder.Replace('|', System.IO.Path.DirectorySeparatorChar);
            discoverer.Discover(new DirectoryInfo(ckAssemblieFolder), true);

            Contract.Assert(discoverDone);
            return discoverer;
        }