Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
02/04/10 12:20:43 (15 years ago)
Author:
gkronber
Message:

Prepared plugin infrastructure to work with versioned plugins and dependencies and added versioning to part of HL.GP plugins. #864 (Plugins should have an a version)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.PluginInfrastructure/Manager/PluginValidator.cs

    r2690 r2750  
    3636  /// </summary>
    3737  internal sealed class PluginValidator : MarshalByRefObject {
     38    // private class to store plugin dependency declarations while reflecting over plugins
     39    private class PluginDependency {
     40      public string Name { get; private set; }
     41      public Version Version { get; private set; }
     42
     43      public PluginDependency(string name, Version version) {
     44        this.Name = name;
     45        this.Version = version;
     46      }
     47    }
     48
     49
    3850    internal event EventHandler<PluginInfrastructureEventArgs> PluginLoaded;
    3951
    40     private Dictionary<PluginDescription, List<string>> pluginDependencies;
     52    private Dictionary<PluginDescription, IEnumerable<PluginDependency>> pluginDependencies;
    4153
    4254    private List<ApplicationDescription> applications;
     
    6173
    6274    internal PluginValidator() {
    63       this.pluginDependencies = new Dictionary<PluginDescription, List<string>>();
     75      this.pluginDependencies = new Dictionary<PluginDescription, IEnumerable<PluginDependency>>();
    6476
    6577      // ReflectionOnlyAssemblyResolveEvent must be handled because we load assemblies from the plugin path
     
    250262      // get all attributes of that type
    251263      IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(pluginType);
    252       List<string> pluginDependencies = new List<string>();
     264      List<PluginDependency> pluginDependencies = new List<PluginDependency>();
    253265      List<PluginFile> pluginFiles = new List<PluginFile>();
    254266      string pluginName = null;
    255267      string pluginDescription = null;
     268      string pluginVersion = "0.0.0.0";
    256269      // iterate through all custom attributes and search for attributed that we are interested in
    257270      foreach (CustomAttributeData attributeData in attributes) {
    258271        if (IsAttributeDataForType(attributeData, typeof(PluginAttribute))) {
    259272          pluginName = (string)attributeData.ConstructorArguments[0].Value;
    260           if (attributeData.ConstructorArguments.Count() == 2) {
    261             pluginDescription = (string)attributeData.ConstructorArguments[1].Value;
    262           } else pluginDescription = pluginName;
     273          if (attributeData.ConstructorArguments.Count() > 1) {
     274            pluginVersion = (string)attributeData.ConstructorArguments[1].Value;
     275          }
     276          if (attributeData.ConstructorArguments.Count() > 2) {
     277            pluginDescription = (string)attributeData.ConstructorArguments[2].Value;
     278          } else {
     279            // no description given => use name as description
     280            pluginDescription = pluginName;
     281          }
    263282        } else if (IsAttributeDataForType(attributeData, typeof(PluginDependencyAttribute))) {
    264           pluginDependencies.Add((string)attributeData.ConstructorArguments[0].Value);
     283          string name = (string)attributeData.ConstructorArguments[0].Value;
     284          Version version = new Version();
     285          // check if version is given for now
     286          // later when the constructore of PluginDependencyAttribute with only one argument has been removed
     287          // this conditional can be removed as well
     288          if (attributeData.ConstructorArguments.Count > 1) {
     289            try {
     290              version = new Version((string)attributeData.ConstructorArguments[1].Value); // throws FormatException
     291            }
     292            catch (FormatException ex) {
     293              throw new InvalidPluginException("Invalid version format of dependency " + name + " in plugin " + pluginType.ToString(), ex);
     294            }
     295          }
     296          pluginDependencies.Add(new PluginDependency(name, version));
    265297        } else if (IsAttributeDataForType(attributeData, typeof(PluginFileAttribute))) {
    266298          string pluginFileName = (string)attributeData.ConstructorArguments[0].Value;
     
    270302      }
    271303
    272       var buildDates = from attr in CustomAttributeData.GetCustomAttributes(pluginType.Assembly)
    273                        where IsAttributeDataForType(attr, typeof(AssemblyBuildDateAttribute))
    274                        select (string)attr.ConstructorArguments[0].Value;
    275 
    276304      // minimal sanity check of the attribute values
    277305      if (!string.IsNullOrEmpty(pluginName) &&
    278306          pluginFiles.Count > 0 &&                                   // at least on file
    279           pluginFiles.Any(f => f.Type == PluginFileType.Assembly) && // at least on assembly
    280           buildDates.Count() == 1) {                                 // build date must be declared
     307          pluginFiles.Any(f => f.Type == PluginFileType.Assembly)) { // at least on assembly
    281308        // create a temporary PluginDescription that contains the attribute values
    282309        PluginDescription info = new PluginDescription();
    283310        info.Name = pluginName;
    284311        info.Description = pluginDescription;
    285         info.Version = pluginType.Assembly.GetName().Version;
    286         info.BuildDate = DateTime.Parse(buildDates.Single(), System.Globalization.CultureInfo.InvariantCulture);
     312        info.Version = new Version(pluginVersion);
    287313        info.AddFiles(pluginFiles);
    288314
     
    303329    private void BuildDependencyTree(IEnumerable<PluginDescription> pluginDescriptions) {
    304330      foreach (var desc in pluginDescriptions) {
    305         foreach (string pluginName in pluginDependencies[desc]) {
    306           var matchingDescriptions = pluginDescriptions.Where(x => x.Name == pluginName);
     331        foreach (var dependency in pluginDependencies[desc]) {
     332          var matchingDescriptions = from availablePlugin in pluginDescriptions
     333                                     where availablePlugin.Name == dependency.Name
     334                                     where IsCompatiblePluginVersion(availablePlugin.Version, dependency.Version)
     335                                     select availablePlugin;
    307336          if (matchingDescriptions.Count() > 0) {
    308337            desc.AddDependency(matchingDescriptions.Single());
     
    313342        }
    314343      }
     344    }
     345
     346    /// <summary>
     347    /// Checks if version <paramref name="available"/> is compatible to version <paramref name="requested"/>.
     348    /// Note: the compatibility relation is not bijective.
     349    /// Compatibility rules:
     350    ///  * major and minor number must be the same
     351    ///  * build and revision number of <paramref name="available"/> must be larger or equal to <paramref name="requested"/>.
     352    /// </summary>
     353    /// <param name="available">The available version which should be compared to <paramref name="requested"/>.</param>
     354    /// <param name="requested">The requested version that must be matched.</param>
     355    /// <returns></returns>
     356    private bool IsCompatiblePluginVersion(Version available, Version requested) {
     357      // this condition must be removed after all plugins have been updated to declare plugin and dependency versions
     358      if (
     359        (requested.Major == 0 && requested.Minor == 0) ||
     360        (available.Major == 0 && available.Minor == 0)) return true;
     361      return
     362        available.Major == requested.Major &&
     363        available.Minor == requested.Minor &&
     364        available.Build >= requested.Build &&
     365        available.Revision >= requested.Revision;
    315366    }
    316367
Note: See TracChangeset for help on using the changeset viewer.