Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.PluginInfrastructure/Advanced/InstallationManager.cs @ 2860

Last change on this file since 2860 was 2811, checked in by gkronber, 15 years ago

Fixed service references in plugin infrastructure. #860 (Deployment server for plugin installation from web locations)

File size: 11.2 KB
RevLine 
[2612]1#region License Information
2/* HeuristicLab
[2790]3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[2612]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
[2513]23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using HeuristicLab.PluginInfrastructure.Manager;
27using System.IO;
[2517]28using System.ComponentModel;
[2688]29using System.Reflection;
[2513]30
31namespace HeuristicLab.PluginInfrastructure.Advanced {
[2517]32  internal class InstallationManager {
[2513]33
[2517]34    internal event EventHandler<PluginInfrastructureCancelEventArgs> PreUpdatePlugin;
35    internal event EventHandler<PluginInfrastructureCancelEventArgs> PreRemovePlugin;
36    internal event EventHandler<PluginInfrastructureCancelEventArgs> PreInstallPlugin;
37
38    internal event EventHandler<PluginInfrastructureEventArgs> PluginUpdated;
39    internal event EventHandler<PluginInfrastructureEventArgs> PluginRemoved;
40    internal event EventHandler<PluginInfrastructureEventArgs> PluginInstalled;
41
[2753]42
43    public IEnumerable<PluginDescription> Plugins {
44      get { return pluginManager.Plugins; }
45    }
46
[2513]47    private string pluginDir;
[2517]48    private string updateLocationUrl;
[2513]49    private PluginManager pluginManager;
[2517]50    public InstallationManager(string pluginDir) {
51      this.pluginDir = pluginDir;
52      this.updateLocationUrl = "http://localhost:59253/UpdateLocation.svc";
[2513]53      this.pluginManager = new PluginManager(pluginDir);
54      this.pluginManager.DiscoverAndCheckPlugins();
55    }
56
57    public IEnumerable<string> Show(IEnumerable<string> pluginNames) {
58      foreach (PluginDescription desc in GetPluginDescriptions(pluginNames)) {
[2517]59        yield return GetInformation(desc);
[2513]60      }
61    }
62
[2517]63    internal string GetInformation(string pluginName) {
64      return GetInformation(GetPluginDescription(pluginName));
65    }
66
67    private string GetInformation(PluginDescription desc) {
[2513]68      StringBuilder builder = new StringBuilder();
69      builder.Append("Name: ").AppendLine(desc.Name);
70      builder.Append("Version: ").AppendLine(desc.Version.ToString());
71      builder.AppendLine("Description:").AppendLine(desc.Description);
[2778]72      if (!string.IsNullOrEmpty(desc.ContactName)) {
73        builder.Append("Contact: ").Append(desc.ContactName).Append(", ").AppendLine(desc.ContactEmail);
74      }
[2753]75      builder.AppendLine("This plugin is " + desc.PluginState.ToString().ToLowerInvariant() + ".");
[2513]76      builder.AppendLine("Files: ");
[2753]77      foreach (var file in desc.Files) {
78        builder.AppendLine(file.Type + " " + file.Name);
[2513]79      }
[2753]80      builder.AppendLine().AppendLine("Directly depends on:");
[2513]81      if (desc.Dependencies.Count() == 0) builder.AppendLine("None");
82      foreach (var dependency in desc.Dependencies) {
[2753]83        builder.AppendLine(dependency.Name + " " + dependency.Version);
[2513]84      }
[2763]85      builder.AppendLine().AppendFormat("Plugins directly dependent on {0}:", desc.Name).AppendLine();
[2513]86      var dependents = from x in pluginManager.Plugins
87                       where x.Dependencies.Contains(desc)
[2753]88                       select x;
[2513]89      if (dependents.Count() == 0) builder.AppendLine("None");
90      foreach (var dependent in dependents) {
[2753]91        builder.AppendLine(dependent.Name + " " + dependent.Version);
[2513]92      }
[2753]93      builder.AppendLine();
[2517]94      if (desc.PluginState == PluginState.Disabled) {
95        builder.AppendLine(DetermineProblem(desc));
96      }
[2513]97
98      return builder.ToString();
99    }
100
[2517]101    private static string DetermineProblem(PluginDescription desc) {
102      // either any file is missing
103      StringBuilder builder = new StringBuilder();
[2753]104      builder.AppendLine("Problem report:");
[2779]105      builder.AppendLine(desc.LoadingErrorInformation);
106      return builder.ToString();
[2517]107    }
108
109    private static IEnumerable<string> GetDeclaredDependencies(PluginDescription desc) {
[2527]110      var plugin = ApplicationManager.GetInstances<IPlugin>(desc).Single();
[2517]111      return plugin.GetType().GetCustomAttributes(typeof(PluginDependencyAttribute), false).Cast<PluginDependencyAttribute>().Select(x => x.Dependency);
112    }
113
114    private PluginDescription GetPluginDescription(string pluginName) {
115      var exactMatch = from pluginDesc in pluginManager.Plugins
116                       where string.Equals(pluginName, pluginDesc.Name, StringComparison.InvariantCultureIgnoreCase)
117                       select pluginDesc;
118      var inexactMatch = from pluginDesc in pluginManager.Plugins
119                         where MatchPluginNameInexact(pluginName, pluginDesc.Name)
120                         select pluginDesc;
121      return exactMatch.Count() > 0 ? exactMatch.Single() : inexactMatch.First();
122    }
123
[2513]124    private IEnumerable<PluginDescription> GetPluginDescriptions(IEnumerable<string> pluginNames) {
[2517]125      return from pluginName in pluginNames
126             select GetPluginDescription(pluginName);
[2513]127    }
128
[2517]129    private static bool MatchPluginNameInexact(string similarName, string actualName) {
130      return
131        // Core-3.2 == HeuristicLab.Core-3.2
132        actualName.Equals("HeuristicLab." + similarName, StringComparison.InvariantCultureIgnoreCase) ||
133        // HeuristicLab.Core == HeuristicLab.Core-3.2 (this should be save because we checked for exact matches first)
134        (Math.Abs(actualName.Length - similarName.Length) <= 4 && actualName.StartsWith(similarName, StringComparison.InvariantCultureIgnoreCase)) ||
135        // Core == HeuristicLab.Core-3.2
136        (Math.Abs(actualName.Length - similarName.Length) <= 17 && actualName.StartsWith("HeuristicLab." + similarName, StringComparison.InvariantCultureIgnoreCase));
137    }
138
[2513]139    public void Install(IEnumerable<string> pluginNames) {
[2527]140      throw new NotImplementedException();
141      //IEnumerable<PluginInformation> pluginsToInstall;
142      //using (UpdateLocationClient updateLocation = new UpdateLocationClient()) {
143      //  pluginsToInstall = from pluginName in pluginNames
144      //                     from matchingPlugin in updateLocation.GetAvailablePluginsByName(pluginName)
145      //                     select matchingPlugin;
[2517]146
[2527]147      //  var args = new PluginInfrastructureCancelEventArgs("Installing", pluginsToInstall);
148      //  OnPreInstall(args);
149      //  foreach (var pluginInfo in pluginsToInstall) {
150      //    var s = updateLocation.GetPluginFiles(pluginInfo);
151      //    Console.WriteLine("Downloading: {0} {1} {2}", pluginInfo.Name, pluginInfo.Version, pluginInfo.BuildDate);
152      //  }
153      //}
154      //OnInstalled(new PluginInfrastructureEventArgs("Installed", pluginsToInstall));
[2513]155    }
156
[2527]157    //private static PluginInformation GetMatchingPluginInformation(string pluginName, IEnumerable<PluginInformation> plugins) {
158    //  var exactMatch = from pluginDesc in plugins
159    //                   where string.Equals(pluginName, pluginDesc.Name, StringComparison.InvariantCultureIgnoreCase)
160    //                   select pluginDesc;
161    //  var inexactMatch = from pluginDesc in plugins
162    //                     where MatchPluginNameInexact(pluginName, pluginDesc.Name)
163    //                     select pluginDesc;
164    //  return exactMatch.Count() > 0 ? exactMatch.Single() : inexactMatch.First();
165    //}
[2517]166
[2513]167    public void Remove(IEnumerable<string> pluginNames) {
[2517]168      var fileNames = from pluginToDelete in PluginDescriptionIterator.IterateDependentsTopDown(GetPluginDescriptions(pluginNames), pluginManager.Plugins)
[2688]169                      from file in pluginToDelete.Files
170                      select Path.Combine(pluginDir, file.Name);
[2517]171      var args = new PluginInfrastructureCancelEventArgs("Deleting", fileNames);
172      OnPreDelete(args);
173      if (!args.Cancel) {
174        foreach (string fileName in fileNames) {
175          Console.WriteLine("Deleting file " + fileName);
176          // File.Delete(fileName);
[2513]177        }
[2517]178
179        OnDeleted(new PluginInfrastructureEventArgs("Deleted", fileNames));
[2513]180      }
181    }
182
183    public void Update(IEnumerable<string> pluginNames) {
[2527]184      var pluginDescriptions = from name in pluginNames
185                               select GetPluginDescription(name);
[2811]186      Dictionary<DeploymentService.PluginDescription, string> matchingPlugins = new Dictionary<DeploymentService.PluginDescription, string>();
[2527]187      foreach (var updateLocation in HeuristicLab.PluginInfrastructure.Properties.Settings.Default.UpdateLocations) {
[2811]188        using (var client = new DeploymentService.UpdateClient("", updateLocation)) {
[2527]189          var updateLocationMatchingPlugins = from desc in pluginDescriptions
[2783]190                                              from info in client.GetPlugins()
191                                              where desc.Name == info.Name
[2527]192                                              select info;
[2811]193          foreach (DeploymentService.PluginDescription info in updateLocationMatchingPlugins) {
[2783]194            // keep only the highest version of any plugin
[2527]195            var existingPlugin = matchingPlugins.Keys.FirstOrDefault(x => x.Name == info.Name);
[2783]196            if (existingPlugin == null || existingPlugin.Version < info.Version) {
[2527]197              matchingPlugins.Remove(existingPlugin);
198              matchingPlugins.Add(info, updateLocation);
199            }
200          }
201        }
202      }
203      PluginInfrastructureCancelEventArgs args = new PluginInfrastructureCancelEventArgs("Updating", matchingPlugins.Keys);
204      OnPreUpdate(args);
205      if (!args.Cancel) {
206        var groupedInfos = matchingPlugins.GroupBy(x => x.Value);
207        foreach (var group in groupedInfos) {
[2811]208          using (var client = new DeploymentService.UpdateClient(group.Key)) {
[2527]209            foreach (var info in group) {
[2783]210              client.GetPlugin(info.Key);
[2527]211            }
212          }
213        }
214        OnUpdated(new PluginInfrastructureEventArgs("Updated", matchingPlugins.Keys));
215      }
[2513]216    }
[2517]217
[2527]218    private void OnPreUpdate(PluginInfrastructureCancelEventArgs args) {
219      if (PreUpdatePlugin != null) PreUpdatePlugin(this, args);
220    }
221
222    private void OnUpdated(PluginInfrastructureEventArgs args) {
223      if (PluginUpdated != null) PluginUpdated(this, args);
224    }
225
[2517]226    private void OnPreDelete(PluginInfrastructureCancelEventArgs args) {
227      if (PreRemovePlugin != null) PreRemovePlugin(this, args);
228    }
229
230    private void OnDeleted(PluginInfrastructureEventArgs args) {
231      if (PluginRemoved != null) PluginRemoved(this, args);
232    }
233
234    private void OnPreInstall(PluginInfrastructureCancelEventArgs args) {
235      if (PreInstallPlugin != null) PreInstallPlugin(this, args);
236    }
237
238    private void OnInstalled(PluginInfrastructureEventArgs args) {
239      if (PluginInstalled != null) PluginInstalled(this, args);
240    }
[2513]241  }
242}
Note: See TracBrowser for help on using the repository browser.