Free cookie consent management tool by TermsFeed Policy Generator

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

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

Worked on review comments by swagner. #989 (Implement review comments in plugin infrastructure)

File size: 20.9 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
21using System;
22using System.Collections.Generic;
23using System.ComponentModel;
24using System.Data;
25using System.Drawing;
26using System.Linq;
27using System.Text;
28using System.Windows.Forms;
29using System.IO;
30using HeuristicLab.PluginInfrastructure.Manager;
31
32namespace HeuristicLab.PluginInfrastructure.Advanced {
33  internal partial class InstallationManagerForm : Form {
34    private class UpdateOrInstallPluginsBackgroundWorkerArgument {
35      public IEnumerable<IPluginDescription> PluginsToUpdate { get; set; }
36      public IEnumerable<IPluginDescription> PluginsToInstall { get; set; }
37    }
38
39    private class RemovePluginsBackgroundWorkerArgument {
40      public IEnumerable<IPluginDescription> PluginsToRemove { get; set; }
41    }
42
43    private class RefreshBackgroundWorkerResult {
44      public IEnumerable<IPluginDescription> RemotePlugins { get; set; }
45      public IEnumerable<DeploymentService.ProductDescription> RemoteProducts { get; set; }
46    }
47
48    private InstallationManager installationManager;
49    private BackgroundWorker refreshServerPluginsBackgroundWorker;
50    private BackgroundWorker updateOrInstallPluginsBackgroundWorker;
51    private BackgroundWorker removePluginsBackgroundWorker;
52    private BackgroundWorker refreshLocalPluginsBackgroundWorker;
53    private BackgroundWorker updateAllPluginsBackgroundWorker;
54    private PluginManager pluginManager;
55    private string pluginDir;
56
57    public InstallationManagerForm(PluginManager pluginManager) {
58      InitializeComponent();
59      this.pluginManager = pluginManager;
60      pluginManager.PluginLoaded += pluginManager_PluginLoaded;
61      pluginManager.PluginUnloaded += pluginManager_PluginUnloaded;
62      pluginManager.Initializing += pluginManager_Initializing;
63      pluginManager.Initialized += pluginManager_Initialized;
64
65      pluginDir = Application.StartupPath;
66
67      #region initialize background workers
68      refreshServerPluginsBackgroundWorker = new BackgroundWorker();
69      refreshServerPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshServerPluginsBackgroundWorker_DoWork);
70      refreshServerPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshServerPluginsBackgroundWorker_RunWorkerCompleted);
71
72      updateOrInstallPluginsBackgroundWorker = new BackgroundWorker();
73      updateOrInstallPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(updateOrInstallPluginsBackgroundWorker_DoWork);
74      updateOrInstallPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted);
75
76      removePluginsBackgroundWorker = new BackgroundWorker();
77      removePluginsBackgroundWorker.DoWork += new DoWorkEventHandler(removePluginsBackgroundWorker_DoWork);
78      removePluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(removePluginsBackgroundWorker_RunWorkerCompleted);
79
80      refreshLocalPluginsBackgroundWorker = new BackgroundWorker();
81      refreshLocalPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshLocalPluginsBackgroundWorker_DoWork);
82      refreshLocalPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshLocalPluginsBackgroundWorker_RunWorkerCompleted);
83
84      updateAllPluginsBackgroundWorker = new BackgroundWorker();
85      updateAllPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(updateAllPluginsBackgroundWorker_DoWork);
86      updateAllPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updateAllPluginsBackgroundWorker_RunWorkerCompleted);
87      #endregion
88
89      installationManager = new InstallationManager(pluginDir);
90      installationManager.PluginInstalled += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginInstalled);
91      installationManager.PluginRemoved += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginRemoved);
92      installationManager.PluginUpdated += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginUpdated);
93      installationManager.PreInstallPlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreInstallPlugin);
94      installationManager.PreRemovePlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreRemovePlugin);
95      installationManager.PreUpdatePlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreUpdatePlugin);
96
97      // show or hide controls for uploading plugins based on setting
98      if (!HeuristicLab.PluginInfrastructure.Properties.Settings.Default.ShowPluginUploadControls) {
99        tabControl.Controls.Remove(uploadPluginsTabPage);
100        tabControl.Controls.Remove(manageProductsTabPage);
101      }
102
103      UpdateLocalPluginList(pluginManager.Plugins);
104      UpdateControlsConnected();
105    }
106
107    #region event handlers for update all plugins backgroundworker
108    void updateAllPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
109      if (e.Error != null) {
110        MessageBox.Show("There was an error while connecting to the server." + Environment.NewLine +
111           "Please check your connection settings and user credentials.");
112        UpdateControlsDisconnected();
113      } else {
114        RefreshLocalPluginListAsync();
115        UpdateControlsConnected();
116      }
117    }
118
119    void updateAllPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
120      IEnumerable<IPluginDescription> installedPlugins = (IEnumerable<IPluginDescription>)e.Argument;
121      var remotePlugins = installationManager.GetRemotePluginList();
122      // if there is a local plugin with same name and same major and minor version then it's an update
123      var pluginsToUpdate = from remotePlugin in remotePlugins
124                            let matchingLocalPlugins = from installedPlugin in installedPlugins
125                                                       where installedPlugin.Name == remotePlugin.Name
126                                                       where installedPlugin.Version.Major == remotePlugin.Version.Major
127                                                       where installedPlugin.Version.Minor == remotePlugin.Version.Minor
128                                                       where installedPlugin.Version.Build <= remotePlugin.Version.Build ||
129                                                         installedPlugin.Version.Revision < remotePlugin.Version.Revision
130                                                       select installedPlugin
131                            where matchingLocalPlugins.Count() > 0
132                            select remotePlugin;
133      installationManager.Update(pluginsToUpdate);
134    }
135    #endregion
136
137    #region event handlers for refresh local plugin list backgroundworker
138    void refreshLocalPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
139      if (!e.Cancelled && e.Error == null) {
140        UpdateLocalPluginList((IEnumerable<PluginDescription>)e.Result);
141        UpdateControlsConnected();
142      }
143    }
144
145    void refreshLocalPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
146      pluginManager.DiscoverAndCheckPlugins();
147      e.Result = new List<PluginDescription>(pluginManager.Plugins);
148    }
149    #endregion
150
151    #region event handlers for plugin removal background worker
152    void removePluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
153      if (e.Error != null) {
154        MessageBox.Show("There was problem while deleting files." + Environment.NewLine +
155              e.Error.Message);
156        UpdateControlsDisconnected();
157      } else {
158        RefreshLocalPluginListAsync();
159        UpdateControlsConnected();
160      }
161    }
162
163    void removePluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
164      IEnumerable<IPluginDescription> pluginsToRemove = (IEnumerable<IPluginDescription>)e.Argument;
165      installationManager.Remove(pluginsToRemove);
166    }
167    #endregion
168
169    #region event handlers for plugin update background worker
170    void updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
171      if (e.Error != null) {
172        MessageBox.Show("There was an error while connecting to the server." + Environment.NewLine +
173          "Please check your connection settings and user credentials.");
174        UpdateControlsDisconnected();
175      } else {
176        RefreshLocalPluginListAsync();
177        RefreshRemotePluginListAsync();
178        UpdateControlsConnected();
179      }
180    }
181
182    void updateOrInstallPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
183      UpdateOrInstallPluginsBackgroundWorkerArgument info = (UpdateOrInstallPluginsBackgroundWorkerArgument)e.Argument;
184      installationManager.Install(info.PluginsToInstall);
185      installationManager.Update(info.PluginsToUpdate);
186    }
187    #endregion
188
189    #region event handlers for refresh server plugins background worker
190    void refreshServerPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
191      if (e.Error != null) {
192        MessageBox.Show("There was an error while connecting to the server." + Environment.NewLine +
193          "Please check your connection settings and user credentials.");
194        UpdateControlsDisconnected();
195      } else {
196        RefreshBackgroundWorkerResult refreshResult = (RefreshBackgroundWorkerResult)e.Result;
197        UpdateRemotePluginList(refreshResult.RemoteProducts, refreshResult.RemotePlugins);
198        UpdateControlsConnected();
199      }
200    }
201
202    void refreshServerPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
203      RefreshBackgroundWorkerResult result = new RefreshBackgroundWorkerResult();
204      result.RemotePlugins = installationManager.GetRemotePluginList();
205      result.RemoteProducts = installationManager.GetRemoteProductList();
206      e.Cancel = false;
207      e.Result = result;
208    }
209
210
211
212    #endregion
213
214    #region plugin manager event handlers
215    void pluginManager_Initialized(object sender, PluginInfrastructureEventArgs e) {
216      SetStatusStrip("Initialized PluginInfrastructure");
217    }
218
219    void pluginManager_Initializing(object sender, PluginInfrastructureEventArgs e) {
220      SetStatusStrip("Initializing PluginInfrastructure");
221    }
222
223    void pluginManager_PluginUnloaded(object sender, PluginInfrastructureEventArgs e) {
224      SetStatusStrip("Unloaded " + e.Entity);
225    }
226
227    void pluginManager_PluginLoaded(object sender, PluginInfrastructureEventArgs e) {
228      SetStatusStrip("Loaded " + e.Entity);
229    }
230    #endregion
231
232    #region installation manager event handlers
233    void installationManager_PreUpdatePlugin(object sender, PluginInfrastructureCancelEventArgs e) {
234      if (e.Plugins.Count() > 0) {
235        e.Cancel = ConfirmUpdateAction(e.Plugins) == false;
236      }
237    }
238
239    void installationManager_PreRemovePlugin(object sender, PluginInfrastructureCancelEventArgs e) {
240      if (e.Plugins.Count() > 0) {
241        e.Cancel = ConfirmRemoveAction(e.Plugins) == false;
242      }
243    }
244
245    void installationManager_PreInstallPlugin(object sender, PluginInfrastructureCancelEventArgs e) {
246      if (e.Plugins.Count() > 0)
247        if (ConfirmInstallAction(e.Plugins) == true) {
248          SetStatusStrip("Installing " + e.Plugins.Aggregate("", (a, b) => a.ToString() + "; " + b.ToString()));
249          e.Cancel = false;
250        } else {
251          e.Cancel = true;
252          SetStatusStrip("Install canceled");
253        }
254    }
255
256    void installationManager_PluginUpdated(object sender, PluginInfrastructureEventArgs e) {
257      SetStatusStrip("Updated " + e.Entity);
258    }
259
260    void installationManager_PluginRemoved(object sender, PluginInfrastructureEventArgs e) {
261      SetStatusStrip("Removed " + e.Entity);
262    }
263
264    void installationManager_PluginInstalled(object sender, PluginInfrastructureEventArgs e) {
265      SetStatusStrip("Installed " + e.Entity);
266    }
267    #endregion
268
269
270
271    #region button events
272
273    private void refreshRemoteButton_Click(object sender, EventArgs e) {
274      Cursor = Cursors.AppStarting;
275      RefreshRemotePluginListAsync();
276      toolStripProgressBar.Visible = true;
277      DisableControls();
278    }
279
280    private void updateOrInstallButton_Click(object sender, EventArgs e) {
281      Cursor = Cursors.AppStarting;
282      toolStripProgressBar.Visible = true;
283      DisableControls();
284      var updateOrInstallInfo = new UpdateOrInstallPluginsBackgroundWorkerArgument();
285      // if there is a local plugin with same name and same major and minor version then it's an update
286      var pluginsToUpdate = from remotePlugin in remotePluginInstaller.CheckedPlugins
287                            let matchingLocalPlugins = from localPlugin in localPluginManagerView.Plugins
288                                                       where localPlugin.Name == remotePlugin.Name
289                                                       where localPlugin.Version.Major == remotePlugin.Version.Major
290                                                       where localPlugin.Version.Minor == remotePlugin.Version.Minor
291                                                       select localPlugin
292                            where matchingLocalPlugins.Count() > 0
293                            select remotePlugin;
294
295      // otherwise install a new plugin
296      var pluginsToInstall = remotePluginInstaller.CheckedPlugins.Except(pluginsToUpdate);
297
298      updateOrInstallInfo.PluginsToInstall = pluginsToInstall;
299      updateOrInstallInfo.PluginsToUpdate = pluginsToUpdate;
300      updateOrInstallPluginsBackgroundWorker.RunWorkerAsync(updateOrInstallInfo);
301    }
302
303    private void removeLocalButton_Click(object sender, EventArgs e) {
304      Cursor = Cursors.AppStarting;
305      toolStripProgressBar.Visible = true;
306      DisableControls();
307      removePluginsBackgroundWorker.RunWorkerAsync(localPluginManagerView.CheckedPlugins);
308    }
309
310    private void updateAllButton_Click(object sender, EventArgs e) {
311      Cursor = Cursors.AppStarting;
312      toolStripProgressBar.Visible = true;
313      updateButton.Enabled = false;
314      var installedPlugins = pluginManager.Plugins.OfType<IPluginDescription>();
315      updateAllPluginsBackgroundWorker.RunWorkerAsync(installedPlugins);
316    }
317
318    private void connectionSettingsToolStripMenuItem_Click(object sender, EventArgs e) {
319      new ConnectionSetupView().ShowDialog();
320    }
321
322    private void tabControl_Selected(object sender, TabControlEventArgs e) {
323      viewToolStripMenuItem.Enabled = e.TabPage == availablePluginsTabPage;
324    }
325
326    private void simpleToolStripMenuItem_Click(object sender, EventArgs e) {
327      remotePluginInstaller.ShowAllPlugins = false;
328      advancedToolStripMenuItem.Checked = false;
329    }
330
331    private void advancedToolStripMenuItem_Click(object sender, EventArgs e) {
332      remotePluginInstaller.ShowAllPlugins = true;
333      simpleToolStripMenuItem.Checked = false;
334    }
335    #endregion
336
337    #region confirmation dialogs
338    private bool ConfirmRemoveAction(IEnumerable<IPluginDescription> plugins) {
339      StringBuilder strBuilder = new StringBuilder();
340      foreach (var plugin in plugins) {
341        foreach (var file in plugin.Files) {
342          strBuilder.AppendLine(Path.GetFileName(file.Name));
343        }
344      }
345      return (new ConfirmationDialog("Confirm Delete", "Do you want to delete following files?", strBuilder.ToString())).ShowDialog() == DialogResult.OK;
346    }
347
348    private bool ConfirmUpdateAction(IEnumerable<IPluginDescription> plugins) {
349      StringBuilder strBuilder = new StringBuilder();
350      foreach (var plugin in plugins) {
351        strBuilder.AppendLine(plugin.ToString());
352      }
353      return (new ConfirmationDialog("Confirm Update", "Do you want to update following plugins?", strBuilder.ToString())).ShowDialog() == DialogResult.OK;
354    }
355
356    private bool ConfirmInstallAction(IEnumerable<IPluginDescription> plugins) {
357      foreach (var plugin in plugins) {
358        if (!string.IsNullOrEmpty(plugin.LicenseText)) {
359          var licenseConfirmationBox = new LicenseConfirmationBox(plugin);
360          if (licenseConfirmationBox.ShowDialog() != DialogResult.OK)
361            return false;
362        }
363      }
364      return true;
365    }
366
367
368    #endregion
369
370    #region helper methods
371    private void SetStatusStrip(string msg) {
372      if (InvokeRequired) Invoke((Action<string>)SetStatusStrip, msg);
373      else {
374        toolStripStatusLabel.Text = msg;
375        logTextBox.Text += DateTime.Now + ": " + msg + Environment.NewLine;
376      }
377    }
378
379    private void UpdateLocalPluginList(IEnumerable<PluginDescription> plugins) {
380      localPluginManagerView.Plugins = plugins;
381    }
382
383    private void UpdateRemotePluginList(
384      IEnumerable<DeploymentService.ProductDescription> remoteProducts,
385      IEnumerable<IPluginDescription> remotePlugins) {
386
387      var mostRecentRemotePlugins = from remote in remotePlugins
388                                    where !remotePlugins.Any(x => x.Name == remote.Name && x.Version > remote.Version) // same name and higher version
389                                    select remote;
390
391      var newPlugins = from remote in mostRecentRemotePlugins
392                       let matchingLocal = (from local in localPluginManagerView.Plugins
393                                            where local.Name == remote.Name
394                                            where local.Version < remote.Version
395                                            select local).FirstOrDefault()
396                       where matchingLocal != null
397                       select remote;
398
399      remotePluginInstaller.NewPlugins = newPlugins;
400      remotePluginInstaller.Products = remoteProducts;
401      remotePluginInstaller.AllPlugins = remotePlugins;
402    }
403
404    private void RefreshRemotePluginListAsync() {
405      Cursor = Cursors.AppStarting;
406      toolStripProgressBar.Visible = true;
407      refreshButton.Enabled = false;
408      refreshServerPluginsBackgroundWorker.RunWorkerAsync();
409    }
410
411    private void RefreshLocalPluginListAsync() {
412      Cursor = Cursors.AppStarting;
413      toolStripProgressBar.Visible = true;
414      DisableControls();
415      refreshLocalPluginsBackgroundWorker.RunWorkerAsync();
416    }
417
418    private void UpdateControlsDisconnected() {
419      //localPluginsListView.Enabled = false;
420      //ClearPluginsList(remotePluginsListView);
421      refreshButton.Enabled = true;
422      toolStripProgressBar.Visible = false;
423      Cursor = Cursors.Default;
424    }
425
426    private void UpdateControlsConnected() {
427      refreshButton.Enabled = true;
428      updateButton.Enabled = true;
429      toolStripProgressBar.Visible = false;
430      Cursor = Cursors.Default;
431    }
432
433    private void DisableControls() {
434      refreshButton.Enabled = false;
435      Cursor = Cursors.Default;
436    }
437    #endregion
438
439    private void localPluginManager_ItemChecked(object sender, ItemCheckedEventArgs e) {
440      removeButton.Enabled = localPluginManagerView.CheckedPlugins.Count() > 0;
441    }
442
443    private void remotePluginInstaller_ItemChecked(object sender, ItemCheckedEventArgs e) {
444      installButton.Enabled = remotePluginInstaller.CheckedPlugins.Count() > 0;
445    }
446
447    protected override void OnClosing(CancelEventArgs e) {
448      installationManager.PluginInstalled -= new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginInstalled);
449      installationManager.PluginRemoved -= new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginRemoved);
450      installationManager.PluginUpdated -= new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginUpdated);
451      installationManager.PreInstallPlugin -= new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreInstallPlugin);
452      installationManager.PreRemovePlugin -= new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreRemovePlugin);
453      installationManager.PreUpdatePlugin -= new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreUpdatePlugin);
454      base.OnClosing(e);
455    }
456
457
458
459
460  }
461}
Note: See TracBrowser for help on using the repository browser.