- Timestamp:
- 02/04/10 12:20:43 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.PluginInfrastructure/Manager/PluginValidator.cs
r2690 r2750 36 36 /// </summary> 37 37 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 38 50 internal event EventHandler<PluginInfrastructureEventArgs> PluginLoaded; 39 51 40 private Dictionary<PluginDescription, List<string>> pluginDependencies;52 private Dictionary<PluginDescription, IEnumerable<PluginDependency>> pluginDependencies; 41 53 42 54 private List<ApplicationDescription> applications; … … 61 73 62 74 internal PluginValidator() { 63 this.pluginDependencies = new Dictionary<PluginDescription, List<string>>();75 this.pluginDependencies = new Dictionary<PluginDescription, IEnumerable<PluginDependency>>(); 64 76 65 77 // ReflectionOnlyAssemblyResolveEvent must be handled because we load assemblies from the plugin path … … 250 262 // get all attributes of that type 251 263 IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(pluginType); 252 List< string> pluginDependencies = new List<string>();264 List<PluginDependency> pluginDependencies = new List<PluginDependency>(); 253 265 List<PluginFile> pluginFiles = new List<PluginFile>(); 254 266 string pluginName = null; 255 267 string pluginDescription = null; 268 string pluginVersion = "0.0.0.0"; 256 269 // iterate through all custom attributes and search for attributed that we are interested in 257 270 foreach (CustomAttributeData attributeData in attributes) { 258 271 if (IsAttributeDataForType(attributeData, typeof(PluginAttribute))) { 259 272 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 } 263 282 } 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)); 265 297 } else if (IsAttributeDataForType(attributeData, typeof(PluginFileAttribute))) { 266 298 string pluginFileName = (string)attributeData.ConstructorArguments[0].Value; … … 270 302 } 271 303 272 var buildDates = from attr in CustomAttributeData.GetCustomAttributes(pluginType.Assembly)273 where IsAttributeDataForType(attr, typeof(AssemblyBuildDateAttribute))274 select (string)attr.ConstructorArguments[0].Value;275 276 304 // minimal sanity check of the attribute values 277 305 if (!string.IsNullOrEmpty(pluginName) && 278 306 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 281 308 // create a temporary PluginDescription that contains the attribute values 282 309 PluginDescription info = new PluginDescription(); 283 310 info.Name = pluginName; 284 311 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); 287 313 info.AddFiles(pluginFiles); 288 314 … … 303 329 private void BuildDependencyTree(IEnumerable<PluginDescription> pluginDescriptions) { 304 330 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; 307 336 if (matchingDescriptions.Count() > 0) { 308 337 desc.AddDependency(matchingDescriptions.Single()); … … 313 342 } 314 343 } 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; 315 366 } 316 367
Note: See TracChangeset
for help on using the changeset viewer.