Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 2790 was 2790, checked in by swagner, 14 years ago

Operator architecture refactoring (#95)

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