001package jmri.jmrit.logixng.actions;
002
003import java.io.*;
004import java.util.*;
005
006import jmri.*;
007import jmri.jmrit.logixng.*;
008import jmri.jmrit.logixng.util.*;
009import jmri.jmrit.logixng.util.parser.*;
010import jmri.util.FileUtil;
011
012/**
013 * This action executes a program.
014 *
015 * @author Daniel Bergqvist Copyright 2025
016 */
017public class ExecuteProgram extends AbstractDigitalAction {
018
019    private final LogixNG_SelectString _selectProgram =
020            new LogixNG_SelectString(this);
021    private final LogixNG_SelectStringList _selectParameters =
022            new LogixNG_SelectStringList();
023    private final LogixNG_SelectString _selectWorkingDirectory =
024            new LogixNG_SelectString(this, "");
025
026
027    public ExecuteProgram(String sys, String user)
028            throws BadUserNameException, BadSystemNameException {
029        super(sys, user);
030    }
031
032    @Override
033    public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws ParserException, JmriException {
034        DigitalActionManager manager = InstanceManager.getDefault(DigitalActionManager.class);
035        String sysName = systemNames.get(getSystemName());
036        String userName = userNames.get(getSystemName());
037        if (sysName == null) sysName = manager.getAutoSystemName();
038        ExecuteProgram copy = new ExecuteProgram(sysName, userName);
039        copy.setComment(getComment());
040        _selectProgram.copy(copy._selectProgram);
041        _selectParameters.copy(copy._selectParameters);
042        _selectWorkingDirectory.copy(copy._selectWorkingDirectory);
043        return manager.registerAction(copy).deepCopyChildren(this, systemNames, userNames);
044    }
045
046    public LogixNG_SelectString getSelectProgram() {
047        return _selectProgram;
048    }
049
050    public LogixNG_SelectStringList getSelectParameters() {
051        return _selectParameters;
052    }
053
054    public LogixNG_SelectString getSelectWorkingDirectory() {
055        return _selectWorkingDirectory;
056    }
057
058    /** {@inheritDoc} */
059    @Override
060    public Category getCategory() {
061        return Category.OTHER;
062    }
063
064    /** {@inheritDoc} */
065    @Override
066    public void execute() throws JmriException {
067        final ConditionalNG conditionalNG;
068
069        synchronized(this) {
070            conditionalNG = getConditionalNG();
071        }
072
073        String program = _selectProgram.evaluateValue(conditionalNG);
074        List<String> parameters = _selectParameters.evaluateValue(conditionalNG);
075        String workingDirectory = _selectWorkingDirectory.evaluateValue(conditionalNG);
076
077        File workingDirectoryFile;
078        if (!workingDirectory.isBlank()) {
079            workingDirectoryFile = new File(workingDirectory);
080        } else {
081            // Ensure the default folder is the preferences folder.
082            workingDirectoryFile = new File(FileUtil.getUserFilesPath());
083        }
084
085        List<String> programAndParameters = new ArrayList<>();
086        programAndParameters.add(program);
087        programAndParameters.addAll(parameters);
088
089        try {
090            Runtime.getRuntime().exec(
091                    programAndParameters.toArray(String[]::new),
092                    null,
093                    workingDirectoryFile);
094        } catch (IOException e) {
095            throw new JmriException(e);
096        }
097    }
098
099    @Override
100    public String getShortDescription(Locale locale) {
101        return Bundle.getMessage(locale, "ExecuteProgram_Short");
102    }
103
104    @Override
105    public String getLongDescription(Locale locale) {
106        String program = _selectProgram.getDescription(locale);
107        return Bundle.getMessage(locale, "ExecuteProgram_Long", program);
108    }
109
110    /** {@inheritDoc} */
111    @Override
112    public void setup() {
113        // Do nothing
114    }
115
116    /** {@inheritDoc} */
117    @Override
118    public void disposeMe() {
119    }
120
121
122//    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ExecuteProgram.class);
123
124}