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