1 /*
   2  * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package anttasks;
  27 
  28 import java.awt.GridBagConstraints;
  29 import java.awt.GridBagLayout;
  30 import java.awt.event.ActionEvent;
  31 import java.awt.event.ActionListener;
  32 import java.awt.event.FocusEvent;
  33 import java.awt.event.FocusListener;
  34 import java.awt.event.ItemEvent;
  35 import java.awt.event.ItemListener;
  36 import java.io.BufferedReader;
  37 import java.io.BufferedWriter;
  38 import java.io.File;
  39 import java.io.FileReader;
  40 import java.io.FileWriter;
  41 import java.io.IOException;
  42 import java.io.Reader;
  43 import java.io.Writer;
  44 import java.util.ArrayList;
  45 import java.util.Arrays;
  46 import java.util.List;
  47 import java.util.Properties;
  48 import javax.swing.JButton;
  49 import javax.swing.JCheckBox;
  50 import javax.swing.JComboBox;
  51 import javax.swing.JDialog;
  52 import javax.swing.JLabel;
  53 import javax.swing.JOptionPane;
  54 import javax.swing.JPanel;
  55 import javax.swing.JTextField;
  56 
  57 import javax.swing.SwingUtilities;
  58 import org.apache.tools.ant.BuildException;
  59 import org.apache.tools.ant.Project;
  60 import org.apache.tools.ant.Task;
  61 
  62 /**
  63  * Task to allow the user to control langtools tools built when using NetBeans.
  64  *
  65  * There are two primary modes.
  66  * 1) Property mode. In this mode, property names are provided to get values
  67  * that may be specified by the user, either directly in a GUI dialog, or
  68  * read from a properties file. If the GUI dialog is invoked, values may
  69  * optionally be set for future use.
  70  * 2) Setup mode. In this mode, no property names are provided, and the GUI
  71  * is invoked to allow the user to set or reset values for use in property mode.
  72  */
  73 public class SelectToolTask extends Task {
  74     /**
  75      * Set the location of the private properties file used to keep the retain
  76      * user preferences for this repository.
  77      */
  78     public void setPropertyFile(File propertyFile) {
  79         this.propertyFile = propertyFile;
  80     }
  81 
  82     /**
  83      * Set the name of the property which will be set to the name of the
  84      * selected tool, if any. If no tool is selected, the property will
  85      * remain unset.
  86      */
  87     public void setToolProperty(String toolProperty) {
  88         this.toolProperty = toolProperty;
  89     }
  90 
  91     /**
  92      * Set the name of the property which will be set to the execution args of the
  93      * selected tool, if any. The args default to an empty string.
  94      */
  95     public void setArgsProperty(String argsProperty) {
  96         this.argsProperty = argsProperty;
  97     }
  98 
  99     /**
 100      * Specify whether or not to pop up a dialog if the user has not specified
 101      * a default value for a property.
 102      */
 103     public void setAskIfUnset(boolean askIfUnset) {
 104         this.askIfUnset = askIfUnset;
 105     }
 106 
 107     @Override
 108     public void execute() {
 109         Project p = getProject();
 110 
 111         Properties props = readProperties(propertyFile);
 112         toolName = props.getProperty("tool.name");
 113         if (toolName != null) {
 114             toolArgs = props.getProperty(toolName + ".args", "");
 115         }
 116 
 117         if (toolProperty == null ||
 118             askIfUnset && (toolName == null
 119                 || (argsProperty != null && toolArgs == null))) {
 120             showGUI(props);
 121         }
 122 
 123         // finally, return required values, if any
 124         if (toolProperty != null && !(toolName == null || toolName.equals(""))) {
 125             p.setProperty(toolProperty, toolName);
 126 
 127             if (argsProperty != null && toolArgs != null)
 128                 p.setProperty(argsProperty, toolArgs);
 129         }
 130     }
 131 
 132     void showGUI(Properties fileProps) {
 133         Properties guiProps = new Properties(fileProps);
 134         JOptionPane p = createPane(guiProps);
 135         p.createDialog("Select Tool").setVisible(true);
 136 
 137         toolName = (String) toolChoice.getSelectedItem();
 138         toolArgs = argsField.getText();
 139 
 140         if (defaultCheck.isSelected()) {
 141             if (toolName.equals("")) {
 142                 fileProps.remove("tool.name");
 143             } else {
 144                 fileProps.put("tool.name", toolName);
 145                 fileProps.put(toolName + ".args", toolArgs);
 146             }
 147             writeProperties(propertyFile, fileProps);
 148         }
 149     }
 150 
 151     JOptionPane createPane(final Properties props) {
 152         JPanel body = new JPanel(new GridBagLayout());
 153         GridBagConstraints lc = new GridBagConstraints();
 154         lc.insets.right = 10;
 155         lc.insets.bottom = 3;
 156         GridBagConstraints fc = new GridBagConstraints();
 157         fc.anchor = GridBagConstraints.WEST;
 158         fc.gridx = 1;
 159         fc.gridwidth = GridBagConstraints.REMAINDER;
 160         fc.insets.bottom = 3;
 161 
 162         JLabel toolLabel = new JLabel("Tool:");
 163         body.add(toolLabel, lc);
 164         String[] toolChoices = { "apt", "javac", "javadoc", "javah", "javap" };
 165         if (true || toolProperty == null) {
 166             // include empty value in setup mode
 167             List<String> l = new ArrayList<String>(Arrays.asList(toolChoices));
 168             l.add(0, "");
 169             toolChoices = l.toArray(new String[l.size()]);
 170         }
 171         toolChoice = new JComboBox(toolChoices);
 172         if (toolName != null)
 173             toolChoice.setSelectedItem(toolName);
 174         toolChoice.addItemListener(new ItemListener() {
 175             public void itemStateChanged(ItemEvent e) {
 176                 String tn = (String) e.getItem();
 177                 argsField.setText(getDefaultArgsForTool(props, tn));
 178                 if (toolProperty != null)
 179                     okButton.setEnabled(!tn.equals(""));
 180             }
 181         });
 182         body.add(toolChoice, fc);
 183 
 184         argsField = new JTextField(getDefaultArgsForTool(props, toolName), 40);
 185         if (toolProperty == null || argsProperty != null) {
 186             JLabel argsLabel = new JLabel("Args:");
 187             body.add(argsLabel, lc);
 188             body.add(argsField, fc);
 189             argsField.addFocusListener(new FocusListener() {
 190                 public void focusGained(FocusEvent e) {
 191                 }
 192                 public void focusLost(FocusEvent e) {
 193                     String toolName = (String) toolChoice.getSelectedItem();
 194                     if (toolName.length() > 0)
 195                         props.put(toolName + ".args", argsField.getText());
 196                 }
 197             });
 198         }
 199 
 200         defaultCheck = new JCheckBox("Set as default");
 201         if (toolProperty == null)
 202             defaultCheck.setSelected(true);
 203         else
 204             body.add(defaultCheck, fc);
 205 
 206         final JOptionPane p = new JOptionPane(body);
 207         okButton = new JButton("OK");
 208         okButton.setEnabled(toolProperty == null || (toolName != null && !toolName.equals("")));
 209         okButton.addActionListener(new ActionListener() {
 210             public void actionPerformed(ActionEvent e) {
 211                 JDialog d = (JDialog) SwingUtilities.getAncestorOfClass(JDialog.class, p);
 212                 d.setVisible(false);
 213             }
 214         });
 215         p.setOptions(new Object[] { okButton });
 216 
 217         return p;
 218     }
 219 
 220     Properties readProperties(File file) {
 221         Properties p = new Properties();
 222         if (file != null && file.exists()) {
 223             Reader in = null;
 224             try {
 225                 in = new BufferedReader(new FileReader(file));
 226                 p.load(in);
 227                 in.close();
 228             } catch (IOException e) {
 229                 throw new BuildException("error reading property file", e);
 230             } finally {
 231                 if (in != null) {
 232                     try {
 233                         in.close();
 234                     } catch (IOException e) {
 235                         throw new BuildException("cannot close property file", e);
 236                     }
 237                 }
 238             }
 239         }
 240         return p;
 241     }
 242 
 243     void writeProperties(File file, Properties p) {
 244         if (file != null) {
 245             Writer out = null;
 246             try {
 247                 File dir = file.getParentFile();
 248                 if (dir != null && !dir.exists())
 249                     dir.mkdirs();
 250                 out = new BufferedWriter(new FileWriter(file));
 251                 p.store(out, "langtools properties");
 252                 out.close();
 253             } catch (IOException e) {
 254                 throw new BuildException("error writing property file", e);
 255             } finally {
 256                 if (out != null) {
 257                     try {
 258                         out.close();
 259                     } catch (IOException e) {
 260                         throw new BuildException("cannot close property file", e);
 261                     }
 262                 }
 263             }
 264         }
 265     }
 266 
 267     String getDefaultArgsForTool(Properties props, String tn) {
 268         return (tn == null || tn.equals("")) ? "" : props.getProperty(tn + ".args", "");
 269     }
 270 
 271     // Ant task parameters
 272     private boolean askIfUnset;
 273     private String toolProperty;
 274     private String argsProperty;
 275     private File propertyFile;
 276 
 277     // GUI components
 278     private JComboBox toolChoice;
 279     private JTextField argsField;
 280     private JCheckBox defaultCheck;
 281     private JButton okButton;
 282 
 283     // Result values for the client
 284     private String toolName;
 285     private String toolArgs;
 286 }