jjg@201: /* mcimadamore@2021: * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. jjg@201: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@201: * jjg@201: * This code is free software; you can redistribute it and/or modify it jjg@201: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this jjg@201: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. jjg@201: * jjg@201: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@201: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@201: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@201: * version 2 for more details (a copy is included in the LICENSE file that jjg@201: * accompanied this code). jjg@201: * jjg@201: * You should have received a copy of the GNU General Public License version jjg@201: * 2 along with this work; if not, write to the Free Software Foundation, jjg@201: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@201: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. jjg@201: */ jjg@201: ohrstrom@1224: package anttasks; ohrstrom@1224: jjg@201: import java.awt.GridBagConstraints; jjg@201: import java.awt.GridBagLayout; jjg@201: import java.awt.event.ActionEvent; jjg@201: import java.awt.event.ActionListener; jjg@201: import java.awt.event.FocusEvent; jjg@201: import java.awt.event.FocusListener; jjg@201: import java.awt.event.ItemEvent; jjg@201: import java.awt.event.ItemListener; jjg@201: import java.io.BufferedReader; jjg@201: import java.io.BufferedWriter; jjg@201: import java.io.File; jjg@201: import java.io.FileReader; jjg@201: import java.io.FileWriter; jjg@201: import java.io.IOException; jjg@201: import java.io.Reader; jjg@201: import java.io.Writer; jjg@201: import java.util.ArrayList; jjg@201: import java.util.Arrays; mcimadamore@2021: import java.util.EnumSet; jjg@201: import java.util.List; jjg@201: import java.util.Properties; jjg@201: import javax.swing.JButton; jjg@201: import javax.swing.JCheckBox; jjg@201: import javax.swing.JComboBox; jjg@201: import javax.swing.JDialog; jjg@201: import javax.swing.JLabel; jjg@201: import javax.swing.JOptionPane; jjg@201: import javax.swing.JPanel; jjg@201: import javax.swing.JTextField; jjg@201: jjg@201: import javax.swing.SwingUtilities; jjg@201: import org.apache.tools.ant.BuildException; jjg@201: import org.apache.tools.ant.Project; jjg@201: import org.apache.tools.ant.Task; jjg@201: jjg@201: /** jjg@201: * Task to allow the user to control langtools tools built when using NetBeans. jjg@201: * jjg@201: * There are two primary modes. jjg@201: * 1) Property mode. In this mode, property names are provided to get values jjg@201: * that may be specified by the user, either directly in a GUI dialog, or jjg@201: * read from a properties file. If the GUI dialog is invoked, values may jjg@201: * optionally be set for future use. jjg@201: * 2) Setup mode. In this mode, no property names are provided, and the GUI jjg@201: * is invoked to allow the user to set or reset values for use in property mode. jjg@201: */ jjg@201: public class SelectToolTask extends Task { mcimadamore@2021: mcimadamore@2021: enum ToolChoices { mcimadamore@2021: NONE(""), mcimadamore@2021: JAVAC("javac"), mcimadamore@2021: JAVADOC("javadoc"), mcimadamore@2021: JAVAH("javah"), mcimadamore@2021: JAVAP("javap"); mcimadamore@2021: mcimadamore@2021: String toolName; mcimadamore@2021: boolean bootstrap; mcimadamore@2021: mcimadamore@2021: ToolChoices(String toolName) { mcimadamore@2021: this(toolName, false); mcimadamore@2021: } mcimadamore@2021: vromero@2064: ToolChoices(String toolName, boolean bootstrap) { mcimadamore@2021: this.toolName = toolName; vromero@2064: this.bootstrap = bootstrap; mcimadamore@2021: } mcimadamore@2021: mcimadamore@2021: @Override mcimadamore@2021: public String toString() { mcimadamore@2021: return toolName; mcimadamore@2021: } mcimadamore@2021: } mcimadamore@2021: jjg@201: /** jjg@201: * Set the location of the private properties file used to keep the retain jjg@201: * user preferences for this repository. jjg@201: */ jjg@201: public void setPropertyFile(File propertyFile) { jjg@201: this.propertyFile = propertyFile; jjg@201: } jjg@201: jjg@201: /** jjg@201: * Set the name of the property which will be set to the name of the jjg@201: * selected tool, if any. If no tool is selected, the property will jjg@201: * remain unset. jjg@201: */ jjg@201: public void setToolProperty(String toolProperty) { jjg@201: this.toolProperty = toolProperty; jjg@201: } jjg@201: jjg@201: /** jjg@201: * Set the name of the property which will be set to the execution args of the jjg@201: * selected tool, if any. The args default to an empty string. jjg@201: */ jjg@201: public void setArgsProperty(String argsProperty) { jjg@201: this.argsProperty = argsProperty; jjg@201: } jjg@201: jjg@201: /** mcimadamore@2021: * Set the name of the property which will be set to the execution args of the mcimadamore@2021: * selected tool, if any. The args default to an empty string. mcimadamore@2021: */ mcimadamore@2021: public void setBootstrapProperty(String bootstrapProperty) { mcimadamore@2021: this.bootstrapProperty = bootstrapProperty; mcimadamore@2021: } mcimadamore@2021: mcimadamore@2021: /** jjg@201: * Specify whether or not to pop up a dialog if the user has not specified jjg@201: * a default value for a property. jjg@201: */ jjg@201: public void setAskIfUnset(boolean askIfUnset) { jjg@201: this.askIfUnset = askIfUnset; jjg@201: } jjg@201: jjg@201: @Override jjg@201: public void execute() { jjg@201: Project p = getProject(); jjg@201: jjg@201: Properties props = readProperties(propertyFile); jjg@201: toolName = props.getProperty("tool.name"); mcimadamore@2021: toolBootstrap = props.getProperty("tool.bootstrap") != null; jjg@201: if (toolName != null) { jjg@201: toolArgs = props.getProperty(toolName + ".args", ""); jjg@201: } jjg@201: jjg@201: if (toolProperty == null || jjg@201: askIfUnset && (toolName == null jjg@201: || (argsProperty != null && toolArgs == null))) { jjg@201: showGUI(props); jjg@201: } jjg@201: jjg@201: // finally, return required values, if any jjg@201: if (toolProperty != null && !(toolName == null || toolName.equals(""))) { jjg@201: p.setProperty(toolProperty, toolName); mcimadamore@2021: if (toolBootstrap) mcimadamore@2021: p.setProperty(bootstrapProperty, "true"); jjg@201: jjg@201: if (argsProperty != null && toolArgs != null) jjg@201: p.setProperty(argsProperty, toolArgs); jjg@201: } jjg@201: } jjg@201: jjg@201: void showGUI(Properties fileProps) { jjg@201: Properties guiProps = new Properties(fileProps); jjg@201: JOptionPane p = createPane(guiProps); jjg@201: p.createDialog("Select Tool").setVisible(true); jjg@201: mcimadamore@2021: toolName = ((ToolChoices)toolChoice.getSelectedItem()).toolName; jjg@201: toolArgs = argsField.getText(); mcimadamore@2021: toolBootstrap = bootstrapCheckbox.isSelected(); jjg@201: if (defaultCheck.isSelected()) { jjg@201: if (toolName.equals("")) { jjg@201: fileProps.remove("tool.name"); mcimadamore@2021: fileProps.remove("tool.bootstrap"); jjg@201: } else { jjg@201: fileProps.put("tool.name", toolName); mcimadamore@2021: if (toolBootstrap) { mcimadamore@2021: fileProps.put("tool.bootstrap", "true"); mcimadamore@2021: } else { mcimadamore@2021: fileProps.remove("tool.bootstrap"); mcimadamore@2021: } jjg@201: fileProps.put(toolName + ".args", toolArgs); jjg@201: } jjg@201: writeProperties(propertyFile, fileProps); jjg@201: } jjg@201: } jjg@201: jjg@201: JOptionPane createPane(final Properties props) { jjg@201: JPanel body = new JPanel(new GridBagLayout()); jjg@201: GridBagConstraints lc = new GridBagConstraints(); jjg@201: lc.insets.right = 10; jjg@201: lc.insets.bottom = 3; jjg@201: GridBagConstraints fc = new GridBagConstraints(); jjg@201: fc.gridx = 1; mcimadamore@2021: fc.gridwidth = GridBagConstraints.NONE; jjg@201: fc.insets.bottom = 3; jjg@201: mcimadamore@2021: JPanel toolPane = new JPanel(new GridBagLayout()); mcimadamore@2021: jjg@201: JLabel toolLabel = new JLabel("Tool:"); jjg@201: body.add(toolLabel, lc); mcimadamore@2021: EnumSet toolChoices = toolProperty == null ? mcimadamore@2021: EnumSet.allOf(ToolChoices.class) : EnumSet.range(ToolChoices.JAVAC, ToolChoices.JAVAP); mcimadamore@2021: toolChoice = new JComboBox(toolChoices.toArray()); jjg@201: if (toolName != null) mcimadamore@2021: toolChoice.setSelectedItem(ToolChoices.valueOf(toolName.toUpperCase())); jjg@201: toolChoice.addItemListener(new ItemListener() { jjg@201: public void itemStateChanged(ItemEvent e) { mcimadamore@2021: String tn = ((ToolChoices)e.getItem()).toolName; jjg@201: argsField.setText(getDefaultArgsForTool(props, tn)); jjg@201: if (toolProperty != null) jjg@201: okButton.setEnabled(!tn.equals("")); jjg@201: } jjg@201: }); mcimadamore@2021: GridBagConstraints checkConstraint = new GridBagConstraints(); mcimadamore@2021: fc.anchor = GridBagConstraints.EAST; mcimadamore@2021: mcimadamore@2021: GridBagConstraints toolConstraint = new GridBagConstraints(); mcimadamore@2021: fc.anchor = GridBagConstraints.WEST; mcimadamore@2021: mcimadamore@2021: toolPane.add(toolChoice, toolConstraint); mcimadamore@2021: bootstrapCheckbox = new JCheckBox("bootstrap", toolBootstrap); mcimadamore@2021: toolPane.add(bootstrapCheckbox, checkConstraint); mcimadamore@2021: mcimadamore@2021: body.add(toolPane, fc); jjg@201: jjg@201: argsField = new JTextField(getDefaultArgsForTool(props, toolName), 40); jjg@201: if (toolProperty == null || argsProperty != null) { jjg@201: JLabel argsLabel = new JLabel("Args:"); jjg@201: body.add(argsLabel, lc); jjg@201: body.add(argsField, fc); jjg@201: argsField.addFocusListener(new FocusListener() { jjg@201: public void focusGained(FocusEvent e) { jjg@201: } jjg@201: public void focusLost(FocusEvent e) { mcimadamore@2021: String toolName = ((ToolChoices)toolChoice.getSelectedItem()).toolName; jjg@201: if (toolName.length() > 0) jjg@201: props.put(toolName + ".args", argsField.getText()); jjg@201: } jjg@201: }); jjg@201: } jjg@201: jjg@201: defaultCheck = new JCheckBox("Set as default"); jjg@201: if (toolProperty == null) jjg@201: defaultCheck.setSelected(true); jjg@201: else jjg@201: body.add(defaultCheck, fc); jjg@201: jjg@201: final JOptionPane p = new JOptionPane(body); jjg@201: okButton = new JButton("OK"); jjg@201: okButton.setEnabled(toolProperty == null || (toolName != null && !toolName.equals(""))); jjg@201: okButton.addActionListener(new ActionListener() { jjg@201: public void actionPerformed(ActionEvent e) { jjg@201: JDialog d = (JDialog) SwingUtilities.getAncestorOfClass(JDialog.class, p); jjg@201: d.setVisible(false); jjg@201: } jjg@201: }); jjg@201: p.setOptions(new Object[] { okButton }); jjg@201: jjg@201: return p; jjg@201: } jjg@201: jjg@201: Properties readProperties(File file) { jjg@201: Properties p = new Properties(); jjg@201: if (file != null && file.exists()) { jjg@201: Reader in = null; jjg@201: try { jjg@201: in = new BufferedReader(new FileReader(file)); jjg@201: p.load(in); jjg@201: in.close(); jjg@201: } catch (IOException e) { jjg@201: throw new BuildException("error reading property file", e); jjg@201: } finally { jjg@201: if (in != null) { jjg@201: try { jjg@201: in.close(); jjg@201: } catch (IOException e) { jjg@201: throw new BuildException("cannot close property file", e); jjg@201: } jjg@201: } jjg@201: } jjg@201: } jjg@201: return p; jjg@201: } jjg@201: jjg@201: void writeProperties(File file, Properties p) { jjg@201: if (file != null) { jjg@201: Writer out = null; jjg@201: try { jjg@201: File dir = file.getParentFile(); jjg@201: if (dir != null && !dir.exists()) jjg@201: dir.mkdirs(); jjg@201: out = new BufferedWriter(new FileWriter(file)); jjg@201: p.store(out, "langtools properties"); jjg@201: out.close(); jjg@201: } catch (IOException e) { jjg@201: throw new BuildException("error writing property file", e); jjg@201: } finally { jjg@201: if (out != null) { jjg@201: try { jjg@201: out.close(); jjg@201: } catch (IOException e) { jjg@201: throw new BuildException("cannot close property file", e); jjg@201: } jjg@201: } jjg@201: } jjg@201: } jjg@201: } jjg@201: jjg@201: String getDefaultArgsForTool(Properties props, String tn) { jjg@201: return (tn == null || tn.equals("")) ? "" : props.getProperty(tn + ".args", ""); jjg@201: } jjg@201: jjg@201: // Ant task parameters jjg@201: private boolean askIfUnset; jjg@201: private String toolProperty; mcimadamore@2021: private String bootstrapProperty; jjg@201: private String argsProperty; jjg@201: private File propertyFile; jjg@201: jjg@201: // GUI components jjg@201: private JComboBox toolChoice; mcimadamore@2021: private JCheckBox bootstrapCheckbox; jjg@201: private JTextField argsField; jjg@201: private JCheckBox defaultCheck; jjg@201: private JButton okButton; jjg@201: jjg@201: // Result values for the client jjg@201: private String toolName; mcimadamore@2021: private boolean toolBootstrap; jjg@201: private String toolArgs; jjg@201: }