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