1
#region License Information
3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 * This file is part of HeuristicLab.
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.
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.
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/>.
23 using System
.Collections
.Generic
;
24 using System
.ComponentModel
;
27 using System
.IO
.Compression
;
29 using System
.ServiceModel
;
30 using System
.Windows
.Forms
;
31 using HeuristicLab
.PluginInfrastructure
.Manager
;
33 namespace HeuristicLab
.PluginInfrastructure
.Advanced
{
34 internal partial class UploadPluginsView
: InstallationManagerControl
{
35 private const string UploadMessage
= "Uploading plugins...";
36 private const string RefreshMessage
= "Downloading plugin information from deployment service...";
38 private Dictionary
<IPluginDescription
, IPluginDescription
> localAndServerPlugins
;
39 private BackgroundWorker pluginUploadWorker
;
40 private BackgroundWorker refreshPluginsWorker
;
42 private PluginManager pluginManager
;
43 public PluginManager PluginManager
{
44 get { return pluginManager; }
45 set { pluginManager = value; }
48 public UploadPluginsView() {
49 InitializeComponent();
50 pluginImageList
.Images
.Add(HeuristicLab
.PluginInfrastructure
.Resources
.Plugin
);
51 localAndServerPlugins
= new Dictionary
<IPluginDescription
, IPluginDescription
>();
53 #region initialize backgroundworkers
54 pluginUploadWorker
= new BackgroundWorker();
55 pluginUploadWorker
.DoWork
+= new DoWorkEventHandler(pluginUploadWorker_DoWork
);
56 pluginUploadWorker
.RunWorkerCompleted
+= new RunWorkerCompletedEventHandler(pluginUploadWorker_RunWorkerCompleted
);
58 refreshPluginsWorker
= new BackgroundWorker();
59 refreshPluginsWorker
.DoWork
+= new DoWorkEventHandler(refreshPluginsWorker_DoWork
);
60 refreshPluginsWorker
.RunWorkerCompleted
+= new RunWorkerCompletedEventHandler(refreshPluginsWorker_RunWorkerCompleted
);
64 #region refresh plugins from server backgroundworker
65 void refreshPluginsWorker_RunWorkerCompleted(object sender
, RunWorkerCompletedEventArgs e
) {
66 if (e
.Error
!= null) {
67 StatusView
.ShowError("Connection Error",
68 "There was an error while connecting to the server." + Environment
.NewLine
+
69 "Please check your connection settings and user credentials.");
71 UpdatePluginListView((IEnumerable
<IPluginDescription
>)e
.Result
);
73 StatusView
.HideProgressIndicator();
74 StatusView
.RemoveMessage(RefreshMessage
);
75 StatusView
.UnlockUI();
78 void refreshPluginsWorker_DoWork(object sender
, DoWorkEventArgs e
) {
79 // refresh available plugins
80 var client
= DeploymentService
.UpdateServiceClientFactory
.CreateClient();
82 e
.Result
= client
.GetPlugins();
85 catch (TimeoutException
) {
89 catch (FaultException
) {
93 catch (CommunicationException
) {
100 #region upload plugins to server backgroundworker
101 void pluginUploadWorker_RunWorkerCompleted(object sender
, RunWorkerCompletedEventArgs e
) {
102 if (e
.Error
!= null) {
103 StatusView
.ShowError("Connection Error",
104 "There was an error while connecting to the server." + Environment
.NewLine
+
105 "Please check your connection settings and user credentials.");
107 UpdatePluginListView((IEnumerable
<IPluginDescription
>)e
.Result
);
109 StatusView
.RemoveMessage(UploadMessage
);
110 StatusView
.HideProgressIndicator();
111 StatusView
.UnlockUI();
114 void pluginUploadWorker_DoWork(object sender
, DoWorkEventArgs e
) {
116 var selectedPlugins
= (IEnumerable
<IPluginDescription
>)e
.Argument
;
117 DeploymentService
.AdminServiceClient adminClient
= DeploymentService
.AdminServiceClientFactory
.CreateClient();
118 Dictionary
<IPluginDescription
, DeploymentService
.PluginDescription
> cachedPluginDescriptions
=
119 new Dictionary
<IPluginDescription
, DeploymentService
.PluginDescription
>();
121 foreach (var plugin
in IteratePlugins(selectedPlugins
)) {
122 adminClient
.DeployPlugin(MakePluginDescription(plugin
, cachedPluginDescriptions
), CreateZipPackage(plugin
));
126 catch (TimeoutException
) {
130 catch (FaultException
) {
134 catch (CommunicationException
) {
138 // refresh available plugins
139 var client
= DeploymentService
.UpdateServiceClientFactory
.CreateClient();
141 e
.Result
= client
.GetPlugins();
144 catch (TimeoutException
) {
148 catch (FaultException
) {
152 catch (CommunicationException
) {
160 #region button events
161 private void uploadButton_Click(object sender
, EventArgs e
) {
162 var selectedPlugins
= from item
in listView
.Items
.Cast
<ListViewItem
>()
164 where item
.Tag
is IPluginDescription
165 select item
.Tag
as IPluginDescription
;
166 if (selectedPlugins
.Count() > 0) {
168 StatusView
.ShowProgressIndicator();
169 StatusView
.ShowMessage(UploadMessage
);
170 pluginUploadWorker
.RunWorkerAsync(selectedPlugins
.ToList());
174 private void refreshButton_Click(object sender
, EventArgs e
) {
176 StatusView
.ShowProgressIndicator();
177 StatusView
.ShowMessage(RefreshMessage
);
178 refreshPluginsWorker
.RunWorkerAsync();
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 Util
.GetAllDependencies(plugin
)) {
195 if (!modifiedPlugins
.Contains(dep
))
196 modifiedPlugins
.Add(dep
);
199 listView
.CheckItems(modifiedPlugins
.Select(x
=> FindItemForPlugin(x
)));
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 Util
.GetAllDependents(plugin
, localAndServerPlugins
.Keys
)) {
207 if (!modifiedPlugins
.Contains(dep
))
208 modifiedPlugins
.Add(dep
);
211 listView
.UncheckItems(modifiedPlugins
.Select(x
=> FindItemForPlugin(x
)));
213 uploadButton
.Enabled
= (from i
in listView
.Items
.OfType
<ListViewItem
>()
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);
226 foreach (var plugin
in remotePlugins
) {
227 var matchingLocalPlugin
= (from localPlugin
in localAndServerPlugins
.Keys
228 where localPlugin
.Name
== plugin
.Name
229 where localPlugin
.Version
== plugin
.Version
230 select localPlugin
).SingleOrDefault();
231 if (matchingLocalPlugin
!= null) {
232 localAndServerPlugins
[matchingLocalPlugin
] = plugin
;
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
);
242 Util
.ResizeColumns(listView
.Columns
.OfType
<ColumnHeader
>());
243 ignoreItemCheckedEvents
= false;
246 private IEnumerable
<IPluginDescription
> IteratePlugins(IEnumerable
<IPluginDescription
> plugins
) {
247 HashSet
<IPluginDescription
> yieldedItems
= new HashSet
<IPluginDescription
>();
248 foreach (var plugin
in plugins
) {
249 foreach (var dependency
in IteratePlugins(plugin
.Dependencies
)) {
250 if (!yieldedItems
.Contains(dependency
)) {
251 yieldedItems
.Add(dependency
);
252 yield return dependency
;
255 if (!yieldedItems
.Contains(plugin
)) {
256 yieldedItems
.Add(plugin
);
262 private static byte[] CreateZipPackage(IPluginDescription plugin
) {
263 using (MemoryStream stream
= new MemoryStream()) {
264 ZipArchive zipFile
= new ZipArchive(stream
, ZipArchiveMode
.Create
);
265 foreach (var file
in plugin
.Files
) {
266 zipFile
.CreateEntry(file
.Name
);
268 stream
.Seek(0, SeekOrigin
.Begin
);
269 return stream
.GetBuffer();
273 private ListViewItem
MakeListViewItem(IPluginDescription plugin
) {
275 if (localAndServerPlugins
[plugin
] != null) {
276 item
= new ListViewItem(new string[] { plugin
.Name
, plugin
.Version
.ToString(),
277 localAndServerPlugins
[plugin
].Version
.ToString(), localAndServerPlugins
[plugin
].Description
});
278 if (plugin
.Version
<= localAndServerPlugins
[plugin
].Version
)
279 item
.ForeColor
= Color
.Gray
;
281 item
= new ListViewItem(new string[] { plugin
.Name
, plugin
.Version
.ToString(),
282 string.Empty
, plugin
.Description
});
286 item
.Checked
= false;
290 private ListViewItem
FindItemForPlugin(IPluginDescription dep
) {
291 return (from i
in listView
.Items
.Cast
<ListViewItem
>()
296 private DeploymentService
.PluginDescription
MakePluginDescription(IPluginDescription plugin
, Dictionary
<IPluginDescription
, DeploymentService
.PluginDescription
> cachedPluginDescriptions
) {
297 if (!cachedPluginDescriptions
.ContainsKey(plugin
)) {
298 var dependencies
= (from dep
in plugin
.Dependencies
299 select MakePluginDescription(dep
, cachedPluginDescriptions
))
301 cachedPluginDescriptions
.Add(plugin
,
302 new DeploymentService
.PluginDescription(plugin
.Name
, plugin
.Version
, dependencies
, plugin
.ContactName
, plugin
.ContactEmail
, plugin
.LicenseText
));
304 return cachedPluginDescriptions
[plugin
];