/// <summary> /// Extracts plugin information for this type. /// Reads plugin name, list and type of files and dependencies of the plugin. This information is necessary for /// plugin dependency checking before plugin activation. /// </summary> /// <param name="pluginType"></param> private PluginDescription GetPluginDescription(Type pluginType) { string pluginName, pluginDescription, pluginVersion; string contactName, contactAddress; GetPluginMetaData(pluginType, out pluginName, out pluginDescription, out pluginVersion); GetPluginContactMetaData(pluginType, out contactName, out contactAddress); var pluginFiles = GetPluginFilesMetaData(pluginType); var pluginDependencies = GetPluginDependencyMetaData(pluginType); // minimal sanity check of the attribute values if (!string.IsNullOrEmpty(pluginName) && pluginFiles.Count() > 0 && // at least one file pluginFiles.Any(f => f.Type == PluginFileType.Assembly)) // at least one assembly // create a temporary PluginDescription that contains the attribute values { PluginDescription info = new PluginDescription(); info.Name = pluginName; info.Description = pluginDescription; info.Version = new Version(pluginVersion); info.ContactName = contactName; info.ContactEmail = contactAddress; info.LicenseText = ReadLicenseFiles(pluginFiles); info.AddFiles(pluginFiles); this.pluginDependencies[info] = pluginDependencies; return(info); } else { throw new InvalidPluginException("Invalid metadata in plugin " + pluginType.ToString()); } }
// equals and hashcode have to be implemented because we want to compare PluginDescriptions from // different AppDomains and serialization destroys reference equality /// <summary> /// Checks whether the given object is equal to the current plugin. /// </summary> /// <param name="obj">The object to compare.</param> /// <returns><c>true</c> if it is equal, <c>false</c> otherwise.</returns> public override bool Equals(object obj) { PluginDescription other = obj as PluginDescription; if (other == null) { return(false); } return(other.Name == this.Name && other.Version == this.Version); }
private bool IsAnyDependencyDisabled(PluginDescription descr, List <PluginDescription> disabledPlugins) { if (descr.PluginState == PluginState.Disabled) { disabledPlugins.Add(descr); return(true); } foreach (PluginDescription dependency in descr.Dependencies) { IsAnyDependencyDisabled(dependency, disabledPlugins); } return(disabledPlugins.Count > 0); }
private void applicationManager_PluginLoaded(object sender, PluginInfrastructureEventArgs e) { // load the matching plugin description ( PluginDescription desc = (PluginDescription)e.Entity; // access to plugin descriptions has to be synchronized because multiple applications // can be started or stopped at the same time lock (locker) { // also load the matching plugin description in this AppDomain plugins.First(x => x.Equals(desc)).Load(); } OnPluginLoaded(e); }
private bool ArePluginFilesMissing(PluginDescription pluginDescription, out IEnumerable <string> missingFiles) { List <string> missing = new List <string>(); foreach (string filename in pluginDescription.Files.Select(x => x.Name)) { if (!FileLiesInDirectory(PluginDir, filename) || !File.Exists(filename)) { missing.Add(filename); } } missingFiles = missing; return(missing.Count > 0); }
private bool HasCycleInDependencies(PluginDescription plugin, IEnumerable <PluginDescription> pluginDependencies) { foreach (var dep in pluginDependencies) { // if one of the dependencies is the original plugin we found a cycle and can return // if the dependency is already disabled we can ignore the cycle detection because we will disable the plugin anyway // if following one of the dependencies recursively leads to a cycle then we also return if (dep == plugin || dep.PluginState == PluginState.Disabled || HasCycleInDependencies(plugin, dep.Dependencies)) { return(true); } } // no cycle found and none of the direct and indirect dependencies is disabled return(false); }
private void DiscoverApplications(IEnumerable <PluginDescription> pluginDescriptions) { applications = new List <ApplicationDescription>(); foreach (IApplication application in GetApplications(pluginDescriptions)) { Type appType = application.GetType(); ApplicationAttribute attr = (from x in appType.GetCustomAttributes(typeof(ApplicationAttribute), false) select(ApplicationAttribute) x).Single(); ApplicationDescription info = new ApplicationDescription(); PluginDescription declaringPlugin = GetDeclaringPlugin(appType, pluginDescriptions); info.Name = application.Name; info.Version = declaringPlugin.Version; info.Description = application.Description; info.AutoRestart = attr.RestartOnErrors; info.DeclaringAssemblyName = appType.Assembly.GetName().Name; info.DeclaringTypeName = appType.Namespace + "." + application.GetType().Name; applications.Add(info); } }
private static IEnumerable <PluginDescription> GetDependentPlugins(PluginDescription desc, IEnumerable <PluginDescription> allPlugins) { return(from plugin in allPlugins where plugin.Dependencies.Contains(desc) select plugin); }
private static IEnumerable<PluginDescription> GetDependentPlugins(PluginDescription desc, IEnumerable<PluginDescription> allPlugins) { return from plugin in allPlugins where plugin.Dependencies.Contains(desc) select plugin; }
private static ListViewItem CreateListViewItem(PluginDescription plugin) { ListViewItem item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(), plugin.Description }); item.Tag = plugin; item.ImageIndex = 0; return item; }
private bool ArePluginFilesMissing(PluginDescription pluginDescription, out IEnumerable<string> missingFiles) { List<string> missing = new List<string>(); foreach (string filename in pluginDescription.Files.Select(x => x.Name)) { if (!FileLiesInDirectory(PluginDir, filename) || !File.Exists(filename)) { missing.Add(filename); } } missingFiles = missing; return missing.Count > 0; }
private bool IsAnyDependencyDisabled(PluginDescription descr, List<PluginDescription> disabledPlugins) { if (descr.PluginState == PluginState.Disabled) { disabledPlugins.Add(descr); return true; } foreach (PluginDescription dependency in descr.Dependencies) { IsAnyDependencyDisabled(dependency, disabledPlugins); } return disabledPlugins.Count > 0; }
private bool HasCycleInDependencies(PluginDescription plugin, IEnumerable<PluginDescription> pluginDependencies) { foreach (var dep in pluginDependencies) { // if one of the dependencies is the original plugin we found a cycle and can return // if the dependency is already disabled we can ignore the cycle detection because we will disable the plugin anyway // if following one of the dependencies recursively leads to a cycle then we also return if (dep == plugin || dep.PluginState == PluginState.Disabled || HasCycleInDependencies(plugin, dep.Dependencies)) return true; } // no cycle found and none of the direct and indirect dependencies is disabled return false; }
/// <summary> /// Extracts plugin information for this type. /// Reads plugin name, list and type of files and dependencies of the plugin. This information is necessary for /// plugin dependency checking before plugin activation. /// </summary> /// <param name="pluginType"></param> private PluginDescription GetPluginDescription(Type pluginType) { string pluginName, pluginDescription, pluginVersion; string contactName, contactAddress; GetPluginMetaData(pluginType, out pluginName, out pluginDescription, out pluginVersion); GetPluginContactMetaData(pluginType, out contactName, out contactAddress); var pluginFiles = GetPluginFilesMetaData(pluginType); var pluginDependencies = GetPluginDependencyMetaData(pluginType); // minimal sanity check of the attribute values if (!string.IsNullOrEmpty(pluginName) && pluginFiles.Count() > 0 && // at least one file pluginFiles.Any(f => f.Type == PluginFileType.Assembly)) { // at least one assembly // create a temporary PluginDescription that contains the attribute values PluginDescription info = new PluginDescription(); info.Name = pluginName; info.Description = pluginDescription; info.Version = new Version(pluginVersion); info.ContactName = contactName; info.ContactEmail = contactAddress; info.LicenseText = ReadLicenseFiles(pluginFiles); info.AddFiles(pluginFiles); this.pluginDependencies[info] = pluginDependencies; return info; } else { throw new InvalidPluginException("Invalid metadata in plugin " + pluginType.ToString()); } }
internal void AddDependency(PluginDescription dependency) { dependencies.Add(dependency); }