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.collections.MapUtils;
044import org.apache.commons.io.IOUtils;
045import org.apache.commons.lang.ArrayUtils;
046import org.apache.commons.lang.BooleanUtils;
047import org.apache.commons.lang.ObjectUtils;
048import org.apache.commons.lang.StringUtils;
049import org.apache.commons.lang.SystemUtils;
050import org.apache.log4j.PropertyConfigurator;
051import org.apache.maven.shared.invoker.DefaultInvocationRequest;
052import org.apache.maven.shared.invoker.DefaultInvoker;
053import org.apache.maven.shared.invoker.InvocationRequest;
054import org.apache.maven.shared.invoker.InvocationResult;
055import org.apache.maven.shared.invoker.Invoker;
056import org.apache.maven.shared.invoker.MavenInvocationException;
057
058import com.ganteater.ae.processor.BaseProcessor;
059import com.ganteater.ae.processor.MessageHandler;
060import com.ganteater.ae.processor.Processor;
061import com.ganteater.ae.processor.SpecialCommands;
062import com.ganteater.ae.util.AEUtils;
063import com.ganteater.ae.util.Encryptor;
064import com.ganteater.ae.util.xml.easyparser.EasyParser;
065import com.ganteater.ae.util.xml.easyparser.Node;
066import com.ganteater.ae.util.xml.easyparser.ParserException;
067
068public class AEWorkspace implements AEManager {
069
070        public static final String CONFIGURATION_TAG_NAME = "Configuration";
071
072        public static final String ENVIRONMENT_FILE_TITLE = "Environment file";
073
074        public static final String MESSAGE_PASSWORD_REQUIRED = "This configuration requires encryption for user preferences data.\nEnter the encryption password: ";
075
076        public static final String CONFIG_SUFIX_PROP_NAME = ".config";
077
078        private static ILogger log = new Logger("AEWorkspace");
079
080        private static String fUser = System.getProperty("user.name");
081
082        private static Properties fUserPreferences;
083
084        private long startTime = System.currentTimeMillis();
085
086        private Node allConfigNode;
087
088        private Map<String, Object> fSystemVariables = new HashMap<>();
089
090        private Node fConfigNode;
091
092        private Properties fTestsDescList = new Properties();
093
094        protected boolean defaultMode;
095
096        private String fConfigurationName;
097
098        private Set<RecipeRunner> runners = new HashSet<RecipeRunner>();
099
100        private File baseDir = SystemUtils.getUserDir();
101
102        private static AEWorkspace instance;
103
104        private Set<Class<?>> operationsClasses;
105
106        private Map<String, OperationHolder> opsMethods = new HashMap<String, OperationHolder>();
107
108        private Encryptor cryptoUtilAesGcm;
109
110        private List<Runnable> closeHooks = new ArrayList<>();
111
112        private RecipesScanner recipesScaner;
113
114        public AEWorkspace() {
115                this(new File(System.getProperty("user.dir")));
116        }
117
118        public AEWorkspace(File startDir) {
119                instance = this;
120                System.out.println("Start dir: " + startDir);
121                recipesScaner = new RecipesScanner(this, startDir);
122        }
123
124        public String loadConfiguration(String confName, boolean refreshTaskPath) {
125                getHomeConfigurationsDir().mkdirs();
126                File homeConfiguration = new File(getHomeConfigurationsDir(), ConfigConstants.AE_CONFIG_XML);
127
128                if (homeConfiguration.exists()) {
129                        System.out.println("User home configuration file: " + homeConfiguration.getAbsolutePath() + " - found");
130                }
131
132                Node configNodes;
133                try {
134                        configNodes = getConfiguration();
135
136                        confName = selectConfiguration(confName, configNodes, refreshTaskPath);
137                        TemplateProcessor tp = new TemplateProcessor(fSystemVariables, fConfigNode, getStartDir());
138                        recipesScaner.loadTaskPath(fConfigNode, tp);
139
140                        String password = System.getProperty("configEncriptKey");
141                        initUserPreferencesEncryption(password);
142                        return confName;
143
144                } catch (TaskCancelingException | ConfigurationException e) {
145                        throw e;
146                } catch (IOException e) {
147                        String message = "Recipes path not found.\nPath: \"" + e.getMessage() + "\"\nEnvironment: \""
148                                        + getConfigurationFile() + "\"\nConfiguration: " + confName;
149                        throw new ConfigurationException("Invalid configuration.", new IOException(message));
150                }
151
152        }
153
154        protected Node getConfiguration() throws IOException {
155
156                File configFile = getConfigurationFile();
157
158                String errorMessage = AEWorkspace.ENVIRONMENT_FILE_TITLE + " (" + ConfigConstants.AE_CONFIG_XML
159                                + ") must be defined in \"" + getHomeWorkingDir() + "\" or \"" + getStartDir()
160                                + "\".\n Please ensure that the file is available in one of the locations above. "
161                                + "If the file is missing or incorrectly defined, refer to the configuration documentation for guidance: "
162                                + "\"https://ganteater.com/configuration.html\"";
163
164                Node object;
165                if (configFile != null) {
166                        setBaseDir(configFile.getParentFile());
167
168                        if (configFile.exists() || configFile.toString().contains(".jar!")) {
169                                try (InputStream inputStream = AEUtils.getInputStream(configFile.toString(), getBaseDir())) {
170                                        object = new EasyParser().getObject(inputStream);
171                                } catch (ParserException e) {
172                                        throw new ConfigurationException(errorMessage, e);
173                                }
174                        } else {
175                                try {
176                                        URL resource = new URL(configFile.toString());
177                                        try (InputStream openStream = resource.openStream()) {
178                                                String recipeXml = IOUtils.toString(openStream);
179                                                object = new EasyParser().getObject(recipeXml);
180                                        }
181                                } catch (Exception e) {
182                                        throw new ConfigurationException(errorMessage, e);
183                                }
184                        }
185                } else {
186                        object = new EasyParser().getObject("<Environment><Configuration name=\"\"></Configuration></Environment>");
187                }
188
189                return object;
190        }
191
192        protected File getConfigurationFile() {
193                File confFile;
194                loadCustomProperties();
195
196                String theConfigurationFile = System.getProperty(ConfigConstants.AE_CONFIG_SYS_PROPERTY_NAME);
197                if (theConfigurationFile == null) {
198                        confFile = new File(SystemUtils.getUserDir(), ConfigConstants.AE_CONFIG_XML);
199                        if (!confFile.exists()) {
200                                confFile = new File(getHomeWorkingDir(), ConfigConstants.AE_CONFIG_XML);
201                                if (!confFile.exists()) {
202                                        confFile = new File(getStartDir(), ConfigConstants.AE_CONFIG_XML);
203                                }
204                        }
205                } else {
206                        confFile = new File(theConfigurationFile);
207                }
208
209                if (!confFile.exists()) {
210                        String name = "/" + ConfigConstants.AE_CONFIG_XML;
211                        URL resource = AEWorkspace.class.getResource(name);
212                        if (resource != null) {
213                                confFile = new File(resource.toString());
214                        } else {
215                                confFile = findAlternativeConfiguration("");
216                        }
217                }
218
219                return confFile;
220        }
221
222        protected File findAlternativeConfiguration(String aeDir) {
223                File confFile = null;
224                File userDir = getBaseDir();
225                List<String> confFiles = findAEconfigs(userDir);
226
227                if (!confFiles.isEmpty()) {
228
229                        String confPropName = userDir.getPath() + CONFIG_SUFIX_PROP_NAME;
230                        String defaultValue = AEWorkspace.getInstance().getDefaultUserConfiguration(confPropName, null);
231
232                        String aeConfFileName = inputChoice("Projects", null, confFiles.toArray(new String[confFiles.size()]),
233                                        defaultValue, null, false);
234
235                        AEWorkspace.getInstance().setDefaultUserConfiguration(confPropName, aeConfFileName);
236
237                        File pomFile = getPomLocation(aeConfFileName, aeDir);
238
239                        if (pomFile != null) {
240                                System.err.println("[ERROR] For the configuration: " + aeConfFileName + " found pom.xml file: "
241                                                + pomFile + ". This Anteter version does not support ae:do, please run it manually.");
242                                System.exit(1);
243
244                        } else {
245                                confFile = new File(aeConfFileName);
246                        }
247                        return confFile;
248                }
249
250                if (confFile == null) {
251                        confFile = selectConfiguration();
252                }
253
254                return confFile;
255        }
256
257        protected File selectConfiguration() {
258                File userDir = getBaseDir();
259                String confPropName = userDir.getPath() + CONFIG_SUFIX_PROP_NAME;
260                String config = AEWorkspace.getInstance().getDefaultUserConfiguration(confPropName, "");
261
262                config = inputValue(ENVIRONMENT_FILE_TITLE, null, config, null, null);
263
264                AEWorkspace.getInstance().setDefaultUserConfiguration(confPropName, config);
265                return new File(config);
266        }
267
268        public File getHomeWorkingDir() {
269                return new File(System.getProperty("user.home"), "anteater");
270        }
271
272        private void configuration() {
273                if (fConfigNode != null) {
274                        Node[] theLogNodes = fConfigNode.getNodes("Logger");
275                        if (ArrayUtils.isEmpty(theLogNodes)) {
276                                theLogNodes = new Node[] { new EasyParser().getObject(
277                                                "<Logger rootLogger=\"DEBUG,LOGFILE,CONSOLE\" Threshold=\"$var{system::log_level,DEBUG}\""
278                                                                + " ConversionPattern=\"%d{dd.MM.yyyy HH:mm:ss} %-6p %m %n\""
279                                                                + " File=\"$var{HOME_WORKINGDIR}/logs/$var{log_file," + getConfigurationName()
280                                                                + "}_$var{START_TIME}.log\" />") };
281                        }
282
283                        initLogger(theLogNodes);
284                }
285
286                final String username = (String) fSystemVariables.get("HTTP_USERNAME");
287                final String password = (String) fSystemVariables.get("HTTP_PASSWORD");
288                if (username != null && password != null) {
289                        Authenticator.setDefault(new Authenticator() {
290                                protected PasswordAuthentication getPasswordAuthentication() {
291                                        return new PasswordAuthentication(username, password.toCharArray());
292                                }
293                        });
294                }
295        }
296
297        protected String choicePriorityRecipeFolder(String text, String[] possibleValues) {
298                String result = inputChoice(text, null, possibleValues, possibleValues[0], null, false);
299                return result;
300        }
301
302        public void runSetupNodes() throws Exception {
303                if (!Boolean.valueOf(System.getProperty("skip.startup"))) {
304                        Node[] theNodes = fConfigNode.getNodes(SpecialCommands.STARTUP);
305                        TemplateProcessor tp = new TemplateProcessor(fSystemVariables, fConfigNode, getStartDir());
306                        if (theNodes != null) {
307                                for (Node node : theNodes) {
308                                        final String theAttribut = tp.replaceProperties(node.getAttribute("task"));
309                                        boolean async = false;
310                                        String asyncValue = tp.replaceProperties(node.getAttribute("async"));
311                                        if (asyncValue != null) {
312                                                async = Boolean.valueOf(asyncValue);
313                                        }
314                                        if (theAttribut != null) {
315                                                runTask(theAttribut, async);
316                                        } else {
317                                                RecipeRunner taskEditor = createTestRunner(null);
318                                                taskEditor.runTest(new Node[] { node });
319                                        }
320                                }
321                        }
322                }
323        }
324
325        protected void loadCustomProperties() {
326                if (fUserPreferences == null) {
327                        fUserPreferences = new Properties();
328
329                        // loading users preferences
330                        File preferencesFile = getPreferencesFile();
331                        try {
332                                FileInputStream fileInputStream = new FileInputStream(preferencesFile);
333                                fUserPreferences.load(fileInputStream);
334                                fileInputStream.close();
335
336                        } catch (IOException e) {
337                                // System.out.println("User preferences configuration file is not found: " +
338                                // preferencesFile);
339                        }
340                }
341        }
342
343        protected File getPreferencesFile() {
344                String configurationName = getConfigurationName();
345                String fileName;
346                if (configurationName != null) {
347                        fileName = configurationName + ".properties";
348                } else {
349                        fileName = ".properties";
350                }
351                File preferencesDir = new File(getHomeWorkingDir(), "preferences");
352                if (preferencesDir.exists() == false) {
353                        preferencesDir.mkdirs();
354                }
355                return new File(preferencesDir, fileName);
356        }
357
358        public String getCustomConfPropFileName(String configurationName) {
359                return getHomeConfigurationsDir() + "/" + fUser + "." + configurationName + ".properties";
360        }
361
362        public File getHomeConfigurationsDir() {
363                File file = new File(getHomeWorkingDir(), "configuration");
364                return file;
365        }
366
367        public void refreshTaskPath() throws IOException {
368                fTestsDescList.clear();
369                TemplateProcessor tp = new TemplateProcessor(fSystemVariables, fConfigNode, getStartDir());
370                getRecipesScaner().loadTaskPath(getConfigNode(), tp);
371        }
372
373        public void progressValue(int i, int length, boolean success) {
374
375        }
376
377        public void progressText(String name) {
378
379        }
380
381        public File getFile(String filePath) {
382                File file = null;
383                if (!StringUtils.startsWithAny(filePath, new String[] { "https:", "http:" })) {
384                        if (filePath != null) {
385                                if (filePath.startsWith("classpath:") || filePath.startsWith("jar:") || filePath.startsWith("file:")
386                                                || '/' == filePath.charAt(0) || '\\' == filePath.charAt(0) || filePath.indexOf(":\\") > 0
387                                                || '/' == filePath.charAt(0)) {
388                                        file = new File(filePath);
389                                } else {
390                                        file = new File(baseDir, filePath);
391                                }
392                        }
393                }
394
395                return file;
396        }
397
398        public String inputValue(String aName, String description, String aValue, ILogger log, String type,
399                        boolean notifyMe, Processor processor) {
400                System.out.print("Input ");
401                String line = inputValue(aName, description, null, type, null);
402                return line;
403        }
404
405        public String inputValue(String name, String description, String defaultValue, String type, Processor processor) {
406                if (defaultValue == null) {
407                        defaultValue = AEWorkspace.getInstance().getDefaultUserConfiguration(".inputValue." + name, defaultValue);
408                }
409
410                boolean password = "password".equalsIgnoreCase(type);
411
412                String showValue = !password ? defaultValue
413                                : (defaultValue != null ? StringUtils.repeat("*", defaultValue.length()) : "");
414                String message = "\"" + StringUtils.defaultIfEmpty(description, name) + "\""
415                                + (StringUtils.isEmpty(defaultValue) ? "" : " [" + showValue + "]") + ": ";
416                System.out.print(message);
417
418                String line = null;
419                if (!Processor.isSilentMode(processor)) {
420                        line = readLine(password);
421                        if (StringUtils.isEmpty(line)) {
422                                line = defaultValue;
423                        } else {
424                                AEWorkspace.getInstance().setDefaultUserConfiguration(".inputValue." + name, line);
425                        }
426                } else {
427                        line = defaultValue;
428                        System.out.println(defaultValue);
429                }
430                return line;
431        }
432
433        @Override
434        public boolean confirmation(String name, String message, Processor unit, boolean notifyMe) throws Exception {
435                if (StringUtils.isBlank(name)) {
436                        System.out.print(message + ", (yes/no): ");
437                } else {
438                        System.out.print(name + " [" + message + "], (yes/no): ");
439                }
440                boolean result = false;
441                String line = readLine(false);
442                result = BooleanUtils.toBoolean(line);
443                return result;
444        }
445
446        public void inputDataTable(Processor unit, Node aTableNode, boolean notifyMe) throws IOException {
447                Node[] theVariablesNodes = aTableNode.getNodes("var");
448                String theLine = null;
449
450                String theFileAttribut = aTableNode.getAttribute("file");
451                if (unit != null)
452                        theFileAttribut = unit.replaceProperties(aTableNode.getAttribute("file"));
453
454                if (theFileAttribut != null) {
455                        File file = unit.getFile(theFileAttribut);
456                        if (file.exists()) {
457                                while ((theLine = readLine(false)) != null) {
458                                        theLine = theLine.trim();
459                                        if (theLine.length() == 0) {
460                                                continue;
461                                        }
462                                        if (theLine.charAt(0) == '#') {
463                                                continue;
464                                        }
465                                        int thePbrk = theLine.indexOf('=');
466
467                                        String theName = StringUtils.upperCase(theLine.substring(0, thePbrk));
468                                        String theValue = theLine.substring(thePbrk + 1);
469
470                                        Node theNode = new Node("var");
471                                        theNode.setAttribute("name", theName);
472                                        theNode.setAttribute("value", theValue);
473
474                                        for (Node node : theVariablesNodes) {
475                                                if (node.getAttribute("name").equalsIgnoreCase(theName)) {
476                                                        node.setAttribute("value", theValue);
477                                                }
478                                        }
479
480                                }
481                        }
482                } else {
483                        String title = aTableNode.getAttribute("name");
484
485                        for (Node node : theVariablesNodes) {
486                                String name = node.getAttribute("name");
487                                String value = node.getAttribute("value");
488
489                                String defaultValue = value;
490
491                                String savedVarName = ".inputValue." + title + "." + StringUtils.upperCase(name);
492                                if (defaultValue == null) {
493                                        defaultValue = AEWorkspace.getInstance().getDefaultUserConfiguration(savedVarName, null);
494                                }
495                                if (defaultValue == null) {
496                                        defaultValue = node.getAttribute("default");
497                                }
498
499                                if (Processor.isSilentMode(unit)) {
500                                        value = defaultValue;
501                                } else {
502                                        value = inputValue(name, null, defaultValue, null, unit);
503                                        AEWorkspace.getInstance().setDefaultUserConfiguration(savedVarName, value);
504                                }
505
506                                unit.setVariableValue(name, value);
507                        }
508                }
509        }
510
511        public void loadConfProperties() throws IOException {
512
513                fSystemVariables.clear();
514
515                Properties properties = new Properties();
516                File theConfFile = new File(getCustomConfPropFileName(getConfigurationName()));
517                if (theConfFile.exists()) {
518                        FileInputStream theFile = new FileInputStream(theConfFile);
519                        properties.load(theFile);
520                        theFile.close();
521                }
522
523                Node[] theVarConfs = fConfigNode.getNodes("Var");
524                for (int i = 0; i < theVarConfs.length; i++) {
525                        Node varNode = theVarConfs[i];
526                        String name = StringUtils.upperCase(varNode.getAttribute("name"));
527
528                        if (name != null) {
529                                Map<String, String> variableDefinition = parseVariableDefinition(varNode);
530                                fSystemVariables.putAll(variableDefinition);
531
532                        } else {
533                                Processor templateProcessor = new BaseProcessor(fSystemVariables, fConfigNode, getStartDir());
534                                String filePath = templateProcessor.replaceProperties(varNode.getAttribute("file"));
535                                File file = getFile(filePath);
536                                templateProcessor.loadProperties(file, fSystemVariables, true);
537                        }
538                }
539
540                for (String key : properties.stringPropertyNames()) {
541                        fSystemVariables.put(key, properties.getProperty(key));
542                }
543
544                fSystemVariables.put("ENV", System.getenv());
545                fSystemVariables.put("SYSTEM", System.getProperties());
546
547                fSystemVariables.put("WORKINGDIR", getStartDir().getAbsolutePath());
548                fSystemVariables.put("HOME_WORKINGDIR", getHomeWorkingDir().getAbsolutePath());
549                fSystemVariables.put("START_TIME", Long.toString(startTime));
550                fSystemVariables.put("USER_NAME", fUser);
551
552                Node[] theTableVarConfs = fConfigNode.getNodes("Table");
553                Processor unit = new BaseProcessor(this, log, getStartDir());
554                Processor.setSilentMode(unit, true);
555
556                for (int i = 0; i < theTableVarConfs.length; i++) {
557                        inputDataTable(unit, theTableVarConfs[i], false);
558                        fSystemVariables.putAll(unit.getVariables());
559                }
560
561                boolean stopped = unit.isStopped();
562                if (stopped) {
563                        throw new TaskCancelingException();
564                }
565
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                        runner = createTestRunner(name);
1132                        String testPath = getTestPath(name);
1133                        if (testPath != null) {
1134                                if (async) {
1135                                        TaskThread theThread = new TaskThread(runner, testPath);
1136                                        theThread.start();
1137
1138                                } else {
1139                                        try {
1140                                                runner.makeRecipe(testPath);
1141                                        } catch (CommandException e) {
1142                                                log.error("Task failed.", e);
1143                                        }
1144                                }
1145                        }
1146                }
1147
1148                return runner;
1149        }
1150
1151        protected RecipeRunner createTestRunner(String name) throws CommandException {
1152                RecipeRunner runner = new RecipeRunner(this);
1153                Processor processor = new BaseProcessor(this, log, getStartDir());
1154                processor.setTestListener(runner);
1155                runner.setProcessor(processor);
1156                runner.setLog(log);
1157                return runner;
1158        }
1159
1160        public void removeTestPath(String name) {
1161                if (fTestsDescList.get(name) != null)
1162                        fTestsDescList.remove(name);
1163        }
1164
1165        public void setTestPath(String name, String path) {
1166                fTestsDescList.put(name, path);
1167        }
1168
1169        public String getWorkingDir() {
1170                return getStartDir().getAbsolutePath();
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 setBaseDir(File baseDir) {
1290                this.baseDir = baseDir;
1291        }
1292
1293        public File getBaseDir() {
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}