001package com.ganteater.ae; 002 003import java.awt.Color; 004import java.awt.Toolkit; 005import java.io.BufferedReader; 006import java.io.Console; 007import java.io.File; 008import java.io.FileInputStream; 009import java.io.FileOutputStream; 010import java.io.IOException; 011import java.io.InputStream; 012import java.io.InputStreamReader; 013import java.io.UnsupportedEncodingException; 014import java.lang.reflect.Method; 015import java.lang.reflect.Modifier; 016import java.net.Authenticator; 017import java.net.Inet4Address; 018import java.net.InetAddress; 019import java.net.NetworkInterface; 020import java.net.PasswordAuthentication; 021import java.net.SocketException; 022import java.net.URL; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.Base64; 026import java.util.Enumeration; 027import java.util.HashMap; 028import java.util.HashSet; 029import java.util.Iterator; 030import java.util.LinkedHashMap; 031import java.util.List; 032import java.util.Locale; 033import java.util.Map; 034import java.util.Properties; 035import java.util.Set; 036import java.util.regex.Pattern; 037 038import org.apache.commons.collections.CollectionUtils; 039import org.apache.commons.collections.MapUtils; 040import org.apache.commons.io.IOUtils; 041import org.apache.commons.lang.ArrayUtils; 042import org.apache.commons.lang.BooleanUtils; 043import org.apache.commons.lang.ObjectUtils; 044import org.apache.commons.lang.StringUtils; 045import org.apache.commons.lang.SystemUtils; 046import org.apache.log4j.PropertyConfigurator; 047 048import com.ganteater.ae.processor.BaseProcessor; 049import com.ganteater.ae.processor.MessageHandler; 050import com.ganteater.ae.processor.Processor; 051import com.ganteater.ae.processor.SpecialCommands; 052import com.ganteater.ae.util.AEUtils; 053import com.ganteater.ae.util.Encryptor; 054import com.ganteater.ae.util.xml.easyparser.EasyParser; 055import com.ganteater.ae.util.xml.easyparser.Node; 056 057public class AEWorkspace implements AEManager { 058 059 public static final String CONFIGURATION_TITLE = "Configuration"; 060 061 public static final String ENVIRONMENT_FILE_TITLE = "Environment file"; 062 063 public static final String MESSAGE_PASSWORD_REQUIRED = "This configuration requires encryption for user preferences data.\nEnter the encryption password: "; 064 065 public static final String CONFIG_SUFIX_PROP_NAME = ".config"; 066 067 private static ILogger log = new Logger("AEWorkspace"); 068 069 private static String fUser = System.getProperty("user.name"); 070 071 private static Properties fUserPreferences; 072 073 private long startTime = System.currentTimeMillis(); 074 075 private Node allConfigNode; 076 077 private Map<String, Object> fSystemVariables = new HashMap<>(); 078 079 private Node fConfigNode; 080 081 private Properties fTestsDescList = new Properties(); 082 083 protected boolean defaultMode; 084 085 private String fConfigurationName; 086 087 private Set<RecipeRunner> runners = new HashSet<RecipeRunner>(); 088 089 private File baseDir = SystemUtils.getUserDir(); 090 091 private static AEWorkspace instance; 092 093 private Set<Class<?>> operationsClasses; 094 095 private Map<String, OperationHolder> opsMethods = new HashMap<String, OperationHolder>(); 096 097 private Encryptor cryptoUtilAesGcm; 098 099 private List<Runnable> closeHooks = new ArrayList<>(); 100 101 private RecipesScanner recipesScaner; 102 103 public AEWorkspace() { 104 this(new File(System.getProperty("user.dir"))); 105 } 106 107 public AEWorkspace(File startDir) { 108 instance = this; 109 System.out.println("Start dir: " + startDir); 110 recipesScaner = new RecipesScanner(this, startDir); 111 } 112 113 public String loadConfiguration(String confName, boolean refreshTaskPath) { 114 getHomeConfigurationsDir().mkdirs(); 115 File homeConfiguration = new File(getHomeConfigurationsDir(), ConfigConstants.AE_CONFIG_XML); 116 117 if (homeConfiguration.exists()) { 118 System.out.println("User home configuration file: " + homeConfiguration.getAbsolutePath() + " - found"); 119 } 120 121 Node configNodes; 122 try { 123 configNodes = getConfiguration(); 124 125 String config = selectConfiguration(confName, configNodes, refreshTaskPath); 126 TemplateProcessor tp = new TemplateProcessor(fSystemVariables, fConfigNode, getStartDir()); 127 recipesScaner.loadTaskPath(fConfigNode, tp); 128 129 String password = System.getProperty("configEncriptKey"); 130 initUserPreferencesEncryption(password); 131 return config; 132 133 } catch (TaskCancelingException e) { 134 throw e; 135 136 } catch (Exception e) { 137 throw new ConfigurationException("Configuration loading failed.", e); 138 } 139 140 } 141 142 protected Node getConfiguration() throws IOException { 143 Node configuration = null; 144 File configFile = getConfigurationFile(); 145 146 if (configFile == null || !configFile.exists()) { 147 148 try (InputStream openStream = AEWorkspace.class.getResourceAsStream("/" + ConfigConstants.AE_CONFIG_XML)) { 149 if (openStream != null) { 150 String recipeXml = IOUtils.toString(openStream); 151 try { 152 configuration = new EasyParser().getObject(recipeXml); 153 } catch (Exception e) { 154 throw new IllegalArgumentException(recipeXml, null); 155 } 156 } else { 157 158 File userDir = getBaseDir(); 159 String confPropName = userDir.getPath() + CONFIG_SUFIX_PROP_NAME; 160 String config = AEWorkspace.getInstance().getDefaultUserConfiguration(confPropName, 161 userDir.getAbsolutePath()); 162 config = inputValue(ENVIRONMENT_FILE_TITLE, null, config, null, null); 163 AEWorkspace.getInstance().setDefaultUserConfiguration(confPropName, config); 164 165 configFile = new File(config); 166 } 167 } 168 } 169 170 if (configuration == null) { 171 if (configFile != null && configFile.exists()) { 172 this.baseDir = configFile.getParentFile(); 173 System.out.println(ENVIRONMENT_FILE_TITLE + ": " + configFile.getAbsolutePath()); 174 175 configuration = new EasyParser().getObject(configFile); 176 } else { 177 throw new ConfigurationException(ENVIRONMENT_FILE_TITLE + " (" + ConfigConstants.AE_CONFIG_XML 178 + ") must be defined in " + getHomeWorkingDir() + " or " + getStartDir() + "."); 179 } 180 } 181 182 return configuration; 183 } 184 185 protected File getConfigurationFile() { 186 File confFile; 187 188 String theConfigurationFile = System.getProperty(ConfigConstants.AE_CONFIG_SYS_PROPERTY_NAME); 189 if (theConfigurationFile == null) { 190 confFile = new File(SystemUtils.getUserDir(), ConfigConstants.AE_CONFIG_XML); 191 if (!confFile.exists()) { 192 confFile = new File(getHomeWorkingDir(), ConfigConstants.AE_CONFIG_XML); 193 if (!confFile.exists()) { 194 confFile = new File(getStartDir(), ConfigConstants.AE_CONFIG_XML); 195 } 196 } 197 } else { 198 confFile = new File(theConfigurationFile); 199 } 200 201 if (!confFile.exists()) { 202 URL resource = AEWorkspace.class.getResource("/" + ConfigConstants.AE_CONFIG_XML); 203 if (resource == null) { 204 confFile = findAlternativeConfiguration(); 205 } else { 206 confFile = new File(resource.toString()); 207 } 208 } 209 210 return confFile; 211 } 212 213 protected File findAlternativeConfiguration() { 214 return null; 215 } 216 217 public File getHomeWorkingDir() { 218 return new File(System.getProperty("user.home"), "anteater"); 219 } 220 221 private void configuration() { 222 if (fConfigNode != null) { 223 Node[] theLogNodes = fConfigNode.getNodes("Logger"); 224 if (!ArrayUtils.isEmpty(theLogNodes)) { 225 Node logNode = theLogNodes[theLogNodes.length - 1]; 226 initLogger(logNode); 227 } 228 } 229 230 final String username = (String) fSystemVariables.get("HTTP_USERNAME"); 231 final String password = (String) fSystemVariables.get("HTTP_PASSWORD"); 232 if (username != null && password != null) { 233 Authenticator.setDefault(new Authenticator() { 234 protected PasswordAuthentication getPasswordAuthentication() { 235 return new PasswordAuthentication(username, password.toCharArray()); 236 } 237 }); 238 } 239 } 240 241 protected String choicePriorityRecipeFolder(String text, String[] possibleValues) { 242 String result = inputChoice(text, null, possibleValues, possibleValues[0], null, false); 243 return result; 244 } 245 246 public void runSetupNodes() throws Exception { 247 if (!Boolean.valueOf(System.getProperty("skip.startup"))) { 248 Node[] theNodes = fConfigNode.getNodes(SpecialCommands.STARTUP); 249 TemplateProcessor tp = new TemplateProcessor(fSystemVariables, fConfigNode, getStartDir()); 250 if (theNodes != null) { 251 for (Node node : theNodes) { 252 final String theAttribut = tp.replaceProperties(node.getAttribute("task")); 253 boolean async = false; 254 String asyncValue = tp.replaceProperties(node.getAttribute("async")); 255 if (asyncValue != null) { 256 async = Boolean.valueOf(asyncValue); 257 } 258 if (theAttribut != null) { 259 runTask(theAttribut, async); 260 } else { 261 RecipeRunner taskEditor = createTestRunner(null); 262 taskEditor.runTest(new Node[] { node }); 263 } 264 } 265 } 266 } 267 } 268 269 private void loadCustomProperties() { 270 if (fUserPreferences == null) { 271 fUserPreferences = new Properties(); 272 273 // loading users preferences 274 File preferencesFile = getPreferencesFile(); 275 try { 276 FileInputStream fileInputStream = new FileInputStream(preferencesFile); 277 fUserPreferences.load(fileInputStream); 278 fileInputStream.close(); 279 280 } catch (IOException e) { 281 // System.out.println("User preferences configuration file is not found: " + 282 // preferencesFile); 283 } 284 } 285 } 286 287 protected File getPreferencesFile() { 288 String configurationName = getConfigurationName(); 289 String fileName; 290 if (configurationName != null) { 291 fileName = configurationName + ".properties"; 292 } else { 293 fileName = "configuration/user.properties"; 294 } 295 return new File(getHomeWorkingDir(), fileName); 296 } 297 298 public String getCustomConfPropFileName(String configurationName) { 299 return getHomeConfigurationsDir() + "/" + fUser + "." + configurationName + ".properties"; 300 } 301 302 public File getHomeConfigurationsDir() { 303 File file = new File(getHomeWorkingDir(), "configuration"); 304 return file; 305 } 306 307 public void refreshTaskPath() throws IOException { 308 fTestsDescList.clear(); 309 TemplateProcessor tp = new TemplateProcessor(fSystemVariables, fConfigNode, getStartDir()); 310 getRecipesScaner().loadTaskPath(getConfigNode(), tp); 311 } 312 313 public void progressValue(int i, int length, boolean success) { 314 315 } 316 317 public void progressText(String name) { 318 319 } 320 321 public File getFile(String filePath) { 322 File file = null; 323 if (!StringUtils.startsWithAny(filePath, new String[] { "https:", "http:" })) { 324 if (filePath != null) { 325 if (filePath.startsWith("classpath:") || filePath.startsWith("jar:") || filePath.startsWith("file:") 326 || '/' == filePath.charAt(0) || '\\' == filePath.charAt(0) || filePath.indexOf(":\\") > 0 327 || '/' == filePath.charAt(0)) { 328 file = new File(filePath); 329 } else { 330 file = new File(baseDir, filePath); 331 } 332 } 333 } 334 335 return file; 336 } 337 338 public String inputValue(String aName, String description, String aValue, ILogger log, String type, 339 boolean notifyMe, Processor processor) { 340 System.out.print("Input "); 341 String line = inputValue(aName, description, null, type, null); 342 return line; 343 } 344 345 public String inputValue(String name, String description, String defaultValue, String type, Processor processor) { 346 if (defaultValue == null) { 347 defaultValue = AEWorkspace.getInstance().getDefaultUserConfiguration(".inputValue." + name, defaultValue); 348 } 349 350 boolean password = "password".equalsIgnoreCase(type); 351 352 String showValue = !password ? defaultValue 353 : (defaultValue != null ? StringUtils.repeat("*", defaultValue.length()) : ""); 354 String message = "\"" + StringUtils.defaultIfEmpty(description, name) + "\"" 355 + (StringUtils.isEmpty(defaultValue) ? "" : " [" + showValue + "]") + ": "; 356 System.out.print(message); 357 358 String line = null; 359 if (!Processor.isSilentMode(processor)) { 360 line = readLine(password); 361 if (StringUtils.isEmpty(line)) { 362 line = defaultValue; 363 } else { 364 AEWorkspace.getInstance().setDefaultUserConfiguration(".inputValue." + name, line); 365 } 366 } else { 367 line = defaultValue; 368 System.out.println(defaultValue); 369 } 370 return line; 371 } 372 373 @Override 374 public boolean confirmation(String name, String message, Processor unit, boolean notifyMe) throws Exception { 375 if (StringUtils.isBlank(name)) { 376 System.out.print(message + ", (yes/no): "); 377 } else { 378 System.out.print(name + " [" + message + "], (yes/no): "); 379 } 380 boolean result = false; 381 String line = readLine(false); 382 result = BooleanUtils.toBoolean(line); 383 return result; 384 } 385 386 public void inputDataTable(Processor unit, Node aTableNode, boolean notifyMe) throws IOException { 387 Node[] theVariablesNodes = aTableNode.getNodes("var"); 388 String theLine = null; 389 390 String theFileAttribut = aTableNode.getAttribute("file"); 391 if (unit != null) 392 theFileAttribut = unit.replaceProperties(aTableNode.getAttribute("file")); 393 394 if (theFileAttribut != null) { 395 File file = unit.getFile(theFileAttribut); 396 if (file.exists()) { 397 while ((theLine = readLine(false)) != null) { 398 theLine = theLine.trim(); 399 if (theLine.length() == 0) { 400 continue; 401 } 402 if (theLine.charAt(0) == '#') { 403 continue; 404 } 405 int thePbrk = theLine.indexOf('='); 406 407 String theName = StringUtils.upperCase(theLine.substring(0, thePbrk)); 408 String theValue = theLine.substring(thePbrk + 1); 409 410 Node theNode = new Node("var"); 411 theNode.setAttribute("name", theName); 412 theNode.setAttribute("value", theValue); 413 414 for (Node node : theVariablesNodes) { 415 if (node.getAttribute("name").equalsIgnoreCase(theName)) { 416 node.setAttribute("value", theValue); 417 } 418 } 419 420 } 421 } 422 } else { 423 String title = aTableNode.getAttribute("name"); 424 425 for (Node node : theVariablesNodes) { 426 String name = node.getAttribute("name"); 427 String value = node.getAttribute("value"); 428 429 String defaultValue = value; 430 431 String savedVarName = ".inputValue." + title + "." + StringUtils.upperCase(name); 432 if (defaultValue == null) { 433 defaultValue = AEWorkspace.getInstance().getDefaultUserConfiguration(savedVarName, null); 434 } 435 if (defaultValue == null) { 436 defaultValue = node.getAttribute("default"); 437 } 438 439 if (Processor.isSilentMode(unit)) { 440 value = defaultValue; 441 } else { 442 value = inputValue(name, null, defaultValue, null, unit); 443 AEWorkspace.getInstance().setDefaultUserConfiguration(savedVarName, value); 444 } 445 446 unit.setVariableValue(name, value); 447 } 448 } 449 } 450 451 public void loadConfProperties() throws IOException { 452 453 fSystemVariables.clear(); 454 455 Properties properties = new Properties(); 456 File theConfFile = new File(getCustomConfPropFileName(getConfigurationName())); 457 if (theConfFile.exists()) { 458 FileInputStream theFile = new FileInputStream(theConfFile); 459 properties.load(theFile); 460 theFile.close(); 461 } 462 463 Node[] theVarConfs = fConfigNode.getNodes("Var"); 464 for (int i = 0; i < theVarConfs.length; i++) { 465 Node varNode = theVarConfs[i]; 466 String name = StringUtils.upperCase(varNode.getAttribute("name")); 467 468 if (name != null) { 469 Map<String, String> variableDefinition = parseVariableDefinition(varNode); 470 fSystemVariables.putAll(variableDefinition); 471 472 } else { 473 Processor templateProcessor = new BaseProcessor(fSystemVariables, fConfigNode, getStartDir()); 474 String filePath = templateProcessor.replaceProperties(varNode.getAttribute("file")); 475 File file = getFile(filePath); 476 templateProcessor.loadProperties(file, fSystemVariables, true); 477 } 478 } 479 480 for (String key : properties.stringPropertyNames()) { 481 fSystemVariables.put(key, properties.getProperty(key)); 482 } 483 484 fSystemVariables.put("ENV", System.getenv()); 485 fSystemVariables.put("SYSTEM", System.getProperties()); 486 487 fSystemVariables.put("WORKINGDIR", getStartDir().getAbsolutePath()); 488 fSystemVariables.put("HOME_WORKINGDIR", getHomeWorkingDir().getAbsolutePath()); 489 fSystemVariables.put("START_TIME", Long.toString(startTime)); 490 fSystemVariables.put("USER_NAME", fUser); 491 492 Node[] theTableVarConfs = fConfigNode.getNodes("Table"); 493 Processor unit = new BaseProcessor(this, log, getStartDir()); 494 Processor.setSilentMode(unit, true); 495 496 for (int i = 0; i < theTableVarConfs.length; i++) { 497 inputDataTable(unit, theTableVarConfs[i], false); 498 fSystemVariables.putAll(unit.getVariables()); 499 } 500 501 boolean stopped = unit.isStopped(); 502 if (stopped) { 503 throw new TaskCancelingException(); 504 } 505 506 } 507 508 private Map<String, String> parseVariableDefinition(Node varNode) { 509 Map<String, String> properties = new HashMap<>(); 510 511 String name = StringUtils.upperCase(varNode.getAttribute("name")); 512 513 String attribute = varNode.getAttribute("init"); 514 String type = varNode.getAttribute("type"); 515 516 Object inputValue; 517 String typeValue = StringUtils.defaultIfBlank(type, "string"); 518 switch (typeValue) { 519 case "array": 520 Node[] nodes = varNode.getNodes("item"); 521 inputValue = new ArrayList<String>(); 522 for (Node node : nodes) { 523 String text = node.getInnerText(); 524 @SuppressWarnings("unchecked") 525 List<String> valueList = (List<String>) inputValue; 526 valueList.add(text); 527 } 528 break; 529 case "map": 530 inputValue = getMap(varNode); 531 break; 532 533 default: 534 inputValue = varNode.getAttribute("value"); 535 if (inputValue == null) { 536 inputValue = varNode.getInnerText(); 537 if (StringUtils.isEmpty((String) inputValue)) { 538 inputValue = getMap(varNode); 539 } 540 } 541 break; 542 } 543 544 if ("mandatory".equals(attribute) && properties.get(name) == null) { 545 attribute = "console"; 546 } 547 548 if ("console".equals(attribute)) { 549 inputValue = inputValue(name, null, ObjectUtils.toString(inputValue, null), log, type, false, null); 550 551 switch (StringUtils.defaultIfBlank(type, "string")) { 552 case "array": 553 break; 554 case "map": 555 inputValue = AEUtils.convertStringToMap((String) inputValue); 556 break; 557 558 default: 559 break; 560 } 561 } 562 563 if (inputValue != null) 564 fSystemVariables.put(StringUtils.upperCase(name), inputValue); 565 else 566 fSystemVariables.remove(name); 567 568 String savedValue = (String) properties.get(name); 569 Object value = null; 570 if (savedValue != null) { 571 switch (StringUtils.defaultIfBlank(type, "string")) { 572 case "array": 573 @SuppressWarnings("unchecked") 574 List<String> list = (List<String>) inputValue; 575 list.remove(savedValue); 576 577 List<String> arrayList = new ArrayList<>(); 578 arrayList.add(savedValue); 579 arrayList.addAll(list); 580 value = arrayList; 581 break; 582 case "map": 583 value = AEUtils.convertStringToMap(savedValue); 584 break; 585 586 default: 587 value = savedValue; 588 break; 589 } 590 591 fSystemVariables.put(StringUtils.upperCase(name), value); 592 } 593 594 return properties; 595 } 596 597 private Object getMap(Node varNode) { 598 Object result = null; 599 Node[] nodes = varNode.getNodes("item"); 600 if (nodes.length > 0) { 601 result = new LinkedHashMap<String, String>(); 602 for (Node node : nodes) { 603 @SuppressWarnings("unchecked") 604 Map<String, String> valueMap = (Map<String, String>) result; 605 String value = node.getAttribute("value"); 606 if (value == null) { 607 value = node.getInnerText(); 608 } 609 valueMap.put(node.getAttribute("key"), value); 610 } 611 } 612 return result; 613 } 614 615 public String selectConfiguration(String confName, Node configNodes, boolean refreshTaskPath) throws IOException { 616 617 allConfigNode = configNodes; 618 619 String configurationName = System.getProperty(ConfigConstants.CONFIG_NAME_SYS_PRPERTY_NAME); 620 if (confName != null) { 621 configurationName = confName; 622 } 623 624 fConfigNode = getCurrentConfig(allConfigNode, configurationName); 625 626 if (fConfigNode == null) { 627 System.out.println("Configuration '" + configurationName + "' not found in " + ConfigConstants.AE_CONFIG_XML 628 + " file."); 629 return configurationName; 630 631 } else { 632 setConfigurationName(fConfigNode.getAttribute("name")); 633 634 if (configurationName == null) { 635 configurationName = fConfigNode.getAttribute("name"); 636 if (configurationName == null) 637 configurationName = fConfigNode.getAttribute("description"); 638 } 639 640 loadConfProperties(); 641 642 Node[] theLocations = fConfigNode.getNodes("Locale"); 643 if (theLocations != null && theLocations.length > 0) { 644 Node theLocation = theLocations[0]; 645 String theISO3Language = theLocation.getAttribute("ISO3Language"); 646 String theDisplayName = theLocation.getAttribute("DisplayName"); 647 Locale[] availableLocales = Locale.getAvailableLocales(); 648 649 boolean theFound = false; 650 for (int l = 0; l < availableLocales.length; l++) { 651 if (availableLocales[l].getISO3Language().equals(theISO3Language)) { 652 Locale.setDefault(availableLocales[l]); 653 System.out.println("Set location ISO3Language: " + theISO3Language); 654 theFound = true; 655 break; 656 } 657 if (availableLocales[l].getDisplayName().equals(theDisplayName)) { 658 Locale.setDefault(availableLocales[l]); 659 System.out.println("Set location DisplayName: " + theDisplayName); 660 theFound = true; 661 break; 662 } 663 } 664 665 if (theFound == false) { 666 for (int j = 0; j < availableLocales.length; j++) { 667 System.out.println(j + ". " + availableLocales[j].getDisplayName()); 668 } 669 } 670 } 671 672 configuration(); 673 674 return fConfigurationName; 675 } 676 677 } 678 679 public void setDefaultUserConfiguration(String propertyName, String value) { 680 681 propertyName = getFullConfPropertyName(propertyName); 682 683 if (value != null) { 684 if (cryptoUtilAesGcm != null) { 685 value = cryptoUtilAesGcm.encrypt(value); 686 } 687 688 fUserPreferences.setProperty(propertyName, value); 689 690 try { 691 File preferencesFile = getPreferencesFile(); 692 FileOutputStream fileInputStream = new FileOutputStream(preferencesFile); 693 694 fUserPreferences.store(fileInputStream, null); 695 fileInputStream.close(); 696 697 } catch (IOException e) { 698 System.out.println("Write default user setting is failed. Error: " + e.getMessage()); 699 } 700 } else { 701 if (fUserPreferences.get(propertyName) != null) { 702 fUserPreferences.remove(propertyName); 703 } 704 } 705 706 } 707 708 private String getFullConfPropertyName(String propertyName) { 709 return propertyName; 710 } 711 712 public String getDefaultUserConfiguration(String aName, String theDefaultConfiguration) { 713 aName = getFullConfPropertyName(aName); 714 715 loadCustomProperties(); 716 String theProperty = fUserPreferences.getProperty(aName); 717 718 if (theProperty != null) { 719 if (cryptoUtilAesGcm != null) { 720 theDefaultConfiguration = cryptoUtilAesGcm.decrypt(theProperty); 721 } else { 722 theDefaultConfiguration = theProperty; 723 } 724 } 725 726 return theDefaultConfiguration; 727 } 728 729 public Node getCurrentConfig(Node configs, String aNameConfiguration) { 730 Node[] configNodes = configs.getNodes(CONFIGURATION_TITLE); 731 732 ArrayList<String> possibleValues = new ArrayList<>(); 733 734 for (int i = 0; i < configNodes.length; i++) { 735 Node node = configNodes[i]; 736 String name = node.getAttribute("name"); 737 String ip = node.getAttribute("ip"); 738 if (ip == null || isEnableIp(ip)) { 739 740 if (possibleValues.contains(name)) { 741 throw new IllegalArgumentException("Duplication name configuration: " + name); 742 } 743 744 if (!name.startsWith("#")) { 745 possibleValues.add(name); 746 } 747 } 748 } 749 750 if (CollectionUtils.isNotEmpty(possibleValues)) { 751 String configName = possibleValues.get(0); 752 if (aNameConfiguration != null) { 753 configName = aNameConfiguration; 754 } 755 756 if (possibleValues.size() > 1 && aNameConfiguration == null) { 757 configName = selectConfiguration(possibleValues.toArray(new String[possibleValues.size()])); 758 } 759 760 Node theConfigNode = prepareConfigurationNode(configs, configName); 761 return theConfigNode; 762 } 763 764 return null; 765 } 766 767 private boolean isEnableIp(String ip) { 768 Enumeration<NetworkInterface> networkInterfaces; 769 Pattern compile = Pattern.compile(ip); 770 try { 771 networkInterfaces = NetworkInterface.getNetworkInterfaces(); 772 while (networkInterfaces.hasMoreElements()) { 773 NetworkInterface nextElement = networkInterfaces.nextElement(); 774 Enumeration<InetAddress> inetAddresses = nextElement.getInetAddresses(); 775 while (inetAddresses.hasMoreElements()) { 776 InetAddress nextElement2 = inetAddresses.nextElement(); 777 if (nextElement2 instanceof Inet4Address) { 778 Inet4Address address = (Inet4Address) nextElement2; 779 String hostAddress = address.getHostAddress(); 780 if (compile.matcher(hostAddress).matches()) { 781 return true; 782 } 783 } 784 } 785 } 786 } catch (SocketException e) { 787 e.printStackTrace(); 788 } 789 return false; 790 } 791 792 private Node prepareConfigurationNode(Node configs, String configName) { 793 794 Node configNode = configs.findNode(CONFIGURATION_TITLE, "name", configName); 795 Node baseNode = null; 796 797 if (configNode != null) { 798 String baseConfig = configNode.getAttribute("base"); 799 800 if (baseConfig != null) { 801 baseNode = prepareConfigurationNode(configs, baseConfig); 802 803 if (baseNode != null) { 804 baseNode = (Node) baseNode.clone(); 805 baseNode.setAttributes(configNode.getAttributes()); 806 807 for (Iterator<Node> theIterator = configNode.iterator(); theIterator.hasNext();) { 808 Node theNode = theIterator.next(); 809 810 String theTagName = theNode.getTag(); 811 Node[] theNodeArray = baseNode.getNodes(theTagName); 812 813 if (theNodeArray.length > 1) { 814 String theName = theNode.getAttribute("name"); 815 816 Node theBaseTag = baseNode.findNode(theTagName, "name", theName); 817 818 if (theBaseTag != null) { 819 System.out.println( 820 "Change node: " + theTagName + " name=" + theName + " Value: " + theNode); 821 int indexOf = baseNode.indexOf(theBaseTag); 822 Node object = baseNode.get(indexOf); 823 if (object.getTag() == theTagName) 824 baseNode.remove(indexOf); 825 } 826 } 827 baseNode.add(theNode); 828 } 829 830 } else { 831 System.out.println("Base configuration is not found. Name: " + baseConfig); 832 baseNode = configNode; 833 } 834 } else 835 baseNode = configNode; 836 837 } else 838 baseNode = configNode; 839 840 return baseNode; 841 } 842 843 public File getStartDir() { 844 return getRecipesScaner().getStartDir(); 845 } 846 847 public String inputChoice(String name, String description, String[] values, String defaultValue, 848 Processor taskProcessor, boolean notifyMe) { 849 if (defaultValue == null && values.length > 0) { 850 String value = getDefaultUserConfiguration(".choice." + name, null); 851 if (value != null) { 852 defaultValue = value; 853 } 854 } 855 856 System.out.println("List of values for [" + name + "]:"); 857 if (!Processor.isSilentMode(taskProcessor)) { 858 int i = 1; 859 for (String val : values) { 860 println(String.format("%3s: ", i++) + val, Color.green); 861 } 862 defaultValue = inputInteger(name, values, defaultValue); 863 } else { 864 System.out.println("Saved selection applied: " + defaultValue); 865 } 866 867 return defaultValue; 868 } 869 870 public String[] inputMultiChoice(String name, String[] values, String defaultValue, Processor taskProcessor) { 871 String[] result = null; 872 873 if (defaultValue == null && values.length > 0) { 874 String value = getDefaultUserConfiguration("MultiTaskRunDialog:" + name, null); 875 if (value != null) { 876 defaultValue = value; 877 } 878 } 879 boolean silent = taskProcessor != null && Processor.isSilentMode(taskProcessor); 880 881 boolean isDone = false; 882 do { 883 try { 884 System.out.println("List of values for [" + name + "]:"); 885 if (!silent) { 886 int i = 1; 887 888 for (String val : values) { 889 println(String.format("%3s: ", i++) + val, Color.green); 890 } 891 String preset = null; 892 System.out.print("Please select "); 893 defaultValue = inputValue(name, preset, defaultValue, null, taskProcessor); 894 result = getValue(values, defaultValue); 895 isDone = true; 896 897 AEWorkspace.getInstance().setDefaultUserConfiguration("MultiTaskRunDialog:" + name, defaultValue); 898 } else { 899 if (defaultValue != null) { 900 result = getValue(values, defaultValue); 901 System.out.println("Saved selection applied: [" + StringUtils.join(result, ",") + "]"); 902 } 903 } 904 } catch (ArrayIndexOutOfBoundsException e) { 905 System.out.println(defaultValue + " - invalid value."); 906 isDone = false; 907 } 908 } while (!isDone && !silent); 909 910 return result; 911 } 912 913 private void println(String text, Color color) { 914 System.out.println(text); 915 } 916 917 protected String[] getValue(String[] values, String defaultValue) { 918 String[] result = null; 919 if (defaultValue != null) { 920 String[] split = StringUtils.split(defaultValue, ";"); 921 922 try { 923 result = new String[split.length]; 924 for (int j = 0; j < split.length; j++) { 925 result[j] = values[Integer.parseInt(split[j]) - 1]; 926 } 927 } catch (NumberFormatException e) { 928 result = split; 929 } 930 } 931 return result; 932 } 933 934 public String inputInteger(String name, String[] values, String defaultValue) { 935 936 boolean isDone = false; 937 do { 938 System.out.print( 939 "Please select" + (StringUtils.isEmpty(defaultValue) ? "" : " [" + defaultValue + "]") + ": "); 940 941 int inputValue; 942 String readLine = null; 943 try { 944 readLine = readLine(false); 945 if (!StringUtils.isEmpty(readLine)) { 946 inputValue = Integer.parseInt(readLine) - 1; 947 defaultValue = values[inputValue]; 948 setDefaultUserConfiguration(".choice." + name, defaultValue); 949 } 950 951 isDone = true; 952 953 } catch (Exception e) { 954 System.out.println(readLine + " - invalid value."); 955 defaultValue = null; 956 } 957 } while (!isDone); 958 959 return defaultValue; 960 } 961 962 public String inputFile(String name, String description, File aDefaultFile, ILogger log, Processor taskProcessor) { 963 String theResult = getDefaultUserConfiguration(".inputFile", 964 aDefaultFile == null ? null : aDefaultFile.getAbsolutePath()); 965 return theResult; 966 } 967 968 protected String selectConfiguration(String[] configNames) { 969 String configName = choiceValue(CONFIGURATION_TITLE, null, configNames, null, true, null); 970 return configName; 971 } 972 973 public String getTestPath(String name) { 974 String recipePath = null; 975 if (name != null) { 976 recipePath = fTestsDescList.getProperty(name); 977 } 978 return recipePath; 979 } 980 981 public RecipeRunner runTask(String name, boolean async) { 982 RecipeRunner runner = null; 983 if (name != null) { 984 runner = createTestRunner(name); 985 String testPath = getTestPath(name); 986 if (testPath != null) { 987 if (async) { 988 TaskThread theThread = new TaskThread(runner, testPath); 989 theThread.start(); 990 991 } else { 992 try { 993 runner.makeRecipe(testPath); 994 } catch (CommandException e) { 995 log.error("Task failed.", e); 996 } 997 } 998 } 999 } 1000 1001 return runner; 1002 } 1003 1004 protected RecipeRunner createTestRunner(String name) { 1005 RecipeRunner runner = new RecipeRunner(this); 1006 Processor processor = new BaseProcessor(this, log, getStartDir()); 1007 processor.setTestListener(runner); 1008 runner.setProcessor(processor); 1009 runner.setLog(log); 1010 return runner; 1011 } 1012 1013 public void removeTestPath(String name) { 1014 if (fTestsDescList.get(name) != null) 1015 fTestsDescList.remove(name); 1016 } 1017 1018 public void setTestPath(String name, String path) { 1019 fTestsDescList.put(name, path); 1020 } 1021 1022 public String getWorkingDir() { 1023 return getStartDir().getAbsolutePath(); 1024 } 1025 1026 public MultiTaskRunDialog tasksChoice(MultiTaskRunDialog dialog, String[] list, boolean exceptionIgnoreFlag, 1027 Object setup, Processor taskProcessor, boolean visible) { 1028 1029 if (setup == null) { 1030 boolean consoleDefaultInput = isConsoleDefaultInput(dialog.getName(), null); 1031 setup = inputMultiChoice(dialog.getName(), list, null, taskProcessor); 1032 dialog.select((String[]) setup, consoleDefaultInput); 1033 } 1034 1035 dialog.setExceptionIgnore(exceptionIgnoreFlag); 1036 dialog.setVisible(visible); 1037 dialog.showDialog(dialog.getName(), list, taskProcessor.getListener().isNotifyMe()); 1038 1039 return dialog; 1040 } 1041 1042 public Map<String, Object> getSystemVariables() { 1043 return fSystemVariables; 1044 } 1045 1046 public void setConsoleDefaultInput(boolean defaultMode) { 1047 this.defaultMode = defaultMode; 1048 } 1049 1050 public boolean isConsoleDefaultInput(String varName, String description) { 1051 return defaultMode; 1052 } 1053 1054 public Node getConfigNode() { 1055 return fConfigNode; 1056 } 1057 1058 public Node getAllConfigNode() { 1059 return allConfigNode; 1060 } 1061 1062 public Properties getTasksMap() { 1063 return fTestsDescList; 1064 } 1065 1066 public Properties getTestsDescList() { 1067 return fTestsDescList; 1068 } 1069 1070 public Object[] getPublicTestsList() { 1071 Enumeration<Object> keys = fTestsDescList.keys(); 1072 List<String> result = new ArrayList<String>(); 1073 while (keys.hasMoreElements()) { 1074 String key = (String) keys.nextElement(); 1075 if (!key.startsWith("#")) { 1076 result.add(key); 1077 } 1078 } 1079 String[] a = result.toArray(new String[result.size()]); 1080 Arrays.sort(a); 1081 return a; 1082 } 1083 1084 public void startTaskNotify(RecipeRunner task) { 1085 1086 } 1087 1088 public String choiceValue(String name, String description, Object[] possibleValues, ILogger log, boolean notifyMe, 1089 Processor processor) { 1090 String result = null; 1091 description = StringUtils.defaultString(description, name); 1092 1093 if (possibleValues != null && possibleValues.length > 0) { 1094 result = getDefaultUserConfiguration(".choiceValue." + name, null); 1095 1096 String[] values = Arrays.copyOf(possibleValues, possibleValues.length, String[].class); 1097 result = inputChoice(description, null, values, result, processor, notifyMe); 1098 1099 AEWorkspace.getInstance().setDefaultUserConfiguration(".choiceValue." + name, result); 1100 } else { 1101 result = (String) possibleValues[0]; 1102 } 1103 1104 return result; 1105 } 1106 1107 public static AEWorkspace getInstance() { 1108 return instance; 1109 } 1110 1111 public void resetConfiguration() { 1112 fConfigNode = null; 1113 } 1114 1115 public void resetConfigurationName() { 1116 setConfigurationName(null); 1117 } 1118 1119 public String getConfigurationName() { 1120 return this.fConfigurationName; 1121 } 1122 1123 public void loadConfiguration(boolean refreshTaskMap) { 1124 loadConfiguration(null, refreshTaskMap); 1125 } 1126 1127 public void addRunner(RecipeRunner testRunner) { 1128 runners.add(testRunner); 1129 } 1130 1131 public void removeRunner(RecipeRunner testRunner) { 1132 runners.remove(testRunner); 1133 } 1134 1135 public void stopAllRunners() { 1136 RecipeRunner[] array = runners.toArray(new RecipeRunner[runners.size()]); 1137 for (RecipeRunner runner : array) { 1138 runner.stopTest(); 1139 } 1140 } 1141 1142 public void setBaseDir(File baseDir) { 1143 this.baseDir = baseDir; 1144 } 1145 1146 public File getBaseDir() { 1147 return this.baseDir; 1148 } 1149 1150 public Set<Class<?>> getOperationsClasses() { 1151 return operationsClasses; 1152 } 1153 1154 public void setOperationsClasses(@SuppressWarnings("rawtypes") Set<Class> operationsClasses) { 1155 if (operationsClasses != null) { 1156 opsMethods = new HashMap<String, OperationHolder>(); 1157 try { 1158 Method[] methods = Object.class.getMethods(); 1159 String exclude[] = new String[methods.length]; 1160 for (int i = 0; i < exclude.length; i++) { 1161 exclude[i] = methods[i].getName(); 1162 } 1163 Arrays.sort(exclude); 1164 1165 for (Class<?> operationClass : operationsClasses) { 1166 methods = operationClass.getMethods(); 1167 for (Method method : methods) { 1168 if (Arrays.binarySearch(exclude, method.getName()) < 0 1169 && method.getModifiers() == Modifier.PUBLIC) { 1170 String shortClassName = operationClass.getName(); 1171 opsMethods.put(shortClassName + "." + method.getName(), 1172 new OperationHolder(operationClass, method)); 1173 } 1174 } 1175 } 1176 } catch (Exception e) { 1177 throw new IllegalArgumentException(e); 1178 } 1179 } 1180 } 1181 1182 public OperationHolder getOperationsMethod(String name) { 1183 return opsMethods.get(name); 1184 } 1185 1186 public Map<String, OperationHolder> getOperationsMethods() { 1187 return opsMethods; 1188 } 1189 1190 public Set<RecipeRunner> getRunners() { 1191 return runners; 1192 } 1193 1194 @Override 1195 public void finished(String aTestFile) { 1196 } 1197 1198 public static Properties getUserPreferences() { 1199 return fUserPreferences; 1200 } 1201 1202 public String[] getTestsList() { 1203 String[] array = fTestsDescList.keySet().toArray(new String[fTestsDescList.size()]); 1204 Arrays.sort(array); 1205 return array; 1206 } 1207 1208 @Override 1209 public MessageHandler message(Processor taskProcessor, String description, String message, boolean notifyMe) { 1210 return new MessageHandler(); 1211 } 1212 1213 public void setConfigurationName(String fConfigurationName) { 1214 this.fConfigurationName = fConfigurationName; 1215 fUserPreferences = null; 1216 loadCustomProperties(); 1217 } 1218 1219 public void initUserPreferencesEncryption(String password) { 1220 Node configNode = getConfigNode(); 1221 boolean userPreferencesEncryption = Boolean.parseBoolean(configNode.getAttribute("userPreferencesEncryption")); 1222 1223 if (userPreferencesEncryption) { 1224 if (password == null) { 1225 System.out.print(MESSAGE_PASSWORD_REQUIRED); 1226 1227 Console console = System.console(); 1228 if (console == null) { 1229 password = readLine(true); 1230 } else { 1231 char[] pwd = console.readPassword(); 1232 password = new String(pwd); 1233 } 1234 } 1235 1236 byte[] pwdBytes; 1237 try { 1238 pwdBytes = new String(password).getBytes("UTF-8"); 1239 } catch (UnsupportedEncodingException e) { 1240 throw new IllegalArgumentException(e); 1241 } 1242 password = Base64.getEncoder().encodeToString(pwdBytes); 1243 cryptoUtilAesGcm = new Encryptor(password); 1244 Enumeration<Object> keys = fUserPreferences.keys(); 1245 while (keys.hasMoreElements()) { 1246 String name = (String) keys.nextElement(); 1247 getDefaultUserConfiguration(name, name); 1248 break; 1249 } 1250 } 1251 } 1252 1253 public void close() { 1254 closeHooks.forEach(e -> e.run()); 1255 } 1256 1257 public void addCloseHook(Runnable shutdownHook) { 1258 closeHooks.add(shutdownHook); 1259 } 1260 1261 public RecipesScanner getRecipesScaner() { 1262 return recipesScaner; 1263 } 1264 1265 public void setStartDir(File startDir) { 1266 recipesScaner.setStartDir(startDir); 1267 } 1268 1269 private String readLine(boolean password) { 1270 try { 1271 Console console = System.console(); 1272 String line; 1273 Toolkit.getDefaultToolkit().beep(); 1274 if (console != null) { 1275 if (password) { 1276 line = new String(console.readPassword()); 1277 } else { 1278 line = console.readLine(); 1279 } 1280 } else { 1281 InputStreamReader inputStreamReader = new InputStreamReader(System.in); 1282 BufferedReader reader = new BufferedReader(inputStreamReader); 1283 try { 1284 line = reader.readLine(); 1285 } catch (IOException e) { 1286 line = null; 1287 } 1288 } 1289 1290 return line; 1291 1292 } catch (RuntimeException e) { 1293 throw new TaskCancelingException(); 1294 } 1295 } 1296 1297 protected void initLogger(Node configNode) { 1298 Properties logProperties = fillLogProperties(configNode); 1299 PropertyConfigurator.configure(logProperties); 1300 log = new Logger("AEWorkspace"); 1301 } 1302 1303 protected Properties fillLogProperties(Node configNode) { 1304 Properties logProperties = new Properties(); 1305 if (configNode != null) { 1306 logProperties = MapUtils.toProperties(configNode.getAttributes()); 1307 } 1308 Node[] theLoggerNodes = fConfigNode.getNodes("Logger"); 1309 Node node = theLoggerNodes[0]; 1310 boolean consoleOn = false; 1311 if (theLoggerNodes != null && theLoggerNodes.length > 0) { 1312 node = theLoggerNodes[0]; 1313 logProperties.putAll(node.getAttributes()); 1314 } 1315 1316 TemplateProcessor templateProcessor = new TemplateProcessor(fSystemVariables, fConfigNode, getStartDir()); 1317 1318 if (logProperties.getProperty("rootLogger") != null) { 1319 String rootLogger = templateProcessor.replaceProperties(logProperties.getProperty("rootLogger")); 1320 1321 consoleOn = rootLogger.indexOf("CONSOLE") >= 0; 1322 1323 logProperties.setProperty("log4j.rootLogger", rootLogger); 1324 logProperties.remove("rootLogger"); 1325 } 1326 if (logProperties.getProperty("File") != null) { 1327 String lofFileName = templateProcessor.replaceProperties(logProperties.getProperty("File")); 1328 File file = new File(lofFileName); 1329 if (file != null && file.getParentFile() != null && file.getParentFile().exists() == false) 1330 file.getParentFile().mkdirs(); 1331 logProperties.setProperty("log4j.appender.LOGFILE.File", lofFileName); 1332 } 1333 if (logProperties.getProperty("Threshold") != null) { 1334 logProperties.setProperty("log4j.appender.LOGFILE.Threshold", 1335 templateProcessor.replaceProperties(logProperties.getProperty("Threshold"))); 1336 if (consoleOn) 1337 logProperties.setProperty("log4j.appender.CONSOLE.Threshold", 1338 templateProcessor.replaceProperties(logProperties.getProperty("Threshold"))); 1339 logProperties.remove("Threshold"); 1340 } 1341 if (logProperties.getProperty("ConversionPattern") != null) { 1342 logProperties.setProperty("log4j.appender.LOGFILE.layout.ConversionPattern", 1343 templateProcessor.replaceProperties(logProperties.getProperty("ConversionPattern"))); 1344 if (consoleOn) 1345 logProperties.setProperty("log4j.appender.CONSOLE.layout.ConversionPattern", 1346 templateProcessor.replaceProperties(logProperties.getProperty("ConversionPattern"))); 1347 logProperties.remove("ConversionPattern"); 1348 } else { 1349 logProperties.setProperty("log4j.appender.LOGFILE.layout.ConversionPattern", 1350 "%d{dd.MM.yyyy HH:mm:ss} %-5p %m %n"); 1351 if (consoleOn) 1352 logProperties.setProperty("log4j.appender.CONSOLE.layout.ConversionPattern", 1353 "%d{dd.MM.yyyy HH:mm:ss} %-5p %m %n"); 1354 } 1355 logProperties.setProperty("log4j.appender.logfile.DatePattern", "'.'yyyy-MM-dd"); 1356 logProperties.setProperty("log4j.appender.LOGFILE", "org.apache.log4j.DailyRollingFileAppender"); 1357 if (consoleOn) 1358 logProperties.setProperty("log4j.appender.CONSOLE", "org.apache.log4j.ConsoleAppender"); 1359 logProperties.setProperty("log4j.appender.LOGFILE.layout", "org.apache.log4j.PatternLayout"); 1360 if (consoleOn) 1361 logProperties.setProperty("log4j.appender.CONSOLE.layout", "org.apache.log4j.PatternLayout"); 1362 1363 logProperties.setProperty("log4j.logger.java.desktop", "ERROR"); 1364 return logProperties; 1365 } 1366 1367}