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