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