1/* 2 * Copyright (c) 2008, 2016, 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 26package anttasks; 27 28import java.awt.GridBagConstraints; 29import java.awt.GridBagLayout; 30import java.awt.event.ActionEvent; 31import java.awt.event.ActionListener; 32import java.awt.event.FocusEvent; 33import java.awt.event.FocusListener; 34import java.awt.event.ItemEvent; 35import java.awt.event.ItemListener; 36import java.io.BufferedReader; 37import java.io.BufferedWriter; 38import java.io.File; 39import java.io.FileReader; 40import java.io.FileWriter; 41import java.io.IOException; 42import java.io.Reader; 43import java.io.Writer; 44import java.util.EnumSet; 45import java.util.Properties; 46 47import javax.swing.JButton; 48import javax.swing.JCheckBox; 49import javax.swing.JComboBox; 50import javax.swing.JDialog; 51import javax.swing.JLabel; 52import javax.swing.JOptionPane; 53import javax.swing.JPanel; 54import javax.swing.JTextField; 55 56import javax.swing.SwingUtilities; 57 58import org.apache.tools.ant.BuildException; 59import org.apache.tools.ant.Project; 60import 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 */ 73public class SelectToolTask extends Task { 74 75 enum ToolChoices { 76 NONE(""), 77 JAVAC("javac"), 78 JAVADOC("javadoc"), 79 JAVAH("javah"), 80 JAVAP("javap"), 81 JSHELL("jshell"); 82 83 String toolName; 84 boolean bootstrap; 85 86 ToolChoices(String toolName) { 87 this(toolName, false); 88 } 89 90 ToolChoices(String toolName, boolean bootstrap) { 91 this.toolName = toolName; 92 this.bootstrap = bootstrap; 93 } 94 95 @Override 96 public String toString() { 97 return toolName; 98 } 99 } 100 101 /** 102 * Set the location of the private properties file used to keep the retain 103 * user preferences for this repository. 104 * @param propertyFile the private properties file 105 */ 106 public void setPropertyFile(File propertyFile) { 107 this.propertyFile = propertyFile; 108 } 109 110 /** 111 * Set the name of the property which will be set to the name of the 112 * selected tool, if any. If no tool is selected, the property will 113 * remain unset. 114 * @param toolProperty the tool name property 115 */ 116 public void setToolProperty(String toolProperty) { 117 this.toolProperty = toolProperty; 118 } 119 120 /** 121 * Set the name of the property which will be set to the execution args of the 122 * selected tool, if any. The args default to an empty string. 123 * @param argsProperty the execution args property value 124 */ 125 public void setArgsProperty(String argsProperty) { 126 this.argsProperty = argsProperty; 127 } 128 129 /** 130 * Specify whether or not to pop up a dialog if the user has not specified 131 * a default value for a property. 132 * @param askIfUnset a boolean flag indicating to prompt the user or not 133 */ 134 public void setAskIfUnset(boolean askIfUnset) { 135 this.askIfUnset = askIfUnset; 136 } 137 138 @Override 139 public void execute() { 140 Project p = getProject(); 141 142 Properties props = readProperties(propertyFile); 143 toolName = props.getProperty("tool.name"); 144 if (toolName != null) { 145 toolArgs = props.getProperty(toolName + ".args", ""); 146 } 147 148 if (toolProperty == null || 149 askIfUnset && (toolName == null 150 || (argsProperty != null && toolArgs == null))) { 151 showGUI(props); 152 } 153 154 // finally, return required values, if any 155 if (toolProperty != null && !(toolName == null || toolName.equals(""))) { 156 p.setProperty(toolProperty, toolName); 157 158 if (argsProperty != null && toolArgs != null) 159 p.setProperty(argsProperty, toolArgs); 160 } 161 } 162 163 void showGUI(Properties fileProps) { 164 Properties guiProps = new Properties(fileProps); 165 JOptionPane p = createPane(guiProps); 166 p.createDialog("Select Tool").setVisible(true); 167 168 ToolChoices tool = (ToolChoices)toolChoice.getSelectedItem(); 169 170 toolName = tool.toolName; 171 toolArgs = argsField.getText(); 172 if (defaultCheck.isSelected()) { 173 if (toolName.equals("")) { 174 fileProps.remove("tool.name"); 175 fileProps.remove("tool.bootstrap"); 176 } else { 177 fileProps.remove("tool.bootstrap"); 178 fileProps.put("tool.name", toolName); 179 fileProps.put(toolName + ".args", toolArgs); 180 } 181 writeProperties(propertyFile, fileProps); 182 } 183 } 184 185 JOptionPane createPane(final Properties props) { 186 JPanel body = new JPanel(new GridBagLayout()); 187 GridBagConstraints lc = new GridBagConstraints(); 188 lc.insets.right = 10; 189 lc.insets.bottom = 3; 190 GridBagConstraints fc = new GridBagConstraints(); 191 fc.gridx = 1; 192 fc.gridwidth = GridBagConstraints.NONE; 193 fc.insets.bottom = 3; 194 195 JPanel toolPane = new JPanel(new GridBagLayout()); 196 197 JLabel toolLabel = new JLabel("Tool:"); 198 body.add(toolLabel, lc); 199 EnumSet<ToolChoices> toolChoices = toolProperty == null ? 200 EnumSet.allOf(ToolChoices.class) : EnumSet.range(ToolChoices.JAVAC, ToolChoices.JAVAP); 201 toolChoice = new JComboBox<>(toolChoices.toArray()); 202 ToolChoices tool = toolName != null ? ToolChoices.valueOf(toolName.toUpperCase()) : null; 203 if (toolName != null) { 204 toolChoice.setSelectedItem(tool); 205 } 206 toolChoice.addItemListener(e -> { 207 ToolChoices tool1 = (ToolChoices)e.getItem(); 208 argsField.setText(getDefaultArgsForTool(props, tool1)); 209 if (toolProperty != null) 210 okButton.setEnabled(tool1 != ToolChoices.NONE); 211 }); 212 fc.anchor = GridBagConstraints.EAST; 213 214 GridBagConstraints toolConstraint = new GridBagConstraints(); 215 fc.anchor = GridBagConstraints.WEST; 216 217 toolPane.add(toolChoice, toolConstraint); 218 219 body.add(toolPane, fc); 220 221 argsField = new JTextField(getDefaultArgsForTool(props, tool), 40); 222 if (toolProperty == null || argsProperty != null) { 223 JLabel argsLabel = new JLabel("Args:"); 224 body.add(argsLabel, lc); 225 body.add(argsField, fc); 226 argsField.addFocusListener(new FocusListener() { 227 @Override 228 public void focusGained(FocusEvent e) { 229 } 230 @Override 231 public void focusLost(FocusEvent e) { 232 String toolName = ((ToolChoices)toolChoice.getSelectedItem()).toolName; 233 if (toolName.length() > 0) 234 props.put(toolName + ".args", argsField.getText()); 235 } 236 }); 237 } 238 239 defaultCheck = new JCheckBox("Set as default"); 240 if (toolProperty == null) 241 defaultCheck.setSelected(true); 242 else 243 body.add(defaultCheck, fc); 244 245 final JOptionPane p = new JOptionPane(body); 246 okButton = new JButton("OK"); 247 okButton.setEnabled(toolProperty == null || (toolName != null && !toolName.equals(""))); 248 okButton.addActionListener(e -> { 249 JDialog d = (JDialog) SwingUtilities.getAncestorOfClass(JDialog.class, p); 250 d.setVisible(false); 251 }); 252 p.setOptions(new Object[] { okButton }); 253 254 return p; 255 } 256 257 Properties readProperties(File file) { 258 Properties p = new Properties(); 259 if (file != null && file.exists()) { 260 Reader in = null; 261 try { 262 in = new BufferedReader(new FileReader(file)); 263 p.load(in); 264 in.close(); 265 } catch (IOException e) { 266 throw new BuildException("error reading property file", e); 267 } finally { 268 if (in != null) { 269 try { 270 in.close(); 271 } catch (IOException e) { 272 throw new BuildException("cannot close property file", e); 273 } 274 } 275 } 276 } 277 return p; 278 } 279 280 void writeProperties(File file, Properties p) { 281 if (file != null) { 282 Writer out = null; 283 try { 284 File dir = file.getParentFile(); 285 if (dir != null && !dir.exists()) 286 dir.mkdirs(); 287 out = new BufferedWriter(new FileWriter(file)); 288 p.store(out, "langtools properties"); 289 out.close(); 290 } catch (IOException e) { 291 throw new BuildException("error writing property file", e); 292 } finally { 293 if (out != null) { 294 try { 295 out.close(); 296 } catch (IOException e) { 297 throw new BuildException("cannot close property file", e); 298 } 299 } 300 } 301 } 302 } 303 304 String getDefaultArgsForTool(Properties props, ToolChoices tool) { 305 if (tool == null) 306 return ""; 307 String toolName = tool.toolName; 308 return toolName.equals("") ? "" : props.getProperty(toolName + ".args", ""); 309 } 310 311 // Ant task parameters 312 private boolean askIfUnset; 313 private String toolProperty; 314 private String argsProperty; 315 private File propertyFile; 316 317 // GUI components 318 private JComboBox<?> toolChoice; 319 private JTextField argsField; 320 private JCheckBox defaultCheck; 321 private JButton okButton; 322 323 // Result values for the client 324 private String toolName; 325 private String toolArgs; 326} 327