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