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