Free cookie consent management tool by TermsFeed Policy Generator

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

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

Incorporated review comments by swagner into plugin infrastructure. #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;
33
34namespace HeuristicLab.PluginInfrastructure.Advanced {
35  internal partial class PluginEditor : InstallationManagerControl {
36    private Dictionary<IPluginDescription, DeploymentService.PluginDescription> localAndServerPlugins;
37    private BackgroundWorker pluginUploadWorker;
38    private BackgroundWorker updateServerPluginsWorker;
39
40    public PluginEditor() {
41      InitializeComponent();
42      // Caption = "Upload Plugins";
43
44      localAndServerPlugins = new Dictionary<IPluginDescription, DeploymentService.PluginDescription>();
45
46      #region initialize backgroundworkers
47      pluginUploadWorker = new BackgroundWorker();
48      pluginUploadWorker.DoWork += new DoWorkEventHandler(pluginUploadWorker_DoWork);
49      pluginUploadWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(pluginUploadWorker_RunWorkerCompleted);
50
51      updateServerPluginsWorker = new BackgroundWorker();
52      updateServerPluginsWorker.DoWork += new DoWorkEventHandler(updateServerPluginsWorker_DoWork);
53      updateServerPluginsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updateServerPluginsWorker_RunWorkerCompleted);
54      #endregion
55    }
56
57    #region refresh plugins from server backgroundworker
58    void updateServerPluginsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
59      if (!e.Cancelled && e.Result != null) {
60        // refresh local plugins
61        localAndServerPlugins.Clear();
62        foreach (var plugin in ApplicationManager.Manager.Plugins) {
63          localAndServerPlugins.Add(plugin, null);
64        }
65        // refresh server plugins (find matching local plugins)
66        var plugins = (DeploymentService.PluginDescription[])e.Result;
67        foreach (var plugin in plugins) {
68          var matchingLocalPlugin = (from localPlugin in localAndServerPlugins.Keys
69                                     where localPlugin.Name == plugin.Name
70                                     where localPlugin.Version == localPlugin.Version
71                                     select localPlugin).SingleOrDefault();
72          if (matchingLocalPlugin != null) {
73            localAndServerPlugins[matchingLocalPlugin] = plugin;
74          }
75        }
76        // refresh the list view with plugins
77        listView.Items.Clear();
78        listView.CheckBoxes = false;
79        //suppressCheckedEvents = true;
80        foreach (var pair in localAndServerPlugins) {
81          var item = MakeListViewItem(pair.Key);
82          listView.Items.Add(item);
83        }
84        foreach (ColumnHeader column in listView.Columns)
85          column.Width = -1;
86        //listView.suppressCheckedEvents = false;
87        listView.CheckBoxes = true;
88        UpdateControlsConnectedState();
89      } else {
90        UpdateControlsDisconnectedState();
91      }
92      // make sure cursor is set correctly
93      Cursor = Cursors.Default;
94    }
95
96    void updateServerPluginsWorker_DoWork(object sender, DoWorkEventArgs e) {
97      try {
98        var client = DeploymentService.UpdateClientFactory.CreateClient();
99        e.Result = client.GetPlugins();
100        e.Cancel = false;
101      }
102      catch (EndpointNotFoundException) {
103        e.Result = null;
104        e.Cancel = true;
105      }
106      catch (FaultException) {
107        e.Result = null;
108        e.Cancel = true;
109      }
110    }
111    #endregion
112
113    #region upload plugins to server backgroundworker
114    void pluginUploadWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
115      Cursor = Cursors.Default;
116      if (e.Cancelled) {
117        UpdateControlsDisconnectedState();
118      } else {
119        UpdateControlsConnectedState();
120        // start another async call to refresh plugin information from server
121        RefreshPluginsAsync();
122      }
123    }
124
125    void pluginUploadWorker_DoWork(object sender, DoWorkEventArgs e) {
126      try {
127        var selectedPlugins = (IEnumerable<IPluginDescription>)e.Argument;
128        DeploymentService.AdminClient adminClient = DeploymentService.AdminClientFactory.CreateClient();
129
130        foreach (var plugin in IteratePlugins(selectedPlugins)) {
131          SetMainFormStatusBar("Uploading", plugin);
132          adminClient.DeployPlugin(MakePluginDescription(plugin), CreateZipPackage(plugin));
133        }
134        e.Cancel = false;
135      }
136      catch (EndpointNotFoundException) {
137        e.Cancel = true;
138      }
139      catch (FaultException) {
140        e.Cancel = true;
141      }
142    }
143
144    #endregion
145
146
147    #region button events
148    private void uploadButton_Click(object sender, EventArgs e) {
149      var selectedPlugins = from item in listView.Items.Cast<ListViewItem>()
150                            where item.Checked
151                            where item.Tag is IPluginDescription
152                            select item.Tag as IPluginDescription;
153      if (selectedPlugins.Count() > 0) {
154        Cursor = Cursors.AppStarting;
155        DisableControl();
156        pluginUploadWorker.RunWorkerAsync(selectedPlugins.ToList());
157      }
158    }
159
160    private void refreshButton_Click(object sender, EventArgs e) {
161      DisableControl();
162      RefreshPluginsAsync();
163    }
164
165    #endregion
166
167    #region item list events
168    private void listView_ItemActivate(object sender, EventArgs e) {
169      foreach (var item in listView.SelectedItems) {
170        var plugin = (IPluginDescription)((ListViewItem)item).Tag;
171        var compView = new PluginComparisonView(plugin, localAndServerPlugins[plugin]);
172        compView.Show();
173      }
174    }
175
176    private void listView_ItemChecked(object sender, ItemCheckedEventArgs e) {
177      List<IPluginDescription> modifiedPlugins = new List<IPluginDescription>();
178      if (e.Item.Checked) {
179        foreach (ListViewItem item in listView.SelectedItems) {
180          var plugin = (IPluginDescription)item.Tag;
181          // also check all dependencies
182          if (!modifiedPlugins.Contains(plugin))
183            modifiedPlugins.Add(plugin);
184          foreach (var dep in GetAllDependencies(plugin)) {
185            if (!modifiedPlugins.Contains(dep))
186              modifiedPlugins.Add(dep);
187          }
188        }
189        listView.CheckItems(modifiedPlugins.Select(x => FindItemForPlugin(x)));
190      } else {
191        foreach (ListViewItem item in listView.SelectedItems) {
192          var plugin = (IPluginDescription)item.Tag;
193          // also uncheck all dependent plugins
194          if (!modifiedPlugins.Contains(plugin))
195            modifiedPlugins.Add(plugin);
196          foreach (var dep in GetAllDependents(plugin)) {
197            if (!modifiedPlugins.Contains(dep))
198              modifiedPlugins.Add(dep);
199          }
200        }
201        listView.UncheckItems(modifiedPlugins.Select(x => FindItemForPlugin(x)));
202      }
203      uploadButton.Enabled = (from i in listView.Items.OfType<ListViewItem>()
204                              where i.Checked
205                              select i).Any();
206    }
207    #endregion
208
209    #region helper methods
210    private IEnumerable<IPluginDescription> GetAllDependents(IPluginDescription plugin) {
211      return from p in localAndServerPlugins.Keys
212             let matchingEntries = from dep in GetAllDependencies(p)
213                                   where dep.Name == plugin.Name
214                                   where dep.Version == plugin.Version
215                                   select dep
216             where matchingEntries.Any()
217             select p;
218    }
219
220    private IEnumerable<IPluginDescription> GetAllDependencies(IPluginDescription plugin) {
221      foreach (var dep in plugin.Dependencies) {
222        foreach (var recDep in GetAllDependencies(dep)) {
223          yield return recDep;
224        }
225        yield return dep;
226      }
227    }
228
229    private IEnumerable<IPluginDescription> IteratePlugins(IEnumerable<IPluginDescription> plugins) {
230      HashSet<IPluginDescription> yieldedItems = new HashSet<IPluginDescription>();
231      foreach (var plugin in plugins) {
232        foreach (var dependency in IteratePlugins(plugin.Dependencies)) {
233          if (!yieldedItems.Contains(dependency)) {
234            yieldedItems.Add(dependency);
235            yield return dependency;
236          }
237        }
238        if (!yieldedItems.Contains(plugin)) {
239          yieldedItems.Add(plugin);
240          yield return plugin;
241        }
242      }
243    }
244
245    private byte[] CreateZipPackage(IPluginDescription plugin) {
246      using (MemoryStream stream = new MemoryStream()) {
247        ZipFile zipFile = new ZipFile(stream);
248        zipFile.BeginUpdate();
249        foreach (var file in plugin.Files) {
250          zipFile.Add(file.Name);
251        }
252        zipFile.CommitUpdate();
253        stream.Seek(0, SeekOrigin.Begin);
254        return stream.GetBuffer();
255      }
256    }
257
258    private ListViewItem MakeListViewItem(IPluginDescription plugin) {
259      ListViewItem item;
260      if (localAndServerPlugins[plugin] != null) {
261        item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(),
262          localAndServerPlugins[plugin].Version.ToString(), localAndServerPlugins[plugin].Description });
263      } else {
264        item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(),
265          string.Empty, plugin.Description });
266      }
267      item.Tag = plugin;
268      item.Checked = false;
269      return item;
270    }
271
272    private ListViewItem FindItemForPlugin(IPluginDescription dep) {
273      return (from i in listView.Items.Cast<ListViewItem>()
274              where i.Tag == dep
275              select i).Single();
276    }
277
278    private DeploymentService.PluginDescription MakePluginDescription(IPluginDescription plugin) {
279      var dependencies = from dep in plugin.Dependencies
280                         select MakePluginDescription(dep);
281      return new DeploymentService.PluginDescription(plugin.Name, plugin.Version, dependencies, plugin.ContactName, plugin.ContactEmail, plugin.LicenseText);
282    }
283
284    // start background process to refresh the plugin list (local and server)
285    private void RefreshPluginsAsync() {
286      Cursor = Cursors.AppStarting;
287      DisableControl();
288      updateServerPluginsWorker.RunWorkerAsync();
289    }
290
291    // is called by all methods that start a background process
292    // controls must be enabled manuall again when the backgroundworker finishes
293    private void DisableControl() {
294      //MainFormManager.GetMainForm<MainForm>().ShowProgressBar();
295      foreach (Control ctrl in Controls)
296        ctrl.Enabled = false;
297    }
298
299    private void UpdateControlsDisconnectedState() {
300      refreshButton.Enabled = false;
301
302      localAndServerPlugins.Clear();
303      listView.Items.Clear();
304      listView.Enabled = false;
305      uploadButton.Enabled = false;
306      //MainFormManager.GetMainForm<MainForm>().HideProgressBar();
307    }
308
309    private void UpdateControlsConnectedState() {
310      refreshButton.Enabled = true;
311      listView.Enabled = true;
312      uploadButton.Enabled = false;
313      //MainFormManager.GetMainForm<MainForm>().HideProgressBar();
314    }
315    private void SetMainFormStatusBar(string p, IPluginDescription plugin) {
316      if (InvokeRequired) Invoke((Action<string, IPluginDescription>)SetMainFormStatusBar, p, plugin);
317      else {
318        //MainFormManager.GetMainForm<MainForm>().SetStatusBarText(p + " " + plugin.ToString());
319      }
320    }
321
322    #endregion
323  }
324}
Note: See TracBrowser for help on using the repository browser.