Free cookie consent management tool by TermsFeed Policy Generator

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

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

Incorporated review comments by swagner into plugin infrastructure. #989 (Implement review comments in plugin infrastructure)

File size: 17.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
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 PluginManager pluginManager;
54    private string pluginDir;
55
56    public InstallationManagerForm(PluginManager pluginManager) {
57      InitializeComponent();
58      this.pluginManager = pluginManager;
59      pluginManager.PluginLoaded += pluginManager_PluginLoaded;
60      pluginManager.PluginUnloaded += pluginManager_PluginUnloaded;
61      pluginManager.Initializing += pluginManager_Initializing;
62      pluginManager.Initialized += pluginManager_Initialized;
63
64      pluginDir = Application.StartupPath;
65
66      #region initialize background workers
67      refreshServerPluginsBackgroundWorker = new BackgroundWorker();
68      refreshServerPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshServerPluginsBackgroundWorker_DoWork);
69      refreshServerPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshServerPluginsBackgroundWorker_RunWorkerCompleted);
70
71      updateOrInstallPluginsBackgroundWorker = new BackgroundWorker();
72      updateOrInstallPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(updateOrInstallPluginsBackgroundWorker_DoWork);
73      updateOrInstallPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted);
74
75      removePluginsBackgroundWorker = new BackgroundWorker();
76      removePluginsBackgroundWorker.DoWork += new DoWorkEventHandler(removePluginsBackgroundWorker_DoWork);
77      removePluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(removePluginsBackgroundWorker_RunWorkerCompleted);
78
79      refreshLocalPluginsBackgroundWorker = new BackgroundWorker();
80      refreshLocalPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshLocalPluginsBackgroundWorker_DoWork);
81      refreshLocalPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshLocalPluginsBackgroundWorker_RunWorkerCompleted);
82      #endregion
83
84      installationManager = new InstallationManager(pluginDir);
85      installationManager.PluginInstalled += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginInstalled);
86      installationManager.PluginRemoved += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginRemoved);
87      installationManager.PluginUpdated += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginUpdated);
88      installationManager.PreInstallPlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreInstallPlugin);
89      installationManager.PreRemovePlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreRemovePlugin);
90      installationManager.PreUpdatePlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreUpdatePlugin);
91
92      RefreshLocalPluginListAsync();
93    }
94
95    #region event handlers for refresh local plugin list backgroundworker
96    void refreshLocalPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
97      if (!e.Cancelled && e.Error == null) {
98        UpdateLocalPluginList((IEnumerable<PluginDescription>)e.Result);
99        UpdateControlsConnected();
100      }
101    }
102
103    void refreshLocalPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
104      pluginManager.DiscoverAndCheckPlugins();
105      e.Result = new List<PluginDescription>(pluginManager.Plugins);
106    }
107    #endregion
108
109    #region event handlers for plugin removal background worker
110    void removePluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
111      if (!e.Cancelled && e.Error == null) {
112        RefreshLocalPluginListAsync();
113        UpdateControlsConnected();
114      }
115    }
116
117    void removePluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
118      IEnumerable<IPluginDescription> pluginsToRemove = (IEnumerable<IPluginDescription>)e.Argument;
119      installationManager.Remove(pluginsToRemove);
120    }
121    #endregion
122
123    #region event handlers for plugin update background worker
124    void updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
125      if (!e.Cancelled && e.Error == null) {
126        RefreshLocalPluginListAsync();
127        RefreshRemotePluginListAsync();
128        UpdateControlsConnected();
129      } else {
130        UpdateControlsDisconnected();
131      }
132    }
133
134    void updateOrInstallPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
135      UpdateOrInstallPluginsBackgroundWorkerArgument info = (UpdateOrInstallPluginsBackgroundWorkerArgument)e.Argument;
136      installationManager.Install(info.PluginsToInstall);
137      installationManager.Update(info.PluginsToUpdate);
138    }
139    #endregion
140
141    #region event handlers for refresh server plugins background worker
142    void refreshServerPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
143      if (!e.Cancelled && e.Result != null) {
144        RefreshBackgroundWorkerResult refreshResult = (RefreshBackgroundWorkerResult)e.Result;
145        UpdateRemotePluginList(refreshResult.RemoteProducts, refreshResult.RemotePlugins);
146        UpdateControlsConnected();
147      } else {
148        UpdateControlsDisconnected();
149      }
150    }
151
152    void refreshServerPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
153      RefreshBackgroundWorkerResult result = new RefreshBackgroundWorkerResult();
154      result.RemotePlugins = installationManager.GetRemotePluginList();
155      result.RemoteProducts = installationManager.GetRemoteProductList();
156      e.Cancel = false;
157      e.Result = result;
158    }
159
160
161
162    #endregion
163
164    #region plugin manager event handlers
165    void pluginManager_Initialized(object sender, PluginInfrastructureEventArgs e) {
166      SetStatusStrip("Initialized PluginInfrastructure");
167    }
168
169    void pluginManager_Initializing(object sender, PluginInfrastructureEventArgs e) {
170      SetStatusStrip("Initializing PluginInfrastructure");
171    }
172
173    void pluginManager_PluginUnloaded(object sender, PluginInfrastructureEventArgs e) {
174      SetStatusStrip("Unloaded " + e.Entity);
175    }
176
177    void pluginManager_PluginLoaded(object sender, PluginInfrastructureEventArgs e) {
178      SetStatusStrip("Loaded " + e.Entity);
179    }
180    #endregion
181
182    #region installation manager event handlers
183    void installationManager_PreUpdatePlugin(object sender, PluginInfrastructureCancelEventArgs e) {
184      if (e.Plugins.Count() > 0) {
185        e.Cancel = ConfirmUpdateAction(e.Plugins) == false;
186      }
187    }
188
189    void installationManager_PreRemovePlugin(object sender, PluginInfrastructureCancelEventArgs e) {
190      if (e.Plugins.Count() > 0) {
191        e.Cancel = ConfirmRemoveAction(e.Plugins) == false;
192      }
193    }
194
195    void installationManager_PreInstallPlugin(object sender, PluginInfrastructureCancelEventArgs e) {
196      if (e.Plugins.Count() > 0)
197        if (ConfirmInstallAction(e.Plugins) == true) {
198          SetStatusStrip("Installing " + e.Plugins.Aggregate("", (a, b) => a.ToString() + "; " + b.ToString()));
199          e.Cancel = false;
200        } else {
201          e.Cancel = true;
202          SetStatusStrip("Install canceled");
203        }
204    }
205
206    void installationManager_PluginUpdated(object sender, PluginInfrastructureEventArgs e) {
207      SetStatusStrip("Updated " + e.Entity);
208    }
209
210    void installationManager_PluginRemoved(object sender, PluginInfrastructureEventArgs e) {
211      SetStatusStrip("Removed " + e.Entity);
212    }
213
214    void installationManager_PluginInstalled(object sender, PluginInfrastructureEventArgs e) {
215      SetStatusStrip("Installed " + e.Entity);
216    }
217    #endregion
218
219    private void SetStatusStrip(string msg) {
220      if (InvokeRequired) Invoke((Action<string>)SetStatusStrip, msg);
221      else {
222        toolStripStatusLabel.Text = msg;
223        logTextBox.Text += DateTime.Now + ": " + msg + Environment.NewLine;
224      }
225    }
226
227    #region button events
228
229    private void refreshButton_Click(object sender, EventArgs e) {
230      RefreshRemotePluginListAsync();
231    }
232
233    private void updateButton_Click(object sender, EventArgs e) {
234      Cursor = Cursors.AppStarting;
235      toolStripProgressBar.Visible = true;
236      DisableControls();
237      var updateOrInstallInfo = new UpdateOrInstallPluginsBackgroundWorkerArgument();
238      // if there is a local plugin with same name and same major and minor version then it's an update
239      var pluginsToUpdate = from remotePlugin in remotePluginInstaller.CheckedPlugins
240                            let matchingLocalPlugins = from localPlugin in localPluginManagerView.Plugins
241                                                       where localPlugin.Name == remotePlugin.Name
242                                                       where localPlugin.Version.Major == remotePlugin.Version.Major
243                                                       where localPlugin.Version.Minor == remotePlugin.Version.Minor
244                                                       select localPlugin
245                            where matchingLocalPlugins.Count() > 0
246                            select remotePlugin;
247
248      // otherwise install a new plugin
249      var pluginsToInstall = remotePluginInstaller.CheckedPlugins.Except(pluginsToUpdate);
250
251      updateOrInstallInfo.PluginsToInstall = pluginsToInstall;
252      updateOrInstallInfo.PluginsToUpdate = pluginsToUpdate;
253      updateOrInstallPluginsBackgroundWorker.RunWorkerAsync(updateOrInstallInfo);
254    }
255
256    private void removeButton_Click(object sender, EventArgs e) {
257      Cursor = Cursors.AppStarting;
258      toolStripProgressBar.Visible = true;
259      DisableControls();
260      removePluginsBackgroundWorker.RunWorkerAsync(localPluginManagerView.CheckedPlugins);
261    }
262
263    #endregion
264
265    #region confirmation dialogs
266    private bool ConfirmRemoveAction(IEnumerable<IPluginDescription> plugins) {
267      StringBuilder strBuilder = new StringBuilder();
268      foreach (var plugin in plugins) {
269        foreach (var file in plugin.Files) {
270          strBuilder.AppendLine(Path.GetFileName(file.Name));
271        }
272      }
273      return (new ConfirmationDialog("Confirm Delete", "Do you want to delete following files?", strBuilder.ToString())).ShowDialog() == DialogResult.OK;
274    }
275
276    private bool ConfirmUpdateAction(IEnumerable<IPluginDescription> plugins) {
277      StringBuilder strBuilder = new StringBuilder();
278      foreach (var plugin in plugins) {
279        strBuilder.AppendLine(plugin.ToString());
280      }
281      return (new ConfirmationDialog("Confirm Update", "Do you want to update following plugins?", strBuilder.ToString())).ShowDialog() == DialogResult.OK;
282    }
283
284    private bool ConfirmInstallAction(IEnumerable<IPluginDescription> plugins) {
285      foreach (var plugin in plugins) {
286        if (!string.IsNullOrEmpty(plugin.LicenseText)) {
287          var licenseConfirmationBox = new LicenseConfirmationBox(plugin);
288          if (licenseConfirmationBox.ShowDialog() != DialogResult.OK)
289            return false;
290        }
291      }
292      return true;
293    }
294
295
296    #endregion
297
298    #region helper methods
299
300    private void UpdateLocalPluginList(IEnumerable<PluginDescription> plugins) {
301      localPluginManagerView.Plugins = plugins;
302    }
303
304    private void UpdateRemotePluginList(
305      IEnumerable<DeploymentService.ProductDescription> remoteProducts,
306      IEnumerable<IPluginDescription> remotePlugins) {
307
308      var mostRecentRemotePlugins = from remote in remotePlugins
309                                    where !remotePlugins.Any(x => x.Name == remote.Name && x.Version > remote.Version) // same name and higher version
310                                    select remote;
311
312      var newPlugins = from remote in mostRecentRemotePlugins
313                       let matchingLocal = (from local in localPluginManagerView.Plugins
314                                            where local.Name == remote.Name
315                                            where local.Version < remote.Version
316                                            select local).FirstOrDefault()
317                       where matchingLocal != null
318                       select remote;
319
320      remotePluginInstaller.NewPlugins = newPlugins;
321      remotePluginInstaller.Products = remoteProducts;
322      remotePluginInstaller.AllPlugins = remotePlugins;
323    }
324
325    private void RefreshRemotePluginListAsync() {
326      Cursor = Cursors.AppStarting;
327      toolStripProgressBar.Visible = true;
328      refreshButton.Enabled = false;
329      refreshServerPluginsBackgroundWorker.RunWorkerAsync();
330    }
331
332    private void RefreshLocalPluginListAsync() {
333      Cursor = Cursors.AppStarting;
334      toolStripProgressBar.Visible = true;
335      DisableControls();
336      refreshLocalPluginsBackgroundWorker.RunWorkerAsync();
337    }
338
339    private void UpdateControlsDisconnected() {
340      //localPluginsListView.Enabled = false;
341      //ClearPluginsList(remotePluginsListView);
342      refreshButton.Enabled = true;
343      toolStripProgressBar.Visible = false;
344      Cursor = Cursors.Default;
345    }
346
347    private void UpdateControlsConnected() {
348      refreshButton.Enabled = true;
349      toolStripProgressBar.Visible = false;
350      Cursor = Cursors.Default;
351    }
352
353    private void DisableControls() {
354      refreshButton.Enabled = false;
355      Cursor = Cursors.Default;
356    }
357    #endregion
358
359    private void localPluginManager_ItemChecked(object sender, ItemCheckedEventArgs e) {
360      removeButton.Enabled = localPluginManagerView.CheckedPlugins.Count() > 0;
361    }
362
363    private void remotePluginInstaller_ItemChecked(object sender, ItemCheckedEventArgs e) {
364      installButton.Enabled = remotePluginInstaller.CheckedPlugins.Count() > 0;
365    }
366
367    private void editConnectionButton_Click(object sender, EventArgs e) {
368    }
369
370    protected override void OnClosing(CancelEventArgs e) {
371      installationManager.PluginInstalled -= new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginInstalled);
372      installationManager.PluginRemoved -= new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginRemoved);
373      installationManager.PluginUpdated -= new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginUpdated);
374      installationManager.PreInstallPlugin -= new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreInstallPlugin);
375      installationManager.PreRemovePlugin -= new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreRemovePlugin);
376      installationManager.PreUpdatePlugin -= new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreUpdatePlugin);
377      base.OnClosing(e);
378    }
379
380    private void connectionSettingsToolStripMenuItem_Click(object sender, EventArgs e) {
381      new ConnectionSetupView().ShowDialog();
382    }
383
384    private void tabControl_Selected(object sender, TabControlEventArgs e) {
385      viewToolStripMenuItem.Enabled = e.TabPage == availablePluginsTabPage;
386    }
387
388    private void simpleToolStripMenuItem_Click(object sender, EventArgs e) {
389
390    }
391
392    private void advancedToolStripMenuItem_Click(object sender, EventArgs e) {
393
394    }
395  }
396}
Note: See TracBrowser for help on using the repository browser.