/*
* RapidMiner
*
* Copyright (C) 2001-2014 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.rapid_i.deployment.update.client;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.rapid_i.deployment.update.client.listmodels.AbstractPackageListModel;
import com.rapidminer.deployment.client.wsimport.PackageDescriptor;
import com.rapidminer.deployment.client.wsimport.UpdateService;
import com.rapidminer.gui.RapidMinerGUI;
import com.rapidminer.gui.tools.ExtendedJScrollPane;
import com.rapidminer.gui.tools.ProgressThread;
import com.rapidminer.gui.tools.ResourceAction;
import com.rapidminer.gui.tools.SwingTools;
import com.rapidminer.gui.tools.dialogs.ButtonDialog;
import com.rapidminer.gui.tools.dialogs.ConfirmDialog;
import com.rapidminer.io.process.XMLTools;
import com.rapidminer.tools.FileSystemService;
import com.rapidminer.tools.I18N;
import com.rapidminer.tools.LogService;
import com.rapidminer.tools.ParameterService;
import com.rapidminer.tools.XMLException;
/**
* The Dialog is eventually shown at the start of RapidMiner, if the user purchased extensions online but haven't installed them yet.
*
* @author Dominik Halfkann
*/
public class PendingPurchasesInstallationDialog extends ButtonDialog {
private static final long serialVersionUID = 1L;
private final PackageDescriptorCache packageDescriptorCache = new PackageDescriptorCache();
private AbstractPackageListModel purchasedModel = new PurchasedNotInstalledModel(packageDescriptorCache);
JCheckBox neverAskAgain = new JCheckBox(I18N.getMessage(I18N.getGUIBundle(), "gui.dialog.purchased_not_installed.not_check_on_startup"));
private final List<String> packages;
private boolean isConfirmed;
private LinkedList<PackageDescriptor> installablePackageList;
private JButton remindNeverButton;
private JButton remindLaterButton;
private JButton okButton;
private class PurchasedNotInstalledModel extends AbstractPackageListModel {
private static final long serialVersionUID = 1L;
public PurchasedNotInstalledModel(PackageDescriptorCache cache) {
super(cache, "gui.dialog.update.tab.no_packages");
}
@Override
public List<String> handleFetchPackageNames() {
return packages;
}
}
public PendingPurchasesInstallationDialog(List<String> packages) {
super("purchased_not_installed");
this.packages = packages;
remindNeverButton = remindNeverButton();
remindLaterButton = remindLaterButton();
okButton = makeOkButton("install_purchased");
layoutDefault(makeContentPanel(), NORMAL, okButton, remindNeverButton, remindLaterButton);
this.setPreferredSize(new Dimension(404, 430));
this.setMaximumSize(new Dimension(404, 430));
this.setMinimumSize(new Dimension(404, 300));
this.setSize(new Dimension(404, 430));
}
private JPanel makeContentPanel() {
BorderLayout layout = new BorderLayout(12, 12);
JPanel panel = new JPanel(layout);
panel.setBorder(new EmptyBorder(0, 12, 8, 12));
panel.add(createExtensionListScrollPane(purchasedModel), BorderLayout.CENTER);
purchasedModel.update();
JPanel southPanel = new JPanel(new BorderLayout(0, 7));
JLabel question = new JLabel(I18N.getMessage(I18N.getGUIBundle(), "gui.dialog.purchased_not_installed.should_install"));
southPanel.add(question, BorderLayout.CENTER);
southPanel.add(neverAskAgain, BorderLayout.SOUTH);
panel.add(southPanel, BorderLayout.SOUTH);
return panel;
}
private JScrollPane createExtensionListScrollPane(AbstractPackageListModel model) {
final JList updateList = new JList(model);
updateList.setCellRenderer(new UpdateListCellRenderer(true));
JScrollPane extensionListScrollPane = new ExtendedJScrollPane(updateList);
extensionListScrollPane.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
return extensionListScrollPane;
}
private JButton remindLaterButton() {
Action Action = new ResourceAction("ask_later") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
wasConfirmed = false;
checkNeverAskAgain();
close();
}
};
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "CLOSE");
getRootPane().getActionMap().put("CLOSE", Action);
JButton button = new JButton(Action);
getRootPane().setDefaultButton(button);
return button;
}
private JButton remindNeverButton() {
Action Action = new ResourceAction("ask_never") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
wasConfirmed = false;
checkNeverAskAgain();
neverRemindAgain();
close();
}
};
JButton button = new JButton(Action);
getRootPane().setDefaultButton(button);
return button;
}
@Override
protected void ok() {
checkNeverAskAgain();
startUpdate(getPackageDescriptorList());
dispose();
}
public List<PackageDescriptor> getPackageDescriptorList() {
List<PackageDescriptor> packageList = new ArrayList<PackageDescriptor>();
for (int a = 0; a < purchasedModel.getSize(); a++) {
Object listItem = purchasedModel.getElementAt(a);
if (listItem instanceof PackageDescriptor) {
packageList.add((PackageDescriptor) listItem);
}
}
return packageList;
}
public void startUpdate(final List<PackageDescriptor> downloadList) {
final UpdateService service;
try {
service = UpdateManager.getService();
} catch (Exception e) {
SwingTools.showSimpleErrorMessage("failed_update_server", e, UpdateManager.getBaseUrl());
return;
}
new ProgressThread("resolving_dependencies", true) {
@Override
public void run() {
try {
getProgressListener().setTotal(100);
remindLaterButton.setEnabled(false);
remindNeverButton.setEnabled(false);
final HashMap<PackageDescriptor, HashSet<PackageDescriptor>> dependency = UpdateDialog.resolveDependency(downloadList, packageDescriptorCache);
getProgressListener().setCompleted(30);
installablePackageList = UpdateDialog.getPackagesforInstallation(dependency);
final HashMap<String, String> licenseNameToLicenseTextMap = UpdateDialog.collectLicenses(installablePackageList,getProgressListener(),100,30,100);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
isConfirmed = ConfirmLicensesDialog.confirm(dependency, licenseNameToLicenseTextMap);
new ProgressThread("installing_updates", true) {
@Override
public void run() {
try {
if (isConfirmed) {
getProgressListener().setTotal(100);
getProgressListener().setCompleted(20);
UpdateService service = UpdateManager.getService();
UpdateManager um = new UpdateManager(service);
List<PackageDescriptor> installedPackages = um.performUpdates(installablePackageList, getProgressListener());
getProgressListener().setCompleted(40);
if (installedPackages.size() > 0) {
int confirmation = SwingTools.showConfirmDialog((installedPackages.size() == 1 ? "update.complete_restart" : "update.complete_restart1"),
ConfirmDialog.YES_NO_OPTION, installedPackages.size());
if (confirmation == ConfirmDialog.YES_OPTION) {
RapidMinerGUI.getMainFrame().exit(true);
} else if (confirmation == ConfirmDialog.NO_OPTION) {
if (installedPackages.size() == installablePackageList.size()) {
dispose();
}
}
}
getProgressListener().complete();
}
} catch (Exception e) {
SwingTools.showSimpleErrorMessage("error_installing_update", e, e.getMessage());
} finally {
getProgressListener().complete();
}
}
}.start();
}
});
remindLaterButton.setEnabled(true);
remindNeverButton.setEnabled(true);
getProgressListener().complete();
} catch (Exception e) {
SwingTools.showSimpleErrorMessage("error_resolving_dependencies", e, e.getMessage());
}
}
}.start();
}
private void checkNeverAskAgain() {
if (neverAskAgain.isSelected()) {
ParameterService.setParameterValue(RapidMinerGUI.PROPERTY_RAPIDMINER_GUI_PURCHASED_NOT_INSTALLED_CHECK, "false");
ParameterService.saveParameters();
}
}
private void neverRemindAgain() {
LogService.getRoot().log(Level.CONFIG, "com.rapid_i.deployment.update.client.PurchasedNotInstalledDialog.saving_ignored_extensions_file");
Document doc;
try {
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
} catch (ParserConfigurationException e) {
LogService.getRoot().log(Level.WARNING,
I18N.getMessage(LogService.getRoot().getResourceBundle(),
"com.rapid_i.deployment.update.client.PurchasedNotInstalledDialog.creating_xml_document_error",
e),
e);
return;
}
Element root = doc.createElement(UpdateManager.NEVER_REMIND_INSTALL_EXTENSIONS_FILE_NAME);
doc.appendChild(root);
for (String i : purchasedModel.fetchPackageNames()) {
Element entryElem = doc.createElement("extension_name");
entryElem.setTextContent(i);
root.appendChild(entryElem);
}
File file = FileSystemService.getUserConfigFile(UpdateManager.NEVER_REMIND_INSTALL_EXTENSIONS_FILE_NAME);
try {
XMLTools.stream(doc, file, null);
} catch (XMLException e) {
LogService.getRoot().log(Level.WARNING,
I18N.getMessage(LogService.getRoot().getResourceBundle(),
"com.rapid_i.deployment.update.client.PurchasedNotInstalledDialog.saving_ignored_extensions_file_error",
e),
e);
}
}
}