1 // ******************************************************************************
2 //
3 // Title: Force Field X.
4 // Description: Force Field X - Software for Molecular Biophysics.
5 // Copyright: Copyright (c) Michael J. Schnieders 2001-2025.
6 //
7 // This file is part of Force Field X.
8 //
9 // Force Field X is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License version 3 as published by
11 // the Free Software Foundation.
12 //
13 // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 // details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20 // Place, Suite 330, Boston, MA 02111-1307 USA
21 //
22 // Linking this library statically or dynamically with other modules is making a
23 // combined work based on this library. Thus, the terms and conditions of the
24 // GNU General Public License cover the whole combination.
25 //
26 // As a special exception, the copyright holders of this library give you
27 // permission to link this library with independent modules to produce an
28 // executable, regardless of the license terms of these independent modules, and
29 // to copy and distribute the resulting executable under terms of your choice,
30 // provided that you also meet, for each linked independent module, the terms
31 // and conditions of the license of that module. An independent module is a
32 // module which is not derived from or based on this library. If you modify this
33 // library, you may extend this exception to your version of the library, but
34 // you are not obligated to do so. If you do not wish to do so, delete this
35 // exception statement from your version.
36 //
37 // ******************************************************************************
38 package ffx.ui;
39
40 import java.io.File;
41 import java.util.logging.Logger;
42 import org.apache.commons.lang3.SystemUtils;
43 import org.apache.commons.lang3.builder.ToStringBuilder;
44
45 /**
46 * FFXExec encapsulates a native replacement for the JDK System.exec() method. TINKER programs are
47 * executed in their own thread through a call to a Native method called "FFXExec" which in turn
48 * calls the function "system()". The reason we are not using the System.exec() methods is that some
49 * TINKER routines execute indefinitely. Users may want to exit Force Field X and shut down the JVM
50 * after launching a dynamics run, for example. In this case the thread should not be dependent on a
51 * JVM instance.
52 *
53 * @author Michael J. Schnieders
54 */
55 public class FFXExec implements Runnable {
56
57 private static final Logger logger = Logger.getLogger(FFXExec.class.getName());
58 private static String path;
59 private static String ld_library_path;
60 private static String classpath;
61 private FFXSystem system;
62 private String name;
63 private String args;
64 private String dir;
65 private MainPanel mainPanel;
66 private File newFile;
67 private boolean alive = true;
68 private boolean openOnto;
69 private int returnValue = 0;
70 /**
71 * Constructor
72 *
73 * @param s FFXSystem the Native command will execute on
74 * @param n Name of the log file
75 * @param a Command to execute
76 * @param d Directory to launch the command in
77 * @param m MainPanel
78 * @param file File to open
79 * @param o Load the resulting version file onto the passed FFXSystem
80 */
81 public FFXExec(FFXSystem s, String n, String a, String d, MainPanel m, File file, boolean o) {
82 system = s;
83 name = n;
84 args = a;
85 dir = d;
86 mainPanel = m;
87 newFile = file;
88 openOnto = o;
89 logger.info(toString());
90 }
91
92 /**
93 * Getter for the field <code>returnValue</code>.
94 *
95 * @return a int.
96 */
97 public int getReturnValue() {
98 return returnValue;
99 }
100
101 /**
102 * isAlive
103 *
104 * @return a boolean.
105 */
106 public boolean isAlive() {
107 return alive;
108 }
109
110 /**
111 * Executes the native call to "System()" and notifies the ResultPanel upon completion. This
112 * should only be called indirectly by Thread.Start()
113 */
114 public void run() {
115 setEnv();
116 if (args == null
117 || dir == null
118 || path == null
119 || classpath == null
120 || ld_library_path == null) {
121 Logger.getLogger("ffx")
122 .severe(
123 "Native executable could not be executed."
124 + "\nCommand: "
125 + args
126 + "\nDIR: "
127 + dir
128 + "\nPATH: "
129 + path
130 + "\nCLASSPATH: "
131 + classpath
132 + "\nLD_LIBRARY_PATH: "
133 + ld_library_path);
134 return;
135 }
136 Logger.getLogger("ffx")
137 .info(
138 "Native command invoked."
139 + "\nCommand: "
140 + args
141 + "\nDIR: "
142 + dir
143 + "\nFFXExec - PATH: "
144 + path
145 + "\nCLASSPATH: "
146 + classpath
147 + "\nLD_LIBRARY_PATH: "
148 + ld_library_path);
149 returnValue = nativeExec(args, dir, path, classpath, ld_library_path);
150 // Check for a bad return value
151 if (returnValue < 0) {
152 Logger.getLogger("ffx")
153 .warning("The following job exited with a failure status: " + returnValue + "\n" + args);
154 }
155 // Open any created file and display the log.
156 if (mainPanel != null) {
157 if (newFile != null) {
158 String[] labels = args.split(" +");
159 String command = labels[0].toUpperCase() + " on " + system.getFile().getName();
160 if (openOnto) {
161 mainPanel.openOn(newFile, system, command);
162 } else {
163 mainPanel.open(newFile, command);
164 }
165 }
166 // mainPanel.getLogPanel().setDone(name);
167 }
168 alive = false;
169 }
170
171 /**
172 * {@inheritDoc}
173 *
174 * <p>Commons.Lang Style toString.
175 */
176 @Override
177 public String toString() {
178 ToStringBuilder toStringBuilder =
179 new ToStringBuilder(this).append(path).append(classpath).append(ld_library_path);
180 return toStringBuilder.toString();
181 }
182
183 // Set up the PATH (to TINKER/bin), CLASSPATH and LD_LIBRARY_PATH
184 private void setEnv() {
185 path = MainPanel.ffxDir.getAbsolutePath();
186 classpath = MainPanel.classpath;
187 // java.home should be the jre directory.
188 ld_library_path = System.getProperty("java.home", ".");
189 if (!SystemUtils.IS_OS_WINDOWS) {
190 ld_library_path =
191 ld_library_path
192 + "/lib/i386/client:"
193 + ld_library_path
194 + "/lib/i386:"
195 + ld_library_path
196 + "/lib/i386/native_threads";
197 } else {
198 ld_library_path = ld_library_path + "\\bin\\client";
199 path = path + File.pathSeparator + ld_library_path;
200 }
201 }
202
203 /**
204 * nativeExec method for launching native executables
205 *
206 * @param argv String
207 * @param dir String
208 * @param path String
209 * @param classpath String
210 * @param jre String
211 * @return int
212 */
213 private native int nativeExec(String argv, String dir, String path, String classpath, String jre);
214 }