Beispiel #1
0
        /// <summary>
        /// Mark plugin as uninstalled
        /// </summary>
        /// <param name="systemName">Plugin system name</param>
        public static void MarkPluginAsUninstalled(string systemName)
        {
            if (String.IsNullOrEmpty(systemName))
            {
                throw new ArgumentNullException("systemName");
            }

            var filePath = CommonHelper.MapPath(InstalledPluginsFilePath);

            if (!File.Exists(filePath))
            {
                using (File.Create(filePath))
                {
                    //we use 'using' to close the file after it's created
                }
            }


            var  installedPluginSystemNames = PluginFileParser.ParseInstalledPluginsFile(GetInstalledPluginsFilePath());
            bool alreadyMarkedAsInstalled   = installedPluginSystemNames
                                              .FirstOrDefault(x => x.Equals(systemName, StringComparison.OrdinalIgnoreCase)) != null;

            if (alreadyMarkedAsInstalled)
            {
                installedPluginSystemNames.Remove(systemName);
            }
            PluginFileParser.SaveInstalledPluginsFile(installedPluginSystemNames, filePath);
        }
        public static void Initialize(IMvcCoreBuilder mvcCoreBuilder, GrandConfig config)
        {
            if (mvcCoreBuilder == null)
            {
                throw new ArgumentNullException("mvcCoreBuilder");
            }

            _config = config ?? throw new ArgumentNullException("config");

            _pluginFolder     = new DirectoryInfo(CommonHelper.MapPath(PluginsPath));
            _shadowCopyFolder = new DirectoryInfo(CommonHelper.MapPath(ShadowCopyPath));

            var referencedPlugins   = new List <PluginDescriptor>();
            var incompatiblePlugins = new List <string>();

            try
            {
                var installedPluginSystemNames = PluginFileParser.ParseInstalledPluginsFile(GetInstalledPluginsFilePath());

                Log.Information("Creating shadow copy folder and querying for dlls");
                //ensure folders are created
                Directory.CreateDirectory(_pluginFolder.FullName);
                Directory.CreateDirectory(_shadowCopyFolder.FullName);

                //get list of all files in bin
                var binFiles = _shadowCopyFolder.GetFiles("*", SearchOption.AllDirectories);
                if (config.ClearPluginShadowDirectoryOnStartup)
                {
                    //clear out shadow copied plugins
                    foreach (var f in binFiles)
                    {
                        Log.Information($"Deleting {f.Name}");
                        try
                        {
                            //ignore index.htm
                            var fileName = Path.GetFileName(f.FullName);
                            if (fileName.Equals("index.htm", StringComparison.OrdinalIgnoreCase))
                            {
                                continue;
                            }

                            File.Delete(f.FullName);
                        }
                        catch (Exception exc)
                        {
                            Log.Error(exc, "PluginManager");
                        }
                    }
                }

                //load description files
                foreach (var pluginDescriptor in GetDescriptions())
                {
                    //ensure that version of plugin is valid
                    if (!pluginDescriptor.SupportedVersions.Contains(GrandVersion.SupportedPluginVersion, StringComparer.OrdinalIgnoreCase))
                    {
                        incompatiblePlugins.Add(pluginDescriptor.SystemName);
                        continue;
                    }

                    //some validation
                    if (string.IsNullOrWhiteSpace(pluginDescriptor.SystemName))
                    {
                        throw new Exception(string.Format("A plugin '{0}' has no system name. Try assigning the plugin a unique name and recompiling.", pluginDescriptor.SystemName));
                    }
                    if (referencedPlugins.Contains(pluginDescriptor))
                    {
                        throw new Exception(string.Format("A plugin with '{0}' system name is already defined", pluginDescriptor.SystemName));
                    }

                    //set 'Installed' property
                    pluginDescriptor.Installed = installedPluginSystemNames
                                                 .FirstOrDefault(x => x.Equals(pluginDescriptor.SystemName, StringComparison.OrdinalIgnoreCase)) != null;

                    try
                    {
                        if (!config.PluginShadowCopy)
                        {
                            //remove deps.json files
                            var depsFiles = pluginDescriptor.OriginalAssemblyFile.Directory.GetFiles("*.deps.json", SearchOption.TopDirectoryOnly);
                            foreach (var f in depsFiles)
                            {
                                try
                                {
                                    File.Delete(f.FullName);
                                }
                                catch (Exception exc)
                                {
                                    Log.Error(exc, "PluginManager");
                                }
                            }
                        }

                        //main plugin file
                        AddApplicationPart(mvcCoreBuilder, pluginDescriptor.ReferencedAssembly, pluginDescriptor.SystemName, pluginDescriptor.PluginFileName);

                        //init plugin type (only one plugin per assembly is allowed)
                        foreach (var t in pluginDescriptor.ReferencedAssembly.GetTypes())
                        {
                            if (typeof(IPlugin).IsAssignableFrom(t))
                            {
                                if (!t.GetTypeInfo().IsInterface)
                                {
                                    if (t.GetTypeInfo().IsClass&& !t.GetTypeInfo().IsAbstract)
                                    {
                                        pluginDescriptor.PluginType = t;
                                        break;
                                    }
                                }
                            }
                        }

                        referencedPlugins.Add(pluginDescriptor);
                    }
                    catch (ReflectionTypeLoadException ex)
                    {
                        //add a plugin name. this way we can easily identify a problematic plugin
                        var msg = string.Format("Plugin '{0}'. ", pluginDescriptor.FriendlyName);
                        foreach (var e in ex.LoaderExceptions)
                        {
                            msg += e.Message + Environment.NewLine;
                        }

                        var fail = new Exception(msg, ex);
                        throw fail;
                    }
                    catch (Exception ex)
                    {
                        //add a plugin name. this way we can easily identify a problematic plugin
                        var msg = string.Format("Plugin '{0}'. {1}", pluginDescriptor.FriendlyName, ex.Message);

                        var fail = new Exception(msg, ex);
                        throw fail;
                    }
                }
            }
            catch (Exception ex)
            {
                var msg = string.Empty;
                for (var e = ex; e != null; e = e.InnerException)
                {
                    msg += e.Message + Environment.NewLine;
                }

                var fail = new Exception(msg, ex);
                throw fail;
            }

            ReferencedPlugins   = referencedPlugins;
            IncompatiblePlugins = incompatiblePlugins;
        }
Beispiel #3
0
        public static void Initialize(IMvcCoreBuilder mvcCoreBuilder, GrandConfig config)
        {
            if (mvcCoreBuilder == null)
            {
                throw new ArgumentNullException("mvcCoreBuilder");
            }

            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            using (new WriteLockDisposable(Locker))
            {
                var pluginFolder = new DirectoryInfo(CommonHelper.MapPath(PluginsPath));
                _shadowCopyFolder = new DirectoryInfo(CommonHelper.MapPath(ShadowCopyPath));

                var referencedPlugins   = new List <PluginDescriptor>();
                var incompatiblePlugins = new List <string>();

                try
                {
                    var installedPluginSystemNames = PluginFileParser.ParseInstalledPluginsFile(GetInstalledPluginsFilePath());

                    Debug.WriteLine("Creating shadow copy folder and querying for dlls");
                    //ensure folders are created
                    Directory.CreateDirectory(pluginFolder.FullName);
                    Directory.CreateDirectory(_shadowCopyFolder.FullName);

                    //get list of all files in bin
                    var binFiles = _shadowCopyFolder.GetFiles("*", SearchOption.AllDirectories);
                    if (config.ClearPluginShadowDirectoryOnStartup)
                    {
                        //clear out shadow copied plugins
                        foreach (var f in binFiles)
                        {
                            Debug.WriteLine("Deleting " + f.Name);
                            try
                            {
                                //ignore index.htm
                                var fileName = Path.GetFileName(f.FullName);
                                if (fileName.Equals("index.htm", StringComparison.OrdinalIgnoreCase))
                                {
                                    continue;
                                }

                                File.Delete(f.FullName);
                            }
                            catch (Exception exc)
                            {
                                Debug.WriteLine("Error deleting file " + f.Name + ". Exception: " + exc);
                            }
                        }
                    }

                    //load description files
                    foreach (var dfd in GetDescriptionFilesAndDescriptors(pluginFolder))
                    {
                        var descriptionFile  = dfd.Key;
                        var pluginDescriptor = dfd.Value;

                        //ensure that version of plugin is valid
                        if (!pluginDescriptor.SupportedVersions.Contains(GrandVersion.CurrentVersion, StringComparer.OrdinalIgnoreCase))
                        {
                            incompatiblePlugins.Add(pluginDescriptor.SystemName);
                            continue;
                        }

                        //some validation
                        if (String.IsNullOrWhiteSpace(pluginDescriptor.SystemName))
                        {
                            throw new Exception(string.Format("A plugin '{0}' has no system name. Try assigning the plugin a unique name and recompiling.", descriptionFile.FullName));
                        }
                        if (referencedPlugins.Contains(pluginDescriptor))
                        {
                            throw new Exception(string.Format("A plugin with '{0}' system name is already defined", pluginDescriptor.SystemName));
                        }

                        //set 'Installed' property
                        pluginDescriptor.Installed = installedPluginSystemNames
                                                     .FirstOrDefault(x => x.Equals(pluginDescriptor.SystemName, StringComparison.OrdinalIgnoreCase)) != null;

                        try
                        {
                            if (descriptionFile.Directory == null)
                            {
                                throw new Exception(string.Format("Directory cannot be resolved for '{0}' description file", descriptionFile.Name));
                            }

                            //get list of all DLLs in plugins (not in bin!)
                            var pluginFiles = descriptionFile.Directory.GetFiles("*.dll", SearchOption.AllDirectories)
                                              //just make sure we're not registering shadow copied plugins
                                              .Where(x => !binFiles.Select(q => q.FullName).Contains(x.FullName))
                                              .Where(x => IsPackagePluginFolder(x.Directory))
                                              .ToList();

                            if (!config.PluginShadowCopy)
                            {
                                //remove deps.json files
                                var depsFiles = descriptionFile.Directory.GetFiles("*.deps.json", SearchOption.TopDirectoryOnly);
                                foreach (var f in depsFiles)
                                {
                                    try
                                    {
                                        File.Delete(f.FullName);
                                    }
                                    catch (Exception exc)
                                    {
                                        Debug.WriteLine("Error deleting file " + f.Name + ". Exception: " + exc);
                                    }
                                }
                            }

                            var mainPluginFile = pluginFiles
                                                 .FirstOrDefault(x => x.Name.Equals(pluginDescriptor.PluginFileName, StringComparison.OrdinalIgnoreCase));
                            pluginDescriptor.OriginalAssemblyFile = mainPluginFile;

                            //main plugin file
                            pluginDescriptor.ReferencedAssembly = AddApplicationPart(mainPluginFile, mvcCoreBuilder, config);

                            //load all other referenced assemblies now
                            foreach (var plugin in pluginFiles
                                     .Where(x => !x.Name.Equals(mainPluginFile.Name, StringComparison.OrdinalIgnoreCase))
                                     .Where(x => !IsAlreadyLoaded(x)))
                            {
                                AddApplicationPart(plugin, mvcCoreBuilder, config);
                            }

                            //init plugin type (only one plugin per assembly is allowed)
                            foreach (var t in pluginDescriptor.ReferencedAssembly.GetTypes())
                            {
                                if (typeof(IPlugin).IsAssignableFrom(t))
                                {
                                    if (!t.GetTypeInfo().IsInterface)
                                    {
                                        if (t.GetTypeInfo().IsClass&& !t.GetTypeInfo().IsAbstract)
                                        {
                                            pluginDescriptor.PluginType = t;
                                            break;
                                        }
                                    }
                                }
                            }

                            referencedPlugins.Add(pluginDescriptor);
                        }
                        catch (ReflectionTypeLoadException ex)
                        {
                            //add a plugin name. this way we can easily identify a problematic plugin
                            var msg = string.Format("Plugin '{0}'. ", pluginDescriptor.FriendlyName);
                            foreach (var e in ex.LoaderExceptions)
                            {
                                msg += e.Message + Environment.NewLine;
                            }

                            var fail = new Exception(msg, ex);
                            throw fail;
                        }
                        catch (Exception ex)
                        {
                            //add a plugin name. this way we can easily identify a problematic plugin
                            var msg = string.Format("Plugin '{0}'. {1}", pluginDescriptor.FriendlyName, ex.Message);

                            var fail = new Exception(msg, ex);
                            throw fail;
                        }
                    }
                }
                catch (Exception ex)
                {
                    var msg = string.Empty;
                    for (var e = ex; e != null; e = e.InnerException)
                    {
                        msg += e.Message + Environment.NewLine;
                    }

                    var fail = new Exception(msg, ex);
                    throw fail;
                }


                ReferencedPlugins   = referencedPlugins;
                IncompatiblePlugins = incompatiblePlugins;
            }
        }