Java tutorial
/** * Copyright (C) 2005 - 2013 Eric Van Dewoestine * * This program 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. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.eclim.installer.step; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.SystemUtils; import org.eclim.installer.step.command.Command; import org.eclim.installer.step.command.InstallCommand; import org.eclim.installer.step.command.ListCommand; import org.eclim.installer.step.command.OutputHandler; import org.eclim.installer.theme.DesertBlue; import org.formic.Installer; import org.formic.util.dialog.gui.GuiDialogs; import org.formic.wizard.step.gui.InstallStep; import com.jgoodies.looks.plastic.PlasticTheme; import foxtrot.Worker; /** * Step which installs necessary third party eclipse plugins. * * @author Eric Van Dewoestine */ public class EclipsePluginsStep extends InstallStep implements OutputHandler { private static final String BEGIN_TASK = "beginTask"; private static final String PREPARE_TASK = "prepare"; private static final String SUB_TASK = "subTask"; private static final String INTERNAL_WORKED = "worked"; private static final String SET_TASK_NAME = "setTaskName"; private static final Color ERROR_COLOR = new Color(255, 201, 201); private String taskName = ""; private JPanel stepPanel; private JPanel featuresPanel; private JLabel messageLabel; private ImageIcon errorIcon; private DefaultTableModel tableModel; private List<Dependency> dependencies; private Map<String, String> availableFeatures; private PlasticTheme theme; private int overallProgressStep; /** * Constructs this step. */ public EclipsePluginsStep(String name, Properties properties) { super(name, properties); } @Override public Component init() { theme = new DesertBlue(); stepPanel = (JPanel) super.init(); stepPanel.setBorder(null); JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); messageLabel = new JLabel(); messageLabel.setPreferredSize(new Dimension(25, 25)); panel.add(messageLabel); panel.add(stepPanel); panel.setBorder(BorderFactory.createEmptyBorder(25, 25, 10, 25)); return panel; } private void setMessage(String message) { if (errorIcon == null) { errorIcon = new ImageIcon(Installer.getImage("form.error.icon")); } if (message != null) { messageLabel.setIcon(errorIcon); messageLabel.setText(message); } else { messageLabel.setIcon(null); messageLabel.setText(null); } } @Override public void displayed() { setBusy(true); setPreviousEnabled(false); try { overallLabel.setText(""); overallProgress.setValue(0); taskLabel.setText(""); taskProgress.setValue(0); taskProgress.setIndeterminate(true); // handle step re-entry. if (featuresPanel != null) { stepPanel.remove(featuresPanel); } EclipseInfo info = (EclipseInfo) Installer.getContext().getValue("eclipse.info"); // find chosen features dependencies which need to be installed/upgraded. dependencies = unsatisfiedDependencies(info); if (dependencies.size() == 0) { overallProgress.setMaximum(1); overallProgress.setValue(1); overallLabel.setText("All third party plugins are up to date."); taskProgress.setMaximum(1); taskProgress.setValue(1); taskLabel.setText(""); } else { tableModel = new DefaultTableModel(); tableModel.addColumn("Feature"); tableModel.addColumn("Version"); tableModel.addColumn("Install / Upgrade"); JTable table = new JTable(tableModel); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.setDefaultRenderer(Object.class, new DependencyCellRenderer()); table.getSelectionModel().addListSelectionListener(new DependencySelectionListener()); featuresPanel = new JPanel(new BorderLayout()); featuresPanel.setAlignmentX(0.0f); JPanel container = new JPanel(new BorderLayout()); container.add(table, BorderLayout.CENTER); JScrollPane scrollPane = new JScrollPane(container); scrollPane.setAlignmentX(0.0f); availableFeatures = loadAvailableFeatures(); for (Dependency dependency : dependencies) { String version = availableFeatures.get(dependency.getId()); String manual = ""; if (version == null) { manual = " (Manual)"; version = dependency.getRequiredVersion(); } tableModel.addRow(new Object[] { dependency.getId(), version, (dependency.isUpgrade() ? "Upgrade" : "Install") + manual, }); } JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0)); buttons.setAlignmentX(0.0f); JButton skipButton = new JButton(new SkipPluginsAction()); JButton installButton = new JButton(new InstallPluginsAction(skipButton)); buttons.add(installButton); buttons.add(skipButton); featuresPanel.add(scrollPane, BorderLayout.CENTER); featuresPanel.add(buttons, BorderLayout.SOUTH); stepPanel.add(featuresPanel); overallProgress.setValue(0); overallLabel.setText(""); taskProgress.setValue(0); taskLabel.setText(""); } } catch (Exception e) { setError(e); } finally { setValid(dependencies != null && dependencies.size() == 0); setBusy(false); setPreviousEnabled(true); taskProgress.setIndeterminate(false); } } public void process(final String line) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (line.startsWith(BEGIN_TASK)) { String l = line.substring(BEGIN_TASK.length() + 2); double work = Double.parseDouble(l.substring(l.indexOf('=') + 1, l.indexOf(' '))); taskProgress.setIndeterminate(false); taskProgress.setMaximum((int) work); taskProgress.setValue(0); } else if (line.startsWith(PREPARE_TASK)) { taskLabel.setText(line.substring(PREPARE_TASK.length() + 1).trim()); } else if (line.startsWith(SUB_TASK)) { taskLabel.setText(taskName + line.substring(SUB_TASK.length() + 1).trim()); } else if (line.startsWith(INTERNAL_WORKED)) { double worked = Double.parseDouble(line.substring(INTERNAL_WORKED.length() + 2)); taskProgress.setValue((int) worked); overallProgress.setValue(overallProgressStep + (int) (taskProgress.getPercentComplete() * 100)); } else if (line.startsWith(SET_TASK_NAME)) { taskName = line.substring(SET_TASK_NAME.length() + 1).trim() + ' '; } } }); } private List<Dependency> unsatisfiedDependencies(EclipseInfo info) { List<Dependency> deps = new ArrayList<Dependency>(); String[] features = Installer.getContext().getKeysByPrefix("featureList"); Arrays.sort(features, new FeatureNameComparator()); for (int ii = 0; ii < features.length; ii++) { Boolean enabled = (Boolean) Installer.getContext().getValue(features[ii]); if (enabled.booleanValue()) { String name = features[ii].substring(features[ii].indexOf('.') + 1); deps.addAll(info.getUnsatisfiedDependencies(name)); } } return deps; } @SuppressWarnings("unchecked") private Map<String, String> loadAvailableFeatures() throws Exception { // load up available features from update sites. overallProgress.setMaximum(1); overallLabel.setText("Loading available features from update sites..."); return (Map<String, String>) Worker.post(new foxtrot.Task() { public Object run() throws Exception { final Map<String, String> availableFeatures = new HashMap<String, String>(); ArrayList<String> sites = new ArrayList<String>(); for (Dependency dependency : dependencies) { String site = dependency.getSite(); if (site == null) { availableFeatures.put(dependency.getId(), dependency.getRequiredVersion()); } else if (!sites.contains(site)) { sites.add(site); } } OutputHandler handler = new OutputHandler() { public void process(String line) { String[] parts = StringUtils.split(line, "="); if (parts.length == 2 && parts[0].endsWith(".feature.group")) { availableFeatures.put(parts[0].replace(".feature.group", ""), parts[1]); } } }; if (sites.size() > 0) { Command command = new ListCommand(handler, sites.toArray(new String[sites.size()])); try { command.start(); command.join(); if (command.getReturnCode() != 0) { throw new RuntimeException( "error: " + command.getErrorMessage() + " out: " + command.getResult()); } } finally { command.destroy(); } } return availableFeatures; } }); } private class InstallPluginsAction extends AbstractAction { private static final long serialVersionUID = 1L; private JButton skipButton; public InstallPluginsAction(JButton skipButton) { super("Install Features"); this.skipButton = skipButton; } public void actionPerformed(ActionEvent e) { ((JButton) e.getSource()).setEnabled(false); setPreviousEnabled(true); try { Boolean successful = (Boolean) Worker.post(new foxtrot.Task() { public Object run() throws Exception { // check if any of the features cannot be installed. for (Dependency dependency : dependencies) { Feature feature = dependency.getFeature(); if (feature != null) { if (feature.getSite() == null) { String installLog = FilenameUtils.concat(SystemUtils.JAVA_IO_TMPDIR, "install.log"); GuiDialogs.showWarning(Installer.getString( "eclipsePlugins.install.features.site.not.found", installLog)); return Boolean.FALSE; } else if (!feature.getSite().canWrite()) { GuiDialogs.showWarning(Installer .getString("eclipsePlugins.install.features.permission.denied")); return Boolean.FALSE; } } } int installCount = 0; for (Iterator<Dependency> ii = dependencies.iterator(); ii.hasNext();) { Dependency dependency = ii.next(); if (dependency.getSite() != null) { installCount++; } } overallProgress.setMaximum(installCount * 100); overallProgress.setValue(0); int removeIndex = 0; for (Iterator<Dependency> ii = dependencies.iterator(); ii.hasNext();) { Dependency dependency = ii.next(); String site = dependency.getSite(); String version = availableFeatures.get(dependency.getId()); if (site != null && version != null) { if (!dependency.isUpgrade()) { overallLabel .setText("Installing feature: " + dependency.getId() + '-' + version); } else { overallLabel.setText("Updating feature: " + dependency.getId() + '-' + version); } taskProgress.setValue(0); taskProgress.setIndeterminate(true); Command command = new InstallCommand(EclipsePluginsStep.this, dependency.getSite(), dependency.getId()); try { command.start(); command.join(); if (command.getReturnCode() != 0) { if (command.isShutdown()) { return Boolean.TRUE; } throw new RuntimeException("error: " + command.getErrorMessage() + " out: " + command.getResult()); } } finally { command.destroy(); } ii.remove(); tableModel.removeRow(removeIndex); } else { removeIndex++; } overallProgressStep += 100; overallProgress.setValue(overallProgressStep); } taskLabel.setText(""); taskProgress.setValue(taskProgress.getMaximum()); overallProgress.setValue(overallProgress.getMaximum()); if (dependencies.size() > 0) { GuiDialogs.showWarning(Installer.getString("eclipsePlugins.manual")); } return Boolean.TRUE; } }); if (successful.booleanValue()) { overallProgress.setValue(overallProgress.getMaximum()); overallLabel.setText(Installer.getString("install.done")); taskProgress.setValue(taskProgress.getMaximum()); taskLabel.setText(Installer.getString("install.done")); setBusy(false); setValid(true); taskProgress.setIndeterminate(false); skipButton.setEnabled(false); } } catch (Exception ex) { setError(ex); } } } private class SkipPluginsAction extends AbstractAction { private static final long serialVersionUID = 1L; public SkipPluginsAction() { super("Skip"); } public void actionPerformed(ActionEvent e) { if (GuiDialogs.showConfirm(Installer.getString("eclipsePlugins.skip"))) { setValid(true); } } } private class DependencyCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); Feature feature = ((Dependency) dependencies.get(row)).getFeature(); if (feature != null && (feature.getSite() == null || !feature.getSite().canWrite())) { component.setBackground(isSelected ? theme.getMenuItemSelectedBackground() : ERROR_COLOR); component.setForeground(isSelected ? ERROR_COLOR : Color.BLACK); } else { component.setBackground(isSelected ? theme.getMenuItemSelectedBackground() : Color.WHITE); component.setForeground( isSelected ? theme.getMenuItemSelectedForeground() : theme.getMenuForeground()); } return component; } } /** * Mouse listener for the feature list. */ private class DependencySelectionListener implements ListSelectionListener { @Override public void valueChanged(ListSelectionEvent e) { ListSelectionModel model = (ListSelectionModel) e.getSource(); int index = model.getMinSelectionIndex(); Feature feature = index >= 0 ? ((Dependency) dependencies.get(index)).getFeature() : null; if (feature != null) { if (feature.getSite() == null) { setMessage(Installer.getString("eclipsePlugins.upgrade.site.not.found")); } else if (!feature.getSite().canWrite()) { setMessage(Installer.getString("eclipsePlugins.upgrade.permission.denied")); } } else { setMessage(null); } } } private static class FeatureNameComparator implements Comparator<String> { private static ArrayList<String> NAMES = new ArrayList<String>(); static { NAMES.add("featureList.jdt"); NAMES.add("featureList.wst"); NAMES.add("featureList.adt"); NAMES.add("featureList.cdt"); NAMES.add("featureList.pdt"); NAMES.add("featureList.python"); NAMES.add("featureList.sdt"); } public int compare(String ob1, String ob2) { return NAMES.indexOf(ob1) - NAMES.indexOf(ob2); } } }