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