Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.PluginInfrastructure/Advanced/PluginEditor.cs @ 3612

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

Implemented change requests of reviewers. #989 (Implement review comments in plugin infrastructure)

File size: 12.3 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.ComponentModel;
25using System.Drawing;
26using System.Data;
27using System.Linq;
28using System.Text;
29using System.Windows.Forms;
30using System.ServiceModel;
31using ICSharpCode.SharpZipLib.Zip;
32using System.IO;
33using HeuristicLab.PluginInfrastructure.Manager;
34
35namespace HeuristicLab.PluginInfrastructure.Advanced {
36  internal partial class PluginEditor : InstallationManagerControl {
37    private const string UploadMessage = "Uploading plugins...";
38    private const string RefreshMessage = "Downloading plugin information from deployment service...";
39
40    private Dictionary<IPluginDescription, IPluginDescription> localAndServerPlugins;
41    private BackgroundWorker pluginUploadWorker;
42    private BackgroundWorker refreshPluginsWorker;
43
44    private PluginManager pluginManager;
45    public PluginManager PluginManager {
46      get { return pluginManager; }
47      set { pluginManager = value; }
48    }
49
50    public PluginEditor() {
51      InitializeComponent();
52      pluginImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.Resources.plugin_16);
53      localAndServerPlugins = new Dictionary<IPluginDescription, IPluginDescription>();
54
55      #region initialize backgroundworkers
56      pluginUploadWorker = new BackgroundWorker();
57      pluginUploadWorker.DoWork += new DoWorkEventHandler(pluginUploadWorker_DoWork);
58      pluginUploadWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(pluginUploadWorker_RunWorkerCompleted);
59
60      refreshPluginsWorker = new BackgroundWorker();
61      refreshPluginsWorker.DoWork += new DoWorkEventHandler(refreshPluginsWorker_DoWork);
62      refreshPluginsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshPluginsWorker_RunWorkerCompleted);
63      #endregion
64    }
65
66    #region refresh plugins from server backgroundworker
67    void refreshPluginsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
68      if (e.Error != null) {
69        StatusView.ShowError("Connection Error",
70          "There was an error while connecting to the server." + Environment.NewLine +
71                   "Please check your connection settings and user credentials.");
72      } else {
73        UpdatePluginListView((IEnumerable<IPluginDescription>)e.Result);
74      }
75      StatusView.HideProgressIndicator();
76      StatusView.RemoveMessage(RefreshMessage);
77      StatusView.UnlockUI();
78    }
79
80    void refreshPluginsWorker_DoWork(object sender, DoWorkEventArgs e) {
81      // refresh available plugins
82      var client = DeploymentService.UpdateClientFactory.CreateClient();
83      try {
84        e.Result = client.GetPlugins();
85        client.Close();
86      }
87      catch (TimeoutException) {
88        client.Abort();
89        throw;
90      }
91      catch (FaultException) {
92        client.Abort();
93        throw;
94      }
95      catch (CommunicationException) {
96        client.Abort();
97        throw;
98      }
99    }
100    #endregion
101
102    #region upload plugins to server backgroundworker
103    void pluginUploadWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
104      if (e.Error != null) {
105        StatusView.ShowError("Connection Error",
106          "There was an error while connecting to the server." + Environment.NewLine +
107                   "Please check your connection settings and user credentials.");
108      } else {
109        UpdatePluginListView((IEnumerable<IPluginDescription>)e.Result);
110      }
111      StatusView.RemoveMessage(UploadMessage);
112      StatusView.HideProgressIndicator();
113      StatusView.UnlockUI();
114    }
115
116    void pluginUploadWorker_DoWork(object sender, DoWorkEventArgs e) {
117      // upload plugins
118      var selectedPlugins = (IEnumerable<IPluginDescription>)e.Argument;
119      DeploymentService.AdminClient adminClient = DeploymentService.AdminClientFactory.CreateClient();
120      try {
121        foreach (var plugin in IteratePlugins(selectedPlugins)) {
122          adminClient.DeployPlugin(MakePluginDescription(plugin), CreateZipPackage(plugin));
123        }
124        adminClient.Close();
125      }
126      catch (TimeoutException) {
127        adminClient.Abort();
128        throw;
129      }
130      catch (FaultException) {
131        adminClient.Abort();
132        throw;
133      }
134      catch (CommunicationException) {
135        adminClient.Abort();
136        throw;
137      }
138      // refresh available plugins
139      var client = DeploymentService.UpdateClientFactory.CreateClient();
140      try {
141        e.Result = client.GetPlugins();
142        client.Close();
143      }
144      catch (TimeoutException) {
145        client.Abort();
146        throw;
147      }
148      catch (FaultException) {
149        client.Abort();
150        throw;
151      }
152      catch (CommunicationException) {
153        client.Abort();
154        throw;
155      }
156    }
157    #endregion
158
159
160    #region button events
161    private void uploadButton_Click(object sender, EventArgs e) {
162      var selectedPlugins = from item in listView.Items.Cast<ListViewItem>()
163                            where item.Checked
164                            where item.Tag is IPluginDescription
165                            select item.Tag as IPluginDescription;
166      if (selectedPlugins.Count() > 0) {
167        StatusView.LockUI();
168        StatusView.ShowProgressIndicator();
169        StatusView.ShowMessage(UploadMessage);
170        pluginUploadWorker.RunWorkerAsync(selectedPlugins.ToList());
171      }
172    }
173
174    private void refreshButton_Click(object sender, EventArgs e) {
175      StatusView.LockUI();
176      StatusView.ShowProgressIndicator();
177      StatusView.ShowMessage(RefreshMessage);
178      refreshPluginsWorker.RunWorkerAsync();
179    }
180
181    #endregion
182
183    #region item list events
184    private bool ignoreItemCheckedEvents = false;
185    private void listView_ItemChecked(object sender, ItemCheckedEventArgs e) {
186      if (ignoreItemCheckedEvents) return;
187      List<IPluginDescription> modifiedPlugins = new List<IPluginDescription>();
188      if (e.Item.Checked) {
189        foreach (ListViewItem item in listView.SelectedItems) {
190          var plugin = (IPluginDescription)item.Tag;
191          // also check all dependencies
192          if (!modifiedPlugins.Contains(plugin))
193            modifiedPlugins.Add(plugin);
194          foreach (var dep in GetAllDependencies(plugin)) {
195            if (!modifiedPlugins.Contains(dep))
196              modifiedPlugins.Add(dep);
197          }
198        }
199        listView.CheckItems(modifiedPlugins.Select(x => FindItemForPlugin(x)));
200      } else {
201        foreach (ListViewItem item in listView.SelectedItems) {
202          var plugin = (IPluginDescription)item.Tag;
203          // also uncheck all dependent plugins
204          if (!modifiedPlugins.Contains(plugin))
205            modifiedPlugins.Add(plugin);
206          foreach (var dep in GetAllDependents(plugin)) {
207            if (!modifiedPlugins.Contains(dep))
208              modifiedPlugins.Add(dep);
209          }
210        }
211        listView.UncheckItems(modifiedPlugins.Select(x => FindItemForPlugin(x)));
212      }
213      uploadButton.Enabled = (from i in listView.Items.OfType<ListViewItem>()
214                              where i.Checked
215                              select i).Any();
216    }
217    #endregion
218
219    #region helper methods
220    private void UpdatePluginListView(IEnumerable<IPluginDescription> remotePlugins) {
221      // refresh local plugins
222      localAndServerPlugins.Clear();
223      foreach (var plugin in pluginManager.Plugins) {
224        localAndServerPlugins.Add(plugin, null);
225      }
226      foreach (var plugin in remotePlugins) {
227        var matchingLocalPlugin = (from localPlugin in localAndServerPlugins.Keys
228                                   where localPlugin.Name == plugin.Name
229                                   where localPlugin.Version == localPlugin.Version
230                                   select localPlugin).SingleOrDefault();
231        if (matchingLocalPlugin != null) {
232          localAndServerPlugins[matchingLocalPlugin] = plugin;
233        }
234      }
235      // refresh the list view with plugins
236      listView.Items.Clear();
237      ignoreItemCheckedEvents = true;
238      foreach (var pair in localAndServerPlugins) {
239        var item = MakeListViewItem(pair.Key);
240        listView.Items.Add(item);
241      }
242      foreach (ColumnHeader column in listView.Columns)
243        if (listView.Items.Count > 0)
244          column.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
245        else column.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
246      ignoreItemCheckedEvents = false;
247    }
248
249    private IEnumerable<IPluginDescription> GetAllDependents(IPluginDescription plugin) {
250      return from p in localAndServerPlugins.Keys
251             let matchingEntries = from dep in GetAllDependencies(p)
252                                   where dep.Name == plugin.Name
253                                   where dep.Version == plugin.Version
254                                   select dep
255             where matchingEntries.Any()
256             select p;
257    }
258
259    private IEnumerable<IPluginDescription> GetAllDependencies(IPluginDescription plugin) {
260      foreach (var dep in plugin.Dependencies) {
261        foreach (var recDep in GetAllDependencies(dep)) {
262          yield return recDep;
263        }
264        yield return dep;
265      }
266    }
267
268    private IEnumerable<IPluginDescription> IteratePlugins(IEnumerable<IPluginDescription> plugins) {
269      HashSet<IPluginDescription> yieldedItems = new HashSet<IPluginDescription>();
270      foreach (var plugin in plugins) {
271        foreach (var dependency in IteratePlugins(plugin.Dependencies)) {
272          if (!yieldedItems.Contains(dependency)) {
273            yieldedItems.Add(dependency);
274            yield return dependency;
275          }
276        }
277        if (!yieldedItems.Contains(plugin)) {
278          yieldedItems.Add(plugin);
279          yield return plugin;
280        }
281      }
282    }
283
284    private byte[] CreateZipPackage(IPluginDescription plugin) {
285      using (MemoryStream stream = new MemoryStream()) {
286        ZipFile zipFile = new ZipFile(stream);
287        zipFile.BeginUpdate();
288        foreach (var file in plugin.Files) {
289          zipFile.Add(file.Name);
290        }
291        zipFile.CommitUpdate();
292        stream.Seek(0, SeekOrigin.Begin);
293        return stream.GetBuffer();
294      }
295    }
296
297    private ListViewItem MakeListViewItem(IPluginDescription plugin) {
298      ListViewItem item;
299      if (localAndServerPlugins[plugin] != null) {
300        item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(),
301          localAndServerPlugins[plugin].Version.ToString(), localAndServerPlugins[plugin].Description });
302      } else {
303        item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(),
304          string.Empty, plugin.Description });
305      }
306      item.Tag = plugin;
307      item.ImageIndex = 0;
308      item.Checked = false;
309      return item;
310    }
311
312    private ListViewItem FindItemForPlugin(IPluginDescription dep) {
313      return (from i in listView.Items.Cast<ListViewItem>()
314              where i.Tag == dep
315              select i).Single();
316    }
317
318    private DeploymentService.PluginDescription MakePluginDescription(IPluginDescription plugin) {
319      var dependencies = from dep in plugin.Dependencies
320                         select MakePluginDescription(dep);
321      return new DeploymentService.PluginDescription(plugin.Name, plugin.Version, dependencies, plugin.ContactName, plugin.ContactEmail, plugin.LicenseText);
322    }
323    #endregion
324  }
325}
Note: See TracBrowser for help on using the repository browser.