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