#region License Information /* HeuristicLab * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using HeuristicLab.PluginInfrastructure.Manager; namespace HeuristicLab.PluginInfrastructure.Advanced { internal partial class InstallationManagerForm : Form { private class UpdateOrInstallPluginsBackgroundWorkerArgument { public IEnumerable PluginsToUpdate { get; set; } public IEnumerable PluginsToInstall { get; set; } } private class RemovePluginsBackgroundWorkerArgument { public IEnumerable PluginsToRemove { get; set; } } private class RefreshBackgroundWorkerResult { public IEnumerable RemotePlugins { get; set; } public IEnumerable RemoteProducts { get; set; } } private InstallationManager installationManager; private BackgroundWorker refreshServerPluginsBackgroundWorker; private BackgroundWorker updateOrInstallPluginsBackgroundWorker; private BackgroundWorker removePluginsBackgroundWorker; private BackgroundWorker refreshLocalPluginsBackgroundWorker; private BackgroundWorker updateAllPluginsBackgroundWorker; private PluginManager pluginManager; private string pluginDir; public InstallationManagerForm(PluginManager pluginManager) { InitializeComponent(); this.pluginManager = pluginManager; pluginManager.PluginLoaded += pluginManager_PluginLoaded; pluginManager.PluginUnloaded += pluginManager_PluginUnloaded; pluginManager.Initializing += pluginManager_Initializing; pluginManager.Initialized += pluginManager_Initialized; pluginDir = Application.StartupPath; #region initialize background workers refreshServerPluginsBackgroundWorker = new BackgroundWorker(); refreshServerPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshServerPluginsBackgroundWorker_DoWork); refreshServerPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshServerPluginsBackgroundWorker_RunWorkerCompleted); updateOrInstallPluginsBackgroundWorker = new BackgroundWorker(); updateOrInstallPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(updateOrInstallPluginsBackgroundWorker_DoWork); updateOrInstallPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted); removePluginsBackgroundWorker = new BackgroundWorker(); removePluginsBackgroundWorker.DoWork += new DoWorkEventHandler(removePluginsBackgroundWorker_DoWork); removePluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(removePluginsBackgroundWorker_RunWorkerCompleted); refreshLocalPluginsBackgroundWorker = new BackgroundWorker(); refreshLocalPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshLocalPluginsBackgroundWorker_DoWork); refreshLocalPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshLocalPluginsBackgroundWorker_RunWorkerCompleted); updateAllPluginsBackgroundWorker = new BackgroundWorker(); updateAllPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(updateAllPluginsBackgroundWorker_DoWork); updateAllPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updateAllPluginsBackgroundWorker_RunWorkerCompleted); #endregion installationManager = new InstallationManager(pluginDir); installationManager.PluginInstalled += new EventHandler(installationManager_PluginInstalled); installationManager.PluginRemoved += new EventHandler(installationManager_PluginRemoved); installationManager.PluginUpdated += new EventHandler(installationManager_PluginUpdated); installationManager.PreInstallPlugin += new EventHandler(installationManager_PreInstallPlugin); installationManager.PreRemovePlugin += new EventHandler(installationManager_PreRemovePlugin); installationManager.PreUpdatePlugin += new EventHandler(installationManager_PreUpdatePlugin); // show or hide controls for uploading plugins based on setting if (!HeuristicLab.PluginInfrastructure.Properties.Settings.Default.ShowPluginUploadControls) { tabControl.Controls.Remove(uploadPluginsTabPage); tabControl.Controls.Remove(manageProductsTabPage); } UpdateLocalPluginList(pluginManager.Plugins); UpdateControlsConnected(); } #region event handlers for update all plugins backgroundworker void updateAllPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show("There was an error while connecting to the server." + Environment.NewLine + "Please check your connection settings and user credentials."); UpdateControlsDisconnected(); } else { RefreshLocalPluginListAsync(); UpdateControlsConnected(); } } void updateAllPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { IEnumerable installedPlugins = (IEnumerable)e.Argument; var remotePlugins = installationManager.GetRemotePluginList(); // if there is a local plugin with same name and same major and minor version then it's an update var pluginsToUpdate = from remotePlugin in remotePlugins let matchingLocalPlugins = from installedPlugin in installedPlugins where installedPlugin.Name == remotePlugin.Name where installedPlugin.Version.Major == remotePlugin.Version.Major where installedPlugin.Version.Minor == remotePlugin.Version.Minor where installedPlugin.Version.Build <= remotePlugin.Version.Build || installedPlugin.Version.Revision < remotePlugin.Version.Revision select installedPlugin where matchingLocalPlugins.Count() > 0 select remotePlugin; installationManager.Update(pluginsToUpdate); } #endregion #region event handlers for refresh local plugin list backgroundworker void refreshLocalPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (!e.Cancelled && e.Error == null) { UpdateLocalPluginList((IEnumerable)e.Result); UpdateControlsConnected(); } } void refreshLocalPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { pluginManager.DiscoverAndCheckPlugins(); e.Result = new List(pluginManager.Plugins); } #endregion #region event handlers for plugin removal background worker void removePluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show("There was problem while deleting files." + Environment.NewLine + e.Error.Message); UpdateControlsDisconnected(); } else { RefreshLocalPluginListAsync(); UpdateControlsConnected(); } } void removePluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { IEnumerable pluginsToRemove = (IEnumerable)e.Argument; installationManager.Remove(pluginsToRemove); } #endregion #region event handlers for plugin update background worker void updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show("There was an error while connecting to the server." + Environment.NewLine + "Please check your connection settings and user credentials."); UpdateControlsDisconnected(); } else { RefreshLocalPluginListAsync(); RefreshRemotePluginListAsync(); UpdateControlsConnected(); } } void updateOrInstallPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { UpdateOrInstallPluginsBackgroundWorkerArgument info = (UpdateOrInstallPluginsBackgroundWorkerArgument)e.Argument; installationManager.Install(info.PluginsToInstall); installationManager.Update(info.PluginsToUpdate); } #endregion #region event handlers for refresh server plugins background worker void refreshServerPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show("There was an error while connecting to the server." + Environment.NewLine + "Please check your connection settings and user credentials."); UpdateControlsDisconnected(); } else { RefreshBackgroundWorkerResult refreshResult = (RefreshBackgroundWorkerResult)e.Result; UpdateRemotePluginList(refreshResult.RemoteProducts, refreshResult.RemotePlugins); UpdateControlsConnected(); } } void refreshServerPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { RefreshBackgroundWorkerResult result = new RefreshBackgroundWorkerResult(); result.RemotePlugins = installationManager.GetRemotePluginList(); result.RemoteProducts = installationManager.GetRemoteProductList(); e.Cancel = false; e.Result = result; } #endregion #region plugin manager event handlers void pluginManager_Initialized(object sender, PluginInfrastructureEventArgs e) { SetStatusStrip("Initialized PluginInfrastructure"); } void pluginManager_Initializing(object sender, PluginInfrastructureEventArgs e) { SetStatusStrip("Initializing PluginInfrastructure"); } void pluginManager_PluginUnloaded(object sender, PluginInfrastructureEventArgs e) { SetStatusStrip("Unloaded " + e.Entity); } void pluginManager_PluginLoaded(object sender, PluginInfrastructureEventArgs e) { SetStatusStrip("Loaded " + e.Entity); } #endregion #region installation manager event handlers void installationManager_PreUpdatePlugin(object sender, PluginInfrastructureCancelEventArgs e) { if (e.Plugins.Count() > 0) { e.Cancel = ConfirmUpdateAction(e.Plugins) == false; } } void installationManager_PreRemovePlugin(object sender, PluginInfrastructureCancelEventArgs e) { if (e.Plugins.Count() > 0) { e.Cancel = ConfirmRemoveAction(e.Plugins) == false; } } void installationManager_PreInstallPlugin(object sender, PluginInfrastructureCancelEventArgs e) { if (e.Plugins.Count() > 0) if (ConfirmInstallAction(e.Plugins) == true) { SetStatusStrip("Installing " + e.Plugins.Aggregate("", (a, b) => a.ToString() + "; " + b.ToString())); e.Cancel = false; } else { e.Cancel = true; SetStatusStrip("Install canceled"); } } void installationManager_PluginUpdated(object sender, PluginInfrastructureEventArgs e) { SetStatusStrip("Updated " + e.Entity); } void installationManager_PluginRemoved(object sender, PluginInfrastructureEventArgs e) { SetStatusStrip("Removed " + e.Entity); } void installationManager_PluginInstalled(object sender, PluginInfrastructureEventArgs e) { SetStatusStrip("Installed " + e.Entity); } #endregion #region button events private void refreshRemoteButton_Click(object sender, EventArgs e) { Cursor = Cursors.AppStarting; RefreshRemotePluginListAsync(); toolStripProgressBar.Visible = true; DisableControls(); } private void updateOrInstallButton_Click(object sender, EventArgs e) { Cursor = Cursors.AppStarting; toolStripProgressBar.Visible = true; DisableControls(); var updateOrInstallInfo = new UpdateOrInstallPluginsBackgroundWorkerArgument(); // if there is a local plugin with same name and same major and minor version then it's an update var pluginsToUpdate = from remotePlugin in remotePluginInstaller.CheckedPlugins let matchingLocalPlugins = from localPlugin in localPluginManagerView.Plugins where localPlugin.Name == remotePlugin.Name where localPlugin.Version.Major == remotePlugin.Version.Major where localPlugin.Version.Minor == remotePlugin.Version.Minor select localPlugin where matchingLocalPlugins.Count() > 0 select remotePlugin; // otherwise install a new plugin var pluginsToInstall = remotePluginInstaller.CheckedPlugins.Except(pluginsToUpdate); updateOrInstallInfo.PluginsToInstall = pluginsToInstall; updateOrInstallInfo.PluginsToUpdate = pluginsToUpdate; updateOrInstallPluginsBackgroundWorker.RunWorkerAsync(updateOrInstallInfo); } private void removeLocalButton_Click(object sender, EventArgs e) { Cursor = Cursors.AppStarting; toolStripProgressBar.Visible = true; DisableControls(); removePluginsBackgroundWorker.RunWorkerAsync(localPluginManagerView.CheckedPlugins); } private void updateAllButton_Click(object sender, EventArgs e) { Cursor = Cursors.AppStarting; toolStripProgressBar.Visible = true; updateButton.Enabled = false; var installedPlugins = pluginManager.Plugins.OfType(); updateAllPluginsBackgroundWorker.RunWorkerAsync(installedPlugins); } private void connectionSettingsToolStripMenuItem_Click(object sender, EventArgs e) { new ConnectionSetupView().ShowDialog(); } private void tabControl_Selected(object sender, TabControlEventArgs e) { viewToolStripMenuItem.Enabled = e.TabPage == availablePluginsTabPage; } private void simpleToolStripMenuItem_Click(object sender, EventArgs e) { remotePluginInstaller.ShowAllPlugins = false; advancedToolStripMenuItem.Checked = false; } private void advancedToolStripMenuItem_Click(object sender, EventArgs e) { remotePluginInstaller.ShowAllPlugins = true; simpleToolStripMenuItem.Checked = false; } #endregion #region confirmation dialogs private bool ConfirmRemoveAction(IEnumerable plugins) { StringBuilder strBuilder = new StringBuilder(); foreach (var plugin in plugins) { foreach (var file in plugin.Files) { strBuilder.AppendLine(Path.GetFileName(file.Name)); } } return (new ConfirmationDialog("Confirm Delete", "Do you want to delete following files?", strBuilder.ToString())).ShowDialog() == DialogResult.OK; } private bool ConfirmUpdateAction(IEnumerable plugins) { StringBuilder strBuilder = new StringBuilder(); foreach (var plugin in plugins) { strBuilder.AppendLine(plugin.ToString()); } return (new ConfirmationDialog("Confirm Update", "Do you want to update following plugins?", strBuilder.ToString())).ShowDialog() == DialogResult.OK; } private bool ConfirmInstallAction(IEnumerable plugins) { foreach (var plugin in plugins) { if (!string.IsNullOrEmpty(plugin.LicenseText)) { var licenseConfirmationBox = new LicenseConfirmationBox(plugin); if (licenseConfirmationBox.ShowDialog() != DialogResult.OK) return false; } } return true; } #endregion #region helper methods private void SetStatusStrip(string msg) { if (InvokeRequired) Invoke((Action)SetStatusStrip, msg); else { toolStripStatusLabel.Text = msg; logTextBox.Text += DateTime.Now + ": " + msg + Environment.NewLine; } } private void UpdateLocalPluginList(IEnumerable plugins) { localPluginManagerView.Plugins = plugins; } private void UpdateRemotePluginList( IEnumerable remoteProducts, IEnumerable remotePlugins) { var mostRecentRemotePlugins = from remote in remotePlugins where !remotePlugins.Any(x => x.Name == remote.Name && x.Version > remote.Version) // same name and higher version select remote; var newPlugins = from remote in mostRecentRemotePlugins let matchingLocal = (from local in localPluginManagerView.Plugins where local.Name == remote.Name where local.Version < remote.Version select local).FirstOrDefault() where matchingLocal != null select remote; remotePluginInstaller.NewPlugins = newPlugins; remotePluginInstaller.Products = remoteProducts; remotePluginInstaller.AllPlugins = remotePlugins; } private void RefreshRemotePluginListAsync() { Cursor = Cursors.AppStarting; toolStripProgressBar.Visible = true; refreshButton.Enabled = false; refreshServerPluginsBackgroundWorker.RunWorkerAsync(); } private void RefreshLocalPluginListAsync() { Cursor = Cursors.AppStarting; toolStripProgressBar.Visible = true; DisableControls(); refreshLocalPluginsBackgroundWorker.RunWorkerAsync(); } private void UpdateControlsDisconnected() { //localPluginsListView.Enabled = false; //ClearPluginsList(remotePluginsListView); refreshButton.Enabled = true; toolStripProgressBar.Visible = false; Cursor = Cursors.Default; } private void UpdateControlsConnected() { refreshButton.Enabled = true; updateButton.Enabled = true; toolStripProgressBar.Visible = false; Cursor = Cursors.Default; } private void DisableControls() { refreshButton.Enabled = false; Cursor = Cursors.Default; } #endregion private void localPluginManager_ItemChecked(object sender, ItemCheckedEventArgs e) { removeButton.Enabled = localPluginManagerView.CheckedPlugins.Count() > 0; } private void remotePluginInstaller_ItemChecked(object sender, ItemCheckedEventArgs e) { installButton.Enabled = remotePluginInstaller.CheckedPlugins.Count() > 0; } protected override void OnClosing(CancelEventArgs e) { installationManager.PluginInstalled -= new EventHandler(installationManager_PluginInstalled); installationManager.PluginRemoved -= new EventHandler(installationManager_PluginRemoved); installationManager.PluginUpdated -= new EventHandler(installationManager_PluginUpdated); installationManager.PreInstallPlugin -= new EventHandler(installationManager_PreInstallPlugin); installationManager.PreRemovePlugin -= new EventHandler(installationManager_PreRemovePlugin); installationManager.PreUpdatePlugin -= new EventHandler(installationManager_PreUpdatePlugin); base.OnClosing(e); } } }