Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.PluginInfrastructure/Advanced/InstallationManagerForm.cs @ 3006

Last change on this file since 3006 was 3006, checked in by gkronber, 14 years ago

Implemented deployment service on servdev.heuristiclab.com and changed all service references and configurations to point to the service address. Improved GUI of installation manager. Implemented user name authentication and authorization for the deployment service. #860 (Deployment server for plugin installation from web locations)

File size: 15.4 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Data;
5using System.Drawing;
6using System.Linq;
7using System.Text;
8using System.Windows.Forms;
9using System.IO;
10using HeuristicLab.PluginInfrastructure.Manager;
11
12namespace HeuristicLab.PluginInfrastructure.Advanced {
13  public partial class InstallationManagerForm : Form {
14    private class UpdateOrInstallPluginsBackgroundWorkerArgument {
15      public IEnumerable<IPluginDescription> PluginsToUpdate { get; set; }
16      public IEnumerable<IPluginDescription> PluginsToInstall { get; set; }
17    }
18
19    private class RemovePluginsBackgroundWorkerArgument {
20      public IEnumerable<IPluginDescription> PluginsToRemove { get; set; }
21    }
22
23    private class RefreshBackgroundWorkerResult {
24      public IEnumerable<IPluginDescription> RemotePlugins { get; set; }
25      public IEnumerable<DeploymentService.ProductDescription> RemoteProducts { get; set; }
26    }
27
28    private InstallationManager installationManager;
29    private BackgroundWorker refreshServerPluginsBackgroundWorker;
30    private BackgroundWorker updateOrInstallPluginsBackgroundWorker;
31    private BackgroundWorker removePluginsBackgroundWorker;
32    private BackgroundWorker refreshLocalPluginsBackgroundWorker;
33    private string pluginDir;
34
35    public InstallationManagerForm() {
36      InitializeComponent();
37
38      pluginDir = Application.StartupPath;
39
40      #region initialize background workers
41      refreshServerPluginsBackgroundWorker = new BackgroundWorker();
42      refreshServerPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshServerPluginsBackgroundWorker_DoWork);
43      refreshServerPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshServerPluginsBackgroundWorker_RunWorkerCompleted);
44
45      updateOrInstallPluginsBackgroundWorker = new BackgroundWorker();
46      updateOrInstallPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(updateOrInstallPluginsBackgroundWorker_DoWork);
47      updateOrInstallPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted);
48
49      removePluginsBackgroundWorker = new BackgroundWorker();
50      removePluginsBackgroundWorker.DoWork += new DoWorkEventHandler(removePluginsBackgroundWorker_DoWork);
51      removePluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(removePluginsBackgroundWorker_RunWorkerCompleted);
52
53      refreshLocalPluginsBackgroundWorker = new BackgroundWorker();
54      refreshLocalPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshLocalPluginsBackgroundWorker_DoWork);
55      refreshLocalPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshLocalPluginsBackgroundWorker_RunWorkerCompleted);
56      #endregion
57
58      installationManager = new InstallationManager(pluginDir);
59      installationManager.PluginInstalled += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginInstalled);
60      installationManager.PluginRemoved += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginRemoved);
61      installationManager.PluginUpdated += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginUpdated);
62      installationManager.PreInstallPlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreInstallPlugin);
63      installationManager.PreRemovePlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreRemovePlugin);
64      installationManager.PreUpdatePlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreUpdatePlugin);
65
66      RefreshLocalPluginListAsync();
67    }
68
69    #region event handlers for refresh local plugin list backgroundworker
70    private IEnumerable<PluginDescription> ReloadLocalPlugins() {
71      PluginManager pluginManager = new PluginManager(Application.StartupPath);
72      pluginManager.PluginLoaded += pluginManager_PluginLoaded;
73      pluginManager.PluginUnloaded += pluginManager_PluginUnloaded;
74      pluginManager.Initializing += pluginManager_Initializing;
75      pluginManager.Initialized += pluginManager_Initialized;
76
77      pluginManager.DiscoverAndCheckPlugins();
78
79      pluginManager.PluginLoaded -= pluginManager_PluginLoaded;
80      pluginManager.PluginUnloaded -= pluginManager_PluginUnloaded;
81      pluginManager.Initializing -= pluginManager_Initializing;
82      pluginManager.Initialized -= pluginManager_Initialized;
83
84      return pluginManager.Plugins;
85    }
86    void refreshLocalPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
87      if (!e.Cancelled && e.Error == null) {
88        UpdateLocalPluginList((IEnumerable<PluginDescription>)e.Result);
89        UpdateControlsConnected();
90      }
91    }
92
93    void refreshLocalPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
94      var plugins = ReloadLocalPlugins();
95      e.Result = plugins;
96    }
97    #endregion
98
99    #region event handlers for plugin removal background worker
100    void removePluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
101      if (!e.Cancelled && e.Error == null) {
102        RefreshLocalPluginListAsync();
103        UpdateControlsConnected();
104      }
105    }
106
107    void removePluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
108      IEnumerable<IPluginDescription> pluginsToRemove = (IEnumerable<IPluginDescription>)e.Argument;
109      installationManager.Remove(pluginsToRemove);
110    }
111    #endregion
112
113    #region event handlers for plugin update background worker
114    void updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
115      if (!e.Cancelled && e.Error == null) {
116        RefreshLocalPluginListAsync();
117        RefreshRemotePluginListAsync();
118        UpdateControlsConnected();
119      } else {
120        UpdateControlsDisconnected();
121      }
122    }
123
124    void updateOrInstallPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
125      UpdateOrInstallPluginsBackgroundWorkerArgument info = (UpdateOrInstallPluginsBackgroundWorkerArgument)e.Argument;
126      installationManager.Install(info.PluginsToInstall);
127      installationManager.Update(info.PluginsToUpdate);
128    }
129    #endregion
130
131    #region event handlers for refresh server plugins background worker
132    void refreshServerPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
133      if (!e.Cancelled && e.Result != null) {
134        RefreshBackgroundWorkerResult refreshResult = (RefreshBackgroundWorkerResult)e.Result;
135        UpdateRemotePluginList(refreshResult.RemoteProducts, refreshResult.RemotePlugins);
136        UpdateControlsConnected();
137      } else {
138        UpdateControlsDisconnected();
139      }
140    }
141
142    void refreshServerPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
143      RefreshBackgroundWorkerResult result = new RefreshBackgroundWorkerResult();
144      result.RemotePlugins = installationManager.GetRemotePluginList();
145      result.RemoteProducts = installationManager.GetRemoteProductList();
146      e.Cancel = false;
147      e.Result = result;
148    }
149
150
151
152    #endregion
153
154    #region plugin manager event handlers
155    void pluginManager_Initialized(object sender, PluginInfrastructureEventArgs e) {
156      SetStatusStrip("Initialized PluginInfrastructure");
157    }
158
159    void pluginManager_Initializing(object sender, PluginInfrastructureEventArgs e) {
160      SetStatusStrip("Initializing PluginInfrastructure");
161    }
162
163    void pluginManager_PluginUnloaded(object sender, PluginInfrastructureEventArgs e) {
164      SetStatusStrip("Unloaded " + e.Entity);
165    }
166
167    void pluginManager_PluginLoaded(object sender, PluginInfrastructureEventArgs e) {
168      SetStatusStrip("Loaded " + e.Entity);
169    }
170    #endregion
171
172    #region installation manager event handlers
173    void installationManager_PreUpdatePlugin(object sender, PluginInfrastructureCancelEventArgs e) {
174      if (e.Plugins.Count() > 0) {
175        e.Cancel = ConfirmUpdateAction(e.Plugins) == false;
176      }
177    }
178
179    void installationManager_PreRemovePlugin(object sender, PluginInfrastructureCancelEventArgs e) {
180      if (e.Plugins.Count() > 0) {
181        e.Cancel = ConfirmRemoveAction(e.Plugins) == false;
182      }
183    }
184
185    void installationManager_PreInstallPlugin(object sender, PluginInfrastructureCancelEventArgs e) {
186      if (e.Plugins.Count() > 0)
187        if (ConfirmInstallAction(e.Plugins) == true) {
188          SetStatusStrip("Installing " + e.Plugins.Aggregate("", (a, b) => a.ToString() + "; " + b.ToString()));
189          e.Cancel = false;
190        } else {
191          e.Cancel = true;
192          SetStatusStrip("Install canceled");
193        }
194    }
195
196    void installationManager_PluginUpdated(object sender, PluginInfrastructureEventArgs e) {
197      SetStatusStrip("Updated " + e.Entity);
198    }
199
200    void installationManager_PluginRemoved(object sender, PluginInfrastructureEventArgs e) {
201      SetStatusStrip("Removed " + e.Entity);
202    }
203
204    void installationManager_PluginInstalled(object sender, PluginInfrastructureEventArgs e) {
205      SetStatusStrip("Installed " + e.Entity);
206    }
207    #endregion
208
209    private void SetStatusStrip(string msg) {
210      if (InvokeRequired) Invoke((Action<string>)SetStatusStrip, msg);
211      else {
212        toolStripStatusLabel.Text = msg;
213        logTextBox.Text += DateTime.Now + ": " + msg + Environment.NewLine;
214      }
215    }
216
217    #region button events
218
219    private void refreshButton_Click(object sender, EventArgs e) {
220      RefreshRemotePluginListAsync();
221    }
222
223    private void updateButton_Click(object sender, EventArgs e) {
224      Cursor = Cursors.AppStarting;
225      toolStripProgressBar.Visible = true;
226      DisableControls();
227      var updateOrInstallInfo = new UpdateOrInstallPluginsBackgroundWorkerArgument();
228      // if there is a local plugin with same name and same major and minor version then it's an update
229      var pluginsToUpdate = from remotePlugin in remotePluginInstaller.CheckedPlugins
230                            let matchingLocalPlugins = from localPlugin in localPluginManager.Plugins
231                                                       where localPlugin.Name == remotePlugin.Name
232                                                       where localPlugin.Version.Major == remotePlugin.Version.Major
233                                                       where localPlugin.Version.Minor == remotePlugin.Version.Minor
234                                                       select localPlugin
235                            where matchingLocalPlugins.Count() > 0
236                            select remotePlugin;
237
238      // otherwise install a new plugin
239      var pluginsToInstall = remotePluginInstaller.CheckedPlugins.Except(pluginsToUpdate);
240
241      updateOrInstallInfo.PluginsToInstall = pluginsToInstall;
242      updateOrInstallInfo.PluginsToUpdate = pluginsToUpdate;
243      updateOrInstallPluginsBackgroundWorker.RunWorkerAsync(updateOrInstallInfo);
244    }
245
246    private void removeButton_Click(object sender, EventArgs e) {
247      Cursor = Cursors.AppStarting;
248      toolStripProgressBar.Visible = true;
249      DisableControls();
250      removePluginsBackgroundWorker.RunWorkerAsync(localPluginManager.CheckedPlugins);
251    }
252
253    #endregion
254
255    #region confirmation dialogs
256    private bool ConfirmRemoveAction(IEnumerable<IPluginDescription> plugins) {
257      StringBuilder strBuilder = new StringBuilder();
258      strBuilder.AppendLine("Delete files:");
259      foreach (var plugin in plugins) {
260        foreach (var file in plugin.Files) {
261          strBuilder.AppendLine(file.ToString());
262        }
263      }
264      return MessageBox.Show(strBuilder.ToString(), "Confirm Delete", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK;
265    }
266
267    private bool ConfirmUpdateAction(IEnumerable<IPluginDescription> plugins) {
268      StringBuilder strBuilder = new StringBuilder();
269      strBuilder.AppendLine("Update plugins:");
270      foreach (var plugin in plugins) {
271        strBuilder.AppendLine(plugin.ToString());
272      }
273      return MessageBox.Show(strBuilder.ToString(), "Confirm Update", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK;
274    }
275
276    private bool ConfirmInstallAction(IEnumerable<IPluginDescription> plugins) {
277      foreach (var plugin in plugins) {
278        if (!string.IsNullOrEmpty(plugin.LicenseText)) {
279          var licenseConfirmationBox = new LicenseConfirmationBox(plugin);
280          if (licenseConfirmationBox.ShowDialog() != DialogResult.OK)
281            return false;
282        }
283      }
284      return true;
285    }
286
287
288    #endregion
289
290    #region helper methods
291
292    private void UpdateLocalPluginList(IEnumerable<PluginDescription> plugins) {
293      localPluginManager.Plugins = plugins;
294    }
295
296    private void UpdateRemotePluginList(
297      IEnumerable<DeploymentService.ProductDescription> remoteProducts,
298      IEnumerable<IPluginDescription> remotePlugins) {
299
300      var mostRecentRemotePlugins = from remote in remotePlugins
301                                    where !remotePlugins.Any(x => x.Name == remote.Name && x.Version > remote.Version) // same name and higher version
302                                    select remote;
303
304      var newPlugins = from remote in mostRecentRemotePlugins
305                       let matchingLocal = (from local in localPluginManager.Plugins
306                                            where local.Name == remote.Name
307                                            where local.Version < remote.Version
308                                            select local).FirstOrDefault()
309                       where matchingLocal != null
310                       select remote;
311
312      remotePluginInstaller.NewPlugins = newPlugins;
313      remotePluginInstaller.Products = remoteProducts;
314      remotePluginInstaller.AllPlugins = remotePlugins;
315    }
316
317    private void RefreshRemotePluginListAsync() {
318      Cursor = Cursors.AppStarting;
319      toolStripProgressBar.Visible = true;
320      DisableControls();
321      refreshServerPluginsBackgroundWorker.RunWorkerAsync();
322    }
323
324    private void RefreshLocalPluginListAsync() {
325      Cursor = Cursors.AppStarting;
326      toolStripProgressBar.Visible = true;
327      DisableControls();
328      refreshLocalPluginsBackgroundWorker.RunWorkerAsync();
329    }
330
331    private void UpdateControlsDisconnected() {
332      //localPluginsListView.Enabled = false;
333      //ClearPluginsList(remotePluginsListView);
334      refreshButton.Enabled = true;
335      toolStripProgressBar.Visible = false;
336      Cursor = Cursors.Default;
337    }
338
339    private void UpdateControlsConnected() {
340      refreshButton.Enabled = true;
341      toolStripProgressBar.Visible = false;
342      Cursor = Cursors.Default;
343    }
344
345    private void DisableControls() {
346      refreshButton.Enabled = false;
347      Cursor = Cursors.Default;
348    }
349    #endregion
350
351    private void localPluginManager_ItemChecked(object sender, ItemCheckedEventArgs e) {
352      removeButton.Enabled = localPluginManager.CheckedPlugins.Count() > 0;
353    }
354
355    private void remotePluginInstaller_ItemChecked(object sender, ItemCheckedEventArgs e) {
356      installButton.Enabled = remotePluginInstaller.CheckedPlugins.Count() > 0;
357    }
358
359    private void editConnectionButton_Click(object sender, EventArgs e) {
360      (new ConnectionSetupView()).ShowInForm();
361    }
362  }
363}
Note: See TracBrowser for help on using the repository browser.