6035 |
29 Oct 20 |
nicklas |
1 |
package net.sf.basedb.reggie.script; |
2863 |
28 Oct 14 |
nicklas |
2 |
|
5049 |
23 Oct 18 |
nicklas |
3 |
import java.io.BufferedInputStream; |
5049 |
23 Oct 18 |
nicklas |
4 |
import java.io.BufferedOutputStream; |
2863 |
28 Oct 14 |
nicklas |
5 |
import java.io.File; |
5049 |
23 Oct 18 |
nicklas |
6 |
import java.io.FileInputStream; |
5049 |
23 Oct 18 |
nicklas |
7 |
import java.io.FileOutputStream; |
3531 |
05 Oct 15 |
nicklas |
8 |
import java.io.IOException; |
5049 |
23 Oct 18 |
nicklas |
9 |
import java.io.InputStream; |
5049 |
23 Oct 18 |
nicklas |
10 |
import java.io.OutputStream; |
2863 |
28 Oct 14 |
nicklas |
11 |
|
2863 |
28 Oct 14 |
nicklas |
12 |
import net.sf.basedb.util.FileUtil; |
2863 |
28 Oct 14 |
nicklas |
13 |
|
2863 |
28 Oct 14 |
nicklas |
14 |
/** |
2863 |
28 Oct 14 |
nicklas |
Holds the result from executing a single R command. |
2863 |
28 Oct 14 |
nicklas |
16 |
|
2863 |
28 Oct 14 |
nicklas |
@author nicklas |
2863 |
28 Oct 14 |
nicklas |
@since 2.18 |
2863 |
28 Oct 14 |
nicklas |
19 |
*/ |
6036 |
02 Nov 20 |
nicklas |
20 |
public class ScriptResult |
2863 |
28 Oct 14 |
nicklas |
21 |
{ |
2863 |
28 Oct 14 |
nicklas |
22 |
|
3002 |
04 Dec 14 |
nicklas |
23 |
private String script; |
3506 |
23 Sep 15 |
nicklas |
24 |
private String scriptDir; |
5431 |
16 May 19 |
nicklas |
25 |
private TemporaryWorkDir tmp; |
2863 |
28 Oct 14 |
nicklas |
26 |
private File workDir; |
2863 |
28 Oct 14 |
nicklas |
27 |
private int exitStatus; |
2863 |
28 Oct 14 |
nicklas |
28 |
private String stdout; |
2863 |
28 Oct 14 |
nicklas |
29 |
private String stderr; |
2863 |
28 Oct 14 |
nicklas |
30 |
private Exception exception; |
2863 |
28 Oct 14 |
nicklas |
31 |
|
6036 |
02 Nov 20 |
nicklas |
32 |
public ScriptResult() |
2991 |
02 Dec 14 |
nicklas |
33 |
{} |
2863 |
28 Oct 14 |
nicklas |
34 |
|
3506 |
23 Sep 15 |
nicklas |
35 |
void setScript(String script, String scriptDir) |
3002 |
04 Dec 14 |
nicklas |
36 |
{ |
3002 |
04 Dec 14 |
nicklas |
37 |
this.script = script; |
3506 |
23 Sep 15 |
nicklas |
38 |
this.scriptDir = scriptDir; |
3002 |
04 Dec 14 |
nicklas |
39 |
} |
3002 |
04 Dec 14 |
nicklas |
40 |
|
3002 |
04 Dec 14 |
nicklas |
41 |
/** |
3002 |
04 Dec 14 |
nicklas |
Get the path to the script file that was executed to produce the results. |
3002 |
04 Dec 14 |
nicklas |
43 |
*/ |
3002 |
04 Dec 14 |
nicklas |
44 |
public String getScript() |
3002 |
04 Dec 14 |
nicklas |
45 |
{ |
3002 |
04 Dec 14 |
nicklas |
46 |
return script; |
3002 |
04 Dec 14 |
nicklas |
47 |
} |
3002 |
04 Dec 14 |
nicklas |
48 |
|
3506 |
23 Sep 15 |
nicklas |
49 |
/** |
3506 |
23 Sep 15 |
nicklas |
Get the path to the directory of script file that was executed to produce the results. |
3506 |
23 Sep 15 |
nicklas |
@since 3.7 |
3506 |
23 Sep 15 |
nicklas |
52 |
*/ |
3506 |
23 Sep 15 |
nicklas |
53 |
public String getScriptDir() |
3506 |
23 Sep 15 |
nicklas |
54 |
{ |
3506 |
23 Sep 15 |
nicklas |
55 |
return scriptDir; |
3506 |
23 Sep 15 |
nicklas |
56 |
} |
3506 |
23 Sep 15 |
nicklas |
57 |
|
5431 |
16 May 19 |
nicklas |
58 |
void setWorkDir(File workDir) |
2863 |
28 Oct 14 |
nicklas |
59 |
{ |
2863 |
28 Oct 14 |
nicklas |
60 |
this.workDir = workDir; |
2863 |
28 Oct 14 |
nicklas |
61 |
} |
2863 |
28 Oct 14 |
nicklas |
62 |
|
5431 |
16 May 19 |
nicklas |
63 |
void setTmpWorkDir(TemporaryWorkDir tmp) |
5431 |
16 May 19 |
nicklas |
64 |
{ |
5431 |
16 May 19 |
nicklas |
65 |
this.tmp = tmp; |
5431 |
16 May 19 |
nicklas |
66 |
this.workDir = tmp.getWorkDir(); |
5431 |
16 May 19 |
nicklas |
67 |
} |
5431 |
16 May 19 |
nicklas |
68 |
|
2863 |
28 Oct 14 |
nicklas |
69 |
/** |
2863 |
28 Oct 14 |
nicklas |
Get the working directory that used and were generated files can be found. |
2863 |
28 Oct 14 |
nicklas |
If this directory was automatically generated when the R script was |
2863 |
28 Oct 14 |
nicklas |
executed it will automatically be removed when this object instance is |
2863 |
28 Oct 14 |
nicklas |
garbage collected. To force earlier removal, call {@link #removeWorkDir()}. |
2863 |
28 Oct 14 |
nicklas |
74 |
*/ |
2863 |
28 Oct 14 |
nicklas |
75 |
public File getWorkDir() |
2863 |
28 Oct 14 |
nicklas |
76 |
{ |
2863 |
28 Oct 14 |
nicklas |
77 |
return workDir; |
2863 |
28 Oct 14 |
nicklas |
78 |
} |
2863 |
28 Oct 14 |
nicklas |
79 |
|
2863 |
28 Oct 14 |
nicklas |
80 |
/** |
2863 |
28 Oct 14 |
nicklas |
Close the results and remove all files in the working |
2863 |
28 Oct 14 |
nicklas |
directory. |
2863 |
28 Oct 14 |
nicklas |
83 |
*/ |
2863 |
28 Oct 14 |
nicklas |
84 |
public void removeWorkDir() |
2863 |
28 Oct 14 |
nicklas |
85 |
{ |
5431 |
16 May 19 |
nicklas |
86 |
if (tmp != null) |
2863 |
28 Oct 14 |
nicklas |
87 |
{ |
5431 |
16 May 19 |
nicklas |
88 |
tmp.close(); |
5431 |
16 May 19 |
nicklas |
89 |
tmp = null; |
5431 |
16 May 19 |
nicklas |
90 |
workDir = null; |
5431 |
16 May 19 |
nicklas |
91 |
} |
5431 |
16 May 19 |
nicklas |
92 |
else if (workDir != null) |
5431 |
16 May 19 |
nicklas |
93 |
{ |
2863 |
28 Oct 14 |
nicklas |
94 |
FileUtil.deleteTempDirectory(workDir); |
2863 |
28 Oct 14 |
nicklas |
95 |
workDir = null; |
2863 |
28 Oct 14 |
nicklas |
96 |
} |
2863 |
28 Oct 14 |
nicklas |
97 |
} |
2863 |
28 Oct 14 |
nicklas |
98 |
|
3531 |
05 Oct 15 |
nicklas |
99 |
/** |
3531 |
05 Oct 15 |
nicklas |
Called before the script is started and allows the |
3531 |
05 Oct 15 |
nicklas |
result object to upload files that are needed by |
3531 |
05 Oct 15 |
nicklas |
the script to the working directory. |
3531 |
05 Oct 15 |
nicklas |
103 |
*/ |
3531 |
05 Oct 15 |
nicklas |
104 |
protected void loadFilesToWorkDir() |
3531 |
05 Oct 15 |
nicklas |
105 |
throws IOException |
3531 |
05 Oct 15 |
nicklas |
106 |
{} |
3531 |
05 Oct 15 |
nicklas |
107 |
|
5962 |
03 Jun 20 |
nicklas |
108 |
/** |
5962 |
03 Jun 20 |
nicklas |
Called after the script has finished to allow |
5962 |
03 Jun 20 |
nicklas |
the result object to remove temporary files that are |
5962 |
03 Jun 20 |
nicklas |
no longer needed (eg. files that have been used as |
5962 |
03 Jun 20 |
nicklas |
indata for the script). |
5962 |
03 Jun 20 |
nicklas |
@since 4.27.1 |
5962 |
03 Jun 20 |
nicklas |
114 |
*/ |
5962 |
03 Jun 20 |
nicklas |
115 |
protected void cleanupWorkDir() |
5962 |
03 Jun 20 |
nicklas |
116 |
{} |
5962 |
03 Jun 20 |
nicklas |
117 |
|
2863 |
28 Oct 14 |
nicklas |
118 |
void setExitStatus(int exitStatus) |
2863 |
28 Oct 14 |
nicklas |
119 |
{ |
2863 |
28 Oct 14 |
nicklas |
120 |
this.exitStatus = exitStatus; |
2863 |
28 Oct 14 |
nicklas |
121 |
} |
2863 |
28 Oct 14 |
nicklas |
122 |
|
2863 |
28 Oct 14 |
nicklas |
123 |
/** |
2863 |
28 Oct 14 |
nicklas |
Get the exit status of the command. A value of 0 should indicate success, |
2863 |
28 Oct 14 |
nicklas |
all other values some kind of error. |
2863 |
28 Oct 14 |
nicklas |
126 |
*/ |
2863 |
28 Oct 14 |
nicklas |
127 |
public int getExitStatus() |
2863 |
28 Oct 14 |
nicklas |
128 |
{ |
2863 |
28 Oct 14 |
nicklas |
129 |
return exitStatus; |
2863 |
28 Oct 14 |
nicklas |
130 |
} |
2863 |
28 Oct 14 |
nicklas |
131 |
|
2863 |
28 Oct 14 |
nicklas |
132 |
void setStdout(String stdout) |
2863 |
28 Oct 14 |
nicklas |
133 |
{ |
2863 |
28 Oct 14 |
nicklas |
134 |
this.stdout = stdout; |
2863 |
28 Oct 14 |
nicklas |
135 |
} |
2863 |
28 Oct 14 |
nicklas |
136 |
|
2863 |
28 Oct 14 |
nicklas |
137 |
/** |
2863 |
28 Oct 14 |
nicklas |
Get the text written to the standard output stream from the command. |
2863 |
28 Oct 14 |
nicklas |
139 |
*/ |
2863 |
28 Oct 14 |
nicklas |
140 |
public String getStdout() |
2863 |
28 Oct 14 |
nicklas |
141 |
{ |
2863 |
28 Oct 14 |
nicklas |
142 |
return stdout; |
2863 |
28 Oct 14 |
nicklas |
143 |
} |
2863 |
28 Oct 14 |
nicklas |
144 |
|
2863 |
28 Oct 14 |
nicklas |
145 |
void setStderr(String stderr) |
2863 |
28 Oct 14 |
nicklas |
146 |
{ |
2863 |
28 Oct 14 |
nicklas |
147 |
this.stderr = stderr; |
2863 |
28 Oct 14 |
nicklas |
148 |
} |
2863 |
28 Oct 14 |
nicklas |
149 |
/** |
2863 |
28 Oct 14 |
nicklas |
Get the text written to standard error stream from the command. |
2863 |
28 Oct 14 |
nicklas |
151 |
*/ |
2863 |
28 Oct 14 |
nicklas |
152 |
public String getStderr() |
2863 |
28 Oct 14 |
nicklas |
153 |
{ |
2863 |
28 Oct 14 |
nicklas |
154 |
return stderr; |
2863 |
28 Oct 14 |
nicklas |
155 |
} |
2863 |
28 Oct 14 |
nicklas |
156 |
|
5049 |
23 Oct 18 |
nicklas |
157 |
/** |
5049 |
23 Oct 18 |
nicklas |
Saves a file to the working directory of the script. Read |
5049 |
23 Oct 18 |
nicklas |
everything from 'in' and saves it to the file 'name' in |
5049 |
23 Oct 18 |
nicklas |
working directory. |
5049 |
23 Oct 18 |
nicklas |
@since 4.20 |
5049 |
23 Oct 18 |
nicklas |
162 |
*/ |
5056 |
26 Oct 18 |
nicklas |
163 |
public void createWorkFile(String name, boolean overwrite, InputStream in, boolean closeIn) |
5049 |
23 Oct 18 |
nicklas |
164 |
throws IOException |
5049 |
23 Oct 18 |
nicklas |
165 |
{ |
5597 |
11 Sep 19 |
nicklas |
166 |
OutputStream out = null; |
5597 |
11 Sep 19 |
nicklas |
167 |
try |
5056 |
26 Oct 18 |
nicklas |
168 |
{ |
5597 |
11 Sep 19 |
nicklas |
169 |
File file = new File(getWorkDir(), name); |
5597 |
11 Sep 19 |
nicklas |
170 |
if (overwrite || !file.exists()) |
5056 |
26 Oct 18 |
nicklas |
171 |
{ |
5056 |
26 Oct 18 |
nicklas |
172 |
out = new BufferedOutputStream(new FileOutputStream(file)); |
5056 |
26 Oct 18 |
nicklas |
173 |
FileUtil.copy(in, out); |
5056 |
26 Oct 18 |
nicklas |
174 |
} |
5056 |
26 Oct 18 |
nicklas |
175 |
} |
5597 |
11 Sep 19 |
nicklas |
176 |
finally |
5597 |
11 Sep 19 |
nicklas |
177 |
{ |
5597 |
11 Sep 19 |
nicklas |
178 |
if (closeIn) FileUtil.close(in); |
5597 |
11 Sep 19 |
nicklas |
179 |
FileUtil.close(out); |
5597 |
11 Sep 19 |
nicklas |
180 |
} |
5056 |
26 Oct 18 |
nicklas |
181 |
} |
5056 |
26 Oct 18 |
nicklas |
182 |
|
5056 |
26 Oct 18 |
nicklas |
183 |
/** |
5056 |
26 Oct 18 |
nicklas |
Create a file in the working directory. |
5056 |
26 Oct 18 |
nicklas |
@since 4.20 |
5056 |
26 Oct 18 |
nicklas |
186 |
*/ |
5056 |
26 Oct 18 |
nicklas |
187 |
public OutputStream createWorkFile(String name, boolean overwrite) |
5056 |
26 Oct 18 |
nicklas |
188 |
throws IOException |
5056 |
26 Oct 18 |
nicklas |
189 |
{ |
5056 |
26 Oct 18 |
nicklas |
190 |
File file = new File(getWorkDir(), name); |
5049 |
23 Oct 18 |
nicklas |
191 |
OutputStream out = null; |
5056 |
26 Oct 18 |
nicklas |
192 |
if (overwrite || !file.exists()) |
5049 |
23 Oct 18 |
nicklas |
193 |
{ |
5049 |
23 Oct 18 |
nicklas |
194 |
out = new BufferedOutputStream(new FileOutputStream(file)); |
5049 |
23 Oct 18 |
nicklas |
195 |
} |
5056 |
26 Oct 18 |
nicklas |
196 |
return out; |
5049 |
23 Oct 18 |
nicklas |
197 |
} |
5049 |
23 Oct 18 |
nicklas |
198 |
|
5049 |
23 Oct 18 |
nicklas |
199 |
/** |
5962 |
03 Jun 20 |
nicklas |
Remove a file from the working directory. |
5962 |
03 Jun 20 |
nicklas |
@since 4.27.1 |
5962 |
03 Jun 20 |
nicklas |
202 |
*/ |
5962 |
03 Jun 20 |
nicklas |
203 |
public void removeWorkFile(String name) |
5962 |
03 Jun 20 |
nicklas |
204 |
{ |
5962 |
03 Jun 20 |
nicklas |
205 |
File file = new File(getWorkDir(), name); |
5962 |
03 Jun 20 |
nicklas |
206 |
if (file.isFile()) file.delete(); |
5962 |
03 Jun 20 |
nicklas |
207 |
} |
5962 |
03 Jun 20 |
nicklas |
208 |
|
5962 |
03 Jun 20 |
nicklas |
209 |
/** |
5049 |
23 Oct 18 |
nicklas |
Check if a result file exists or not. |
5049 |
23 Oct 18 |
nicklas |
@since 4.20 |
5049 |
23 Oct 18 |
nicklas |
212 |
*/ |
5049 |
23 Oct 18 |
nicklas |
213 |
public boolean resultFileExists(String name) |
5049 |
23 Oct 18 |
nicklas |
214 |
{ |
5049 |
23 Oct 18 |
nicklas |
215 |
File file = new File(getWorkDir(), name); |
5049 |
23 Oct 18 |
nicklas |
216 |
return file.exists(); |
5049 |
23 Oct 18 |
nicklas |
217 |
} |
5049 |
23 Oct 18 |
nicklas |
218 |
|
5049 |
23 Oct 18 |
nicklas |
219 |
/** |
5049 |
23 Oct 18 |
nicklas |
Read result file from working directory if it exists. |
5049 |
23 Oct 18 |
nicklas |
Returns null if not not found. |
5049 |
23 Oct 18 |
nicklas |
@since 4.20 |
5049 |
23 Oct 18 |
nicklas |
223 |
*/ |
5049 |
23 Oct 18 |
nicklas |
224 |
public InputStream getResultFile(String name) |
5049 |
23 Oct 18 |
nicklas |
225 |
throws IOException |
5049 |
23 Oct 18 |
nicklas |
226 |
{ |
5049 |
23 Oct 18 |
nicklas |
227 |
File file = new File(getWorkDir(), name); |
5049 |
23 Oct 18 |
nicklas |
228 |
InputStream in = null; |
5049 |
23 Oct 18 |
nicklas |
229 |
if (file.exists()) |
5049 |
23 Oct 18 |
nicklas |
230 |
{ |
5049 |
23 Oct 18 |
nicklas |
231 |
in = new BufferedInputStream(new FileInputStream(file)); |
5049 |
23 Oct 18 |
nicklas |
232 |
} |
5049 |
23 Oct 18 |
nicklas |
233 |
return in; |
5049 |
23 Oct 18 |
nicklas |
234 |
} |
5049 |
23 Oct 18 |
nicklas |
235 |
|
5049 |
23 Oct 18 |
nicklas |
236 |
/** |
5049 |
23 Oct 18 |
nicklas |
Save result file from working directory if it exists. |
5049 |
23 Oct 18 |
nicklas |
The output stream can optionally be closed automatically. |
5049 |
23 Oct 18 |
nicklas |
@return The number of bytes copied |
5049 |
23 Oct 18 |
nicklas |
@since 4.20 |
5049 |
23 Oct 18 |
nicklas |
241 |
*/ |
5049 |
23 Oct 18 |
nicklas |
242 |
public long saveResultFile(String name, OutputStream out, boolean closeOut) |
5049 |
23 Oct 18 |
nicklas |
243 |
throws IOException |
5049 |
23 Oct 18 |
nicklas |
244 |
{ |
5049 |
23 Oct 18 |
nicklas |
245 |
long copied = 0; |
5049 |
23 Oct 18 |
nicklas |
246 |
InputStream in = null; |
5049 |
23 Oct 18 |
nicklas |
247 |
try |
5049 |
23 Oct 18 |
nicklas |
248 |
{ |
5049 |
23 Oct 18 |
nicklas |
249 |
in = getResultFile(name); |
5049 |
23 Oct 18 |
nicklas |
250 |
if (in != null) copied = FileUtil.copy(in, out); |
5049 |
23 Oct 18 |
nicklas |
251 |
} |
5049 |
23 Oct 18 |
nicklas |
252 |
finally |
5049 |
23 Oct 18 |
nicklas |
253 |
{ |
5049 |
23 Oct 18 |
nicklas |
254 |
if (closeOut) FileUtil.close(out); |
5049 |
23 Oct 18 |
nicklas |
255 |
FileUtil.close(in); |
5049 |
23 Oct 18 |
nicklas |
256 |
} |
5049 |
23 Oct 18 |
nicklas |
257 |
return copied; |
5049 |
23 Oct 18 |
nicklas |
258 |
} |
5049 |
23 Oct 18 |
nicklas |
259 |
|
2863 |
28 Oct 14 |
nicklas |
260 |
void setException(Exception ex) |
2863 |
28 Oct 14 |
nicklas |
261 |
{ |
2863 |
28 Oct 14 |
nicklas |
262 |
this.exception = ex; |
2863 |
28 Oct 14 |
nicklas |
263 |
this.stderr = ex.getMessage(); |
2863 |
28 Oct 14 |
nicklas |
264 |
this.exitStatus = -1; |
2863 |
28 Oct 14 |
nicklas |
265 |
} |
2863 |
28 Oct 14 |
nicklas |
266 |
|
2863 |
28 Oct 14 |
nicklas |
267 |
/** |
2863 |
28 Oct 14 |
nicklas |
Get the exception that may have caused a failure. Exception are typically |
2863 |
28 Oct 14 |
nicklas |
indications that something was wrong on the local server and not the |
2863 |
28 Oct 14 |
nicklas |
remote server. If an exception has occurred. |
2863 |
28 Oct 14 |
nicklas |
271 |
*/ |
2863 |
28 Oct 14 |
nicklas |
272 |
public Exception getException() |
2863 |
28 Oct 14 |
nicklas |
273 |
{ |
2863 |
28 Oct 14 |
nicklas |
274 |
return exception; |
2863 |
28 Oct 14 |
nicklas |
275 |
} |
2863 |
28 Oct 14 |
nicklas |
276 |
|
2863 |
28 Oct 14 |
nicklas |
277 |
@Override |
2863 |
28 Oct 14 |
nicklas |
278 |
public String toString() |
2863 |
28 Oct 14 |
nicklas |
279 |
{ |
2863 |
28 Oct 14 |
nicklas |
280 |
if (exitStatus == 0) |
2863 |
28 Oct 14 |
nicklas |
281 |
{ |
2991 |
02 Dec 14 |
nicklas |
282 |
return stdout; |
2863 |
28 Oct 14 |
nicklas |
283 |
} |
2863 |
28 Oct 14 |
nicklas |
284 |
else |
2863 |
28 Oct 14 |
nicklas |
285 |
{ |
2991 |
02 Dec 14 |
nicklas |
286 |
return "[" + exitStatus + "] " + stderr; |
2863 |
28 Oct 14 |
nicklas |
287 |
} |
2863 |
28 Oct 14 |
nicklas |
288 |
} |
2863 |
28 Oct 14 |
nicklas |
289 |
} |