001package com.ganteater.ae.desktop; 002 003import java.awt.BorderLayout; 004import java.awt.Component; 005import java.awt.Container; 006import java.awt.Frame; 007import java.awt.HeadlessException; 008import java.awt.event.WindowAdapter; 009import java.awt.event.WindowEvent; 010import java.io.BufferedReader; 011import java.io.File; 012import java.io.FileOutputStream; 013import java.io.FileReader; 014import java.io.FileWriter; 015import java.io.IOException; 016import java.util.Arrays; 017import java.util.List; 018 019import javax.swing.Icon; 020import javax.swing.JDialog; 021import javax.swing.JFileChooser; 022import javax.swing.JLabel; 023import javax.swing.JOptionPane; 024import javax.swing.JPanel; 025import javax.swing.JPasswordField; 026import javax.swing.JScrollPane; 027import javax.swing.JTable; 028import javax.swing.WindowConstants; 029import javax.swing.filechooser.FileFilter; 030import javax.swing.table.AbstractTableModel; 031 032import org.apache.commons.io.FilenameUtils; 033import org.apache.commons.lang.ObjectUtils; 034import org.apache.commons.lang.StringUtils; 035import org.apache.commons.lang.SystemUtils; 036 037import com.ganteater.ae.AEWorkspace; 038import com.ganteater.ae.CommandException; 039import com.ganteater.ae.ILogger; 040import com.ganteater.ae.MultiTaskRunDialog; 041import com.ganteater.ae.RecipeRunner; 042import com.ganteater.ae.desktop.editor.TaskEditor; 043import com.ganteater.ae.desktop.ui.AEFrame; 044import com.ganteater.ae.desktop.ui.AEFrame.UIChoiceTaskRunner; 045import com.ganteater.ae.desktop.ui.CheckPointBox; 046import com.ganteater.ae.desktop.ui.ConfigurationView; 047import com.ganteater.ae.desktop.ui.InputTableModel; 048import com.ganteater.ae.desktop.ui.OptionPane; 049import com.ganteater.ae.desktop.util.SoundManager; 050import com.ganteater.ae.desktop.util.UIUtils; 051import com.ganteater.ae.processor.MessageHandler; 052import com.ganteater.ae.processor.Processor; 053import com.ganteater.ae.util.xml.easyparser.Node; 054 055public class DesktopWorkspace extends AEWorkspace { 056 057 private static final String INPUT_FILE_NAME = ".inputFile"; 058 059 private final class JFileChooserExtension extends JFileChooser { 060 private static final long serialVersionUID = 1L; 061 private final String name; 062 private int returnValue; 063 064 private JFileChooserExtension(String name) { 065 this.name = name; 066 } 067 068 @Override 069 protected JDialog createDialog(Component parent) throws HeadlessException { 070 JDialog dialog = super.createDialog(parent); 071 Container contentPane = dialog.getContentPane(); 072 CheckPointBox vip = new CheckPointBox(name, null, InputDialogType.FILE); 073 contentPane.add(vip, BorderLayout.SOUTH); 074 075 dialog.addWindowListener(new WindowAdapter() { 076 077 @Override 078 public void windowClosing(WindowEvent e) { 079 returnValue = -1; 080 } 081 }); 082 return dialog; 083 } 084 085 @Override 086 public int showDialog(Component parent, String approveButtonText) throws HeadlessException { 087 int showDialog = super.showDialog(parent, approveButtonText); 088 return returnValue == -1 ? -1 : showDialog; 089 } 090 } 091 092 private AEFrame frame; 093 094 public DesktopWorkspace(AEFrame frame) { 095 this.frame = frame; 096 } 097 098 @Override 099 protected String selectConfiguration(String[] aPossibleValues) { 100 String theValue; 101 102 String theDefaultConfiguration = aPossibleValues[0]; 103 theDefaultConfiguration = AEWorkspace.getInstance().getDefaultUserConfiguration(".defaultConfiguration", 104 theDefaultConfiguration); 105 106 frame.setAlwaysOnTop(true); 107 Icon fWelcomeLogo = AEFrame.getIcon(AEFrame.LOGO_JPG); 108 theValue = (String) JOptionPane.showInputDialog(frame, "Environments:", "Giant anteater looking for food ...", 109 JOptionPane.QUESTION_MESSAGE, fWelcomeLogo, aPossibleValues, theDefaultConfiguration); 110 frame.setAlwaysOnTop(false); 111 if (theValue == null) 112 throw new IllegalArgumentException("Configuration is not selected."); 113 114 AEWorkspace.getInstance().setDefaultUserConfiguration(".defaultConfiguration", theValue); 115 116 return theValue; 117 } 118 119 @Override 120 public MultiTaskRunDialog tasksChoice(MultiTaskRunDialog dialog, String[] list, boolean exceptionIgnoreFlag, 121 Object setup, Processor taskProcessor, boolean visible) { 122 UIChoiceTaskRunner runner = frame.getChoiceTaskRunner(dialog, taskProcessor, setup); 123 124 String name = runner.getName(); 125 boolean consoleDefaultInput = isConsoleDefaultInput(name, null); 126 127 if (setup != null) { 128 if (setup instanceof String[]) 129 runner.select((String[]) setup, consoleDefaultInput); 130 else if (setup instanceof List) { 131 @SuppressWarnings("unchecked") 132 List<String> setupList = (List<String>) setup; 133 String[] array = setupList.toArray(new String[setupList.size()]); 134 runner.select(array, consoleDefaultInput); 135 } else if (setup instanceof String) { 136 String[] attribute = new String[] { (String) setup }; 137 runner.select(attribute, consoleDefaultInput); 138 } 139 } 140 141 runner.setExceptionIgnore(exceptionIgnoreFlag); 142 runner.setVisible(visible); 143 boolean notifyMe = taskProcessor.getListener().isNotifyMe(); 144 145 runner.showDialog(name, list, notifyMe); 146 147 return runner; 148 } 149 150 @Override 151 public void startTaskNotify(RecipeRunner task) { 152 TaskEditor editor = (TaskEditor) task; 153 super.startTaskNotify(editor); 154 frame.startTaskNotify(editor); 155 } 156 157 @Override 158 public void progressValue(int i, int length, boolean success) { 159 frame.progressValue(i, length, success); 160 } 161 162 @Override 163 public void removeRunner(RecipeRunner testRunner) { 164 super.removeRunner(testRunner); 165 frame.endTask(testRunner); 166 } 167 168 @Override 169 public String inputValue(String name, String description, String value, ILogger log, String type, boolean notifyMe, 170 Processor processor) { 171 String inputValue = null; 172 if ("path".equalsIgnoreCase(type)) { 173 File defaultFile; 174 if (value != null) { 175 defaultFile = new File(value); 176 } else { 177 defaultFile = new File(getWorkingDir()); 178 } 179 inputValue = inputFile(name, description, defaultFile, log, processor); 180 } else { 181 inputValue = frame.inputValue(name, description, value, type, notifyMe); 182 } 183 return inputValue; 184 } 185 186 @Override 187 public boolean isConsoleDefaultInput(String varName, String description) { 188 varName = StringUtils.defaultString(description, varName); 189 boolean consoleDefaultInput = "Error Trace".equals(varName) || frame.isConsoleDefaultInput(); 190 if (varName != null && consoleDefaultInput) { 191 Boolean checkPointFlag = false; 192 InputDialogType[] values = InputDialogType.values(); 193 for (InputDialogType inputDialogType : values) { 194 checkPointFlag = CheckPointBox.getCheckPointFlag(inputDialogType, varName); 195 if (checkPointFlag != null) { 196 break; 197 } 198 } 199 consoleDefaultInput = checkPointFlag != null && !checkPointFlag; 200 } 201 return consoleDefaultInput; 202 } 203 204 @Override 205 protected RecipeRunner createTestRunner(String name) throws CommandException { 206 return frame.editTask(name); 207 } 208 209 @Override 210 public String inputChoice(String name, String description, String[] aValues, String aDefaultValue, 211 Processor taskProcessor, boolean notifyMe) { 212 return frame.inputSelectChoice(name, description, aValues, aDefaultValue, notifyMe, null); 213 } 214 215 public String inputFile(String name, String description, File defaultFile, ILogger log, Processor taskProcessor) { 216 String result = null; 217 description = StringUtils.defaultString(description, name); 218 219 String defaultUserConfiguration = getDefaultUserConfiguration(INPUT_FILE_NAME, 220 defaultFile == null ? null : defaultFile.getAbsolutePath()); 221 if (defaultUserConfiguration != null) 222 defaultFile = new File(defaultUserConfiguration); 223 224 result = defaultUserConfiguration; 225 226 if (defaultUserConfiguration == null || !isConsoleDefaultInput(name, null)) { 227 228 JFileChooser chooser = new JFileChooserExtension(name); 229 230 if (defaultFile != null) { 231 String path = defaultFile.getPath(); 232 if (path != null && !"null".equals(path)) { 233 if (defaultFile.isDirectory()) { 234 chooser.setCurrentDirectory(defaultFile.getParentFile()); 235 } else { 236 chooser.setSelectedFile(defaultFile); 237 } 238 } 239 } 240 241 chooser.setDialogTitle(description); 242 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 243 int showOpenDialog = chooser.showOpenDialog(JOptionPane.getRootFrame()); 244 if (showOpenDialog == JFileChooser.APPROVE_OPTION) { 245 result = new File(chooser.getCurrentDirectory(), chooser.getSelectedFile().getName()).getAbsolutePath(); 246 setDefaultUserConfiguration(INPUT_FILE_NAME, result); 247 } else if (showOpenDialog == JFileChooser.CANCEL_OPTION) { 248 result = null; 249 setDefaultUserConfiguration(INPUT_FILE_NAME, result); 250 } else { 251 taskProcessor.stop(); 252 result = null; 253 } 254 255 } 256 257 CheckPointBox.setCheckPointFlag(InputDialogType.FILE, name, (boolean) ObjectUtils 258 .defaultIfNull(CheckPointBox.getCheckPointFlag(InputDialogType.FILE, name), false)); 259 260 return result; 261 } 262 263 @Override 264 public boolean confirmation(String name, String message, Processor unit, boolean notifyMe) throws Exception { 265 266 name = StringUtils.defaultIfEmpty(name, "Confirmation"); 267 if (notifyMe) { 268 frame.getSoundManager().play(); 269 } 270 271 JOptionPane pane = new JOptionPane(message, JOptionPane.WARNING_MESSAGE, JOptionPane.YES_NO_OPTION); 272 JDialog dialog = pane.createDialog(frame, name); 273 dialog.setModal(false); 274 dialog.setResizable(true); 275 276 dialog.setVisible(true); 277 if (!UIUtils.applyPreferedView(dialog, name)) { 278 dialog.pack(); 279 } 280 281 Object value = null; 282 do { 283 value = pane.getValue(); 284 Thread.sleep(100); 285 } while (value == "uninitializedValue"); 286 287 if (notifyMe) { 288 SoundManager.stop(); 289 } 290 291 UIUtils.saveDialogPreferedView(dialog, name); 292 dialog.dispose(); 293 294 if (value == null) { 295 value = -1; 296 } 297 298 int confirm = (int) value; 299 if (confirm < 0) { 300 unit.stop(); 301 } 302 return confirm == JOptionPane.YES_OPTION; 303 } 304 305 @Override 306 public MessageHandler message(final Processor taskProcessor, String title, String message, boolean notifyMe) { 307 String dialogTitle = StringUtils.defaultIfEmpty(title, "Message"); 308 309 JOptionPane pane = new JOptionPane(message, JOptionPane.INFORMATION_MESSAGE); 310 311 JDialog dialog = pane.createDialog(frame, dialogTitle); 312 dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 313 314 MessageHandler handle = new MessageHandler() { 315 @Override 316 public void close() { 317 dialog.dispose(); 318 super.close(); 319 } 320 }; 321 322 dialog.addWindowListener(new WindowAdapter() { 323 @Override 324 public void windowClosed(WindowEvent var1) { 325 if (!handle.isProcessDone()) { 326 taskProcessor.stop(); 327 } 328 UIUtils.saveDialogPreferedView(dialog, dialogTitle); 329 SoundManager.stop(); 330 frame.pushOnTop(); 331 } 332 }); 333 dialog.setModal(false); 334 dialog.setResizable(true); 335 336 if (!UIUtils.applyPreferedView(dialog, dialogTitle)) { 337 dialog.pack(); 338 } 339 340 frame.pushOnTop(); 341 342 if (notifyMe) { 343 frame.getSoundManager().play(); 344 } 345 346 dialog.setVisible(true); 347 348 return handle; 349 } 350 351 public void inputDataTable(Processor unit, Node aTableNode, boolean notifyMe) throws IOException { 352 Node[] theVariablesNodes = aTableNode.getNodes("var"); 353 354 String fileName = aTableNode.getAttribute("file"); 355 if (unit != null) 356 fileName = unit.replaceProperties(aTableNode.getAttribute("file")); 357 358 if (fileName != null) { 359 File file = unit.getFile(fileName); 360 if (file.exists()) { 361 BufferedReader theFileReader = new BufferedReader(new FileReader(file)); 362 String line = null; 363 while ((line = theFileReader.readLine()) != null) { 364 line = line.trim(); 365 if (!line.isEmpty() && line.charAt(0) != '#') { 366 int thePbrk = line.indexOf('='); 367 368 String theName = line.substring(0, thePbrk); 369 String theValue = line.substring(thePbrk + 1); 370 371 Node theNode = new Node("var"); 372 theNode.setAttribute("name", theName); 373 theNode.setAttribute("value", theValue); 374 375 for (Node node : theVariablesNodes) { 376 if (node.getAttribute("name").equalsIgnoreCase(theName)) { 377 node.setAttribute("value", theValue); 378 } 379 } 380 } 381 } 382 theFileReader.close(); 383 } 384 } 385 386 String title = aTableNode.getAttribute("name"); 387 AbstractTableModel dataModel = new InputTableModel(unit, title, theVariablesNodes); 388 389 JTable table = new JTable(dataModel); 390 table.setRowHeight(20); 391 JScrollPane scrollpane = new JScrollPane(table); 392 CheckPointBox vip = new CheckPointBox(title, null, InputDialogType.MAP); 393 394 if ((!Processor.isSilentMode(unit) && !isConsoleDefaultInput(title, null)) || vip.isSelected()) { 395 JPanel jPanel = new JPanel(); 396 jPanel.add(new JLabel(), BorderLayout.NORTH); 397 jPanel.setLayout(new BorderLayout()); 398 jPanel.add(scrollpane, BorderLayout.CENTER); 399 400 jPanel.add(vip, BorderLayout.SOUTH); 401 402 if (notifyMe) { 403 frame.getSoundManager().play(); 404 } 405 406 int showConfirmDialog = OptionPane.showConfirmDialog(frame, jPanel, title); 407 408 if (notifyMe) { 409 SoundManager.stop(); 410 } 411 412 if (showConfirmDialog == -1 || showConfirmDialog == 2) { 413 unit.stop(); 414 } 415 } 416 417 FileWriter theFileReader = null; 418 if (fileName != null) { 419 File file = unit.getFile(fileName); 420 file.getParentFile().mkdirs(); 421 theFileReader = new FileWriter(file); 422 } 423 424 try { 425 for (int row = 0; row < dataModel.getRowCount(); row++) { 426 427 String name = StringUtils.upperCase((String) dataModel.getValueAt(row, 0)); 428 Object valueAt = dataModel.getValueAt(row, -1); 429 if (valueAt != null) { 430 if (theFileReader != null) { 431 theFileReader.write(name + "=" + valueAt + "\n"); 432 } 433 String value = null; 434 if (valueAt instanceof String) { 435 value = (String) valueAt; 436 } else if (valueAt instanceof String[] && ((String[]) valueAt).length > 0) { 437 value = ((String[]) valueAt)[0]; 438 } 439 value = unit.replaceProperties(value); 440 AEWorkspace.getInstance().setDefaultUserConfiguration(".inputValue." + title + "." + name, value); 441 unit.setVariableValue(name, value); 442 } 443 444 } 445 } finally { 446 if (theFileReader != null) { 447 theFileReader.close(); 448 } 449 } 450 } 451 452 @Override 453 public String choiceValue(String name, String description, Object[] aPossibleValues, ILogger log, boolean notifyMe, 454 Processor processor) { 455 return frame.choiceValue(name, description, aPossibleValues, notifyMe); 456 } 457 458 @Override 459 protected String choicePriorityRecipeFolder(String text, String[] possibleValues) { 460 return (String) JOptionPane.showInputDialog(frame, text, "Conflict of the names", 461 JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); 462 } 463 464 @Override 465 public void setTestPath(String name, String path) { 466 super.setTestPath(name, path); 467 frame.getRecipesPanel().refreshTaskPathTable(); 468 } 469 470 @Override 471 public void removeTestPath(String name) { 472 super.removeTestPath(name); 473 frame.getRecipesPanel().refreshTaskPathTable(); 474 } 475 476 @Override 477 protected File findAlternativeConfiguration(String aeDir) { 478 File confFile = null; 479 List<String> confFiles = findAEconfigs(getBaseDir()); 480 481 if (!confFiles.isEmpty()) { 482 if (confFiles.size() == 1) { 483 confFile = new File(confFiles.get(0)); 484 485 } else { 486 File userDir = getBaseDir(); 487 String workingDir = getWorkingDir(); 488 confFiles.replaceAll(f -> StringUtils.replace(f, workingDir, ".")); 489 490 String[] files = confFiles.toArray(new String[confFiles.size()]); 491 Arrays.sort(files); 492 493 String confPropName = userDir.getPath() + CONFIG_SUFIX_PROP_NAME; 494 String defaultValue = AEWorkspace.getInstance().getDefaultUserConfiguration(confPropName, null); 495 496 String aeConfFileName = frame.inputSelectChoice("Projects:", null, files, defaultValue, false, "list"); 497 498 if (aeConfFileName != null) { 499 AEWorkspace.getInstance().setDefaultUserConfiguration(confPropName, aeConfFileName); 500 501 if (aeConfFileName.startsWith(".")) { 502 aeConfFileName = workingDir + aeConfFileName.substring(1); 503 } 504 505 File pomFile = getPomLocation(aeConfFileName, aeDir); 506 507 if (pomFile != null) { 508 executeAnteaterMaven(pomFile, "run"); 509 510 } else { 511 confFile = new File(aeConfFileName); 512 } 513 } 514 } 515 return confFile; 516 } 517 518 if (confFile == null) { 519 confFile = selectConfiguration(); 520 } 521 522 return confFile; 523 } 524 525 protected File selectConfiguration() { 526 File userDir = SystemUtils.getUserDir(); 527 String config = AEWorkspace.getInstance() 528 .getDefaultUserConfiguration(userDir.getPath() + CONFIG_SUFIX_PROP_NAME, null); 529 530 JFileChooser chooser; 531 if (config == null) { 532 chooser = new JFileChooser(); 533 chooser.setCurrentDirectory(userDir); 534 } else { 535 File file = new File(config); 536 chooser = new JFileChooser(file.getParent()); 537 chooser.setSelectedFile(file); 538 } 539 540 chooser.setDialogTitle("Configuration File"); 541 chooser.addChoosableFileFilter(new FileFilter() { 542 @Override 543 public String getDescription() { 544 return ConfigurationView.CONFIGURATION_TITLE; 545 } 546 547 @Override 548 public boolean accept(File f) { 549 return FilenameUtils.isExtension(f.getName(), "xml"); 550 } 551 }); 552 553 int returnVal = chooser.showOpenDialog(JOptionPane.getRootFrame()); 554 switch (returnVal) { 555 case JFileChooser.APPROVE_OPTION: 556 File selectedFile = chooser.getSelectedFile(); 557 AEWorkspace.getInstance().setDefaultUserConfiguration(userDir.getPath() + CONFIG_SUFIX_PROP_NAME, 558 selectedFile.getAbsolutePath()); 559 return selectedFile; 560 } 561 562 return null; 563 } 564 565 public void resetConfiguration() { 566 super.resetConfiguration(); 567 frame.resetConfiguration(); 568 } 569 570 @Override 571 public void initUserPreferencesEncryption(String password) { 572 Node configNode = getConfigNode(); 573 boolean userPreferencesEncryption = Boolean.parseBoolean(configNode.getAttribute("userPreferencesEncryption")); 574 575 if (userPreferencesEncryption) { 576 do { 577 if (password == null) { 578 579 JPanel panel = new JPanel(new BorderLayout(4, 4)); 580 JLabel label = new JLabel( 581 "<html>" + AEWorkspace.MESSAGE_PASSWORD_REQUIRED.replace("\n", "<br/>") + "</html>"); 582 JPasswordField pass = new JPasswordField(20); 583 pass.putClientProperty("JPasswordField.cutCopyAllowed", true); 584 585 panel.add(label, BorderLayout.NORTH); 586 panel.add(pass, BorderLayout.CENTER); 587 588 Frame rootFrame = JOptionPane.getRootFrame(); 589 590 int option = JOptionPane.showOptionDialog(rootFrame, panel, "User Preferences Encryption", 591 JOptionPane.NO_OPTION, JOptionPane.WARNING_MESSAGE, null, new String[] { "OK" }, "OK"); 592 593 if (option == JOptionPane.CLOSED_OPTION) { 594 System.exit(1); 595 } 596 597 password = new String(pass.getPassword()); 598 try { 599 super.initUserPreferencesEncryption(password); 600 601 } catch (Exception e) { 602 603 int showConfirmDialog = JOptionPane.showConfirmDialog(frame, 604 "Incorrect key!\nReset the user preferences data?", "Error", JOptionPane.ERROR_MESSAGE, 605 JOptionPane.YES_NO_OPTION); 606 607 if (showConfirmDialog == JOptionPane.YES_OPTION) { 608 getUserPreferences().clear(); 609 try { 610 File preferencesFile = getPreferencesFile(); 611 FileOutputStream fileInputStream = new FileOutputStream(preferencesFile); 612 613 getUserPreferences().store(fileInputStream, null); 614 fileInputStream.close(); 615 616 } catch (IOException e1) { 617 e1.printStackTrace(); 618 } 619 } 620 if (showConfirmDialog == JOptionPane.CLOSED_OPTION) { 621 System.exit(1); 622 } 623 624 password = null; 625 } 626 } 627 } while (password == null); 628 } 629 } 630}