-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathGNUPlotExec.java
More file actions
263 lines (234 loc) · 8.85 KB
/
GNUPlotExec.java
File metadata and controls
263 lines (234 loc) · 8.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/* Copyright (c) 2007-2014 by panayotis.com
*
* JavaPlot is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 2.
*
* JavaPlot is free in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CrossMobile; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Created on October 14, 2007, 1:42 PM
*/
package com.panayotis.gnuplot;
import com.panayotis.gnuplot.terminal.GNUPlotTerminal;
import com.panayotis.gnuplot.utils.Debug;
import com.panayotis.gnuplot.utils.FileUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
/**
* Object representing the low level gnuplot executable. This object is used in
* the plot() method of GNUPlot.
*
* @author teras
*/
class GNUPlotExec {
private static final transient String DEFAULT_PATH = FileUtils.findPathExec();
private transient String gnuplotexec;
private boolean ispersist;
private boolean interactive;
private final static String[] persistcommand = {"path", "file", "-persist"};
private final static String[] persist_interactive = {"path", "file", "-", "-persist"};
private final static String[] nopersist = {"path", "file"};
private Process proc;
private String tmpfile;
/**
* Create a new GNUPlotExec object with defaultΩ gnuplot path. Under POSIX
* environment, it is able to automatically find gnuplot executable in the
* $PATH
*
* @throws java.io.IOException if something went wrong and it is impossible
* to continue without further notice
*/
GNUPlotExec() throws IOException {
this(null);
}
/**
* Create a new GNUPlotExec object with a specific gnuplot path.
*
* @param path Path of gnuplot executable
* @throws java.io.IOException if the gnuplot executable is not found
*/
GNUPlotExec(String path) throws IOException {
if (path == null)
path = DEFAULT_PATH;
setGNUPlotPath(path);
ispersist = true;
}
/**
* Set the desired path for gnuplot executable.
*
* @param path Filename of gnuplot executable
* @throws java.io.IOException gnuplot is not found, or not valid
*/
final void setGNUPlotPath(String path) throws IOException {
if (new File(path).isFile())
gnuplotexec = path;
else
throw new IOException("GnuPlot executable \"" + path + "\" not found.");
}
/**
* Retrieve the file path of gnuplot
*
* @return The gnuplot file path
*/
String getGNUPlotPath() {
return gnuplotexec;
}
/**
* Retrieves the command which will actually send to gnuplot, if we perform
* a plot with the given parameters to the selected terminal. <br> This
* method is used for debugging purposes.
*
* @return The commands to send to the gnuplot executable
*/
public String getCommands(GNUPlotParameters par, GNUPlotTerminal terminal) {
// Could cache these commands..
return par.getPlotCommands(terminal);
}
/**
* Plot using specific parameters and selected terminal.
*
* @param par The parameters to use
* @param terminal The terminal to use
* @throws com.panayotis.gnuplot.GNUPlotException throw if something goes
* wrong
*/
void plot(GNUPlotParameters par, GNUPlotTerminal terminal) throws GNUPlotException {
try {
final GNUPlotTerminal term = terminal; // Use this thread-aware variable instead of "terminal"
final String comms = getCommands(par, term); // Get the commands to send to gnuplot
final Messages msg = new Messages(); // Where to store messages from output threads
/*
* Display plot commands to send to gnuplot
*/
GNUPlot.getDebugger().msg("** Start of plot commands **", Debug.INFO);
GNUPlot.getDebugger().msg(comms, Debug.INFO);
GNUPlot.getDebugger().msg("** End of plot commands **", Debug.INFO);
/*
* It's time now to start the actual gnuplot application
*/
String[] command;
if (ispersist)
command = interactive ? persist_interactive : persistcommand;
else
command = nopersist;
command[0] = getGNUPlotPath();
command[1] = FileUtils.createTempFile(comms);
{
String cmdStr = "";
for (String cmd : command)
cmdStr += cmd + " ";
GNUPlot.getDebugger().msg("exec(" + cmdStr + ")", Debug.INFO);
}
final Process proc = Runtime.getRuntime().exec(command);
/*
* Windows buffers DEMAND asynchronus read & write
*/
/*
* Thread to process the STDERR of gnuplot
*/
Thread err_thread = new Thread() {
@Override
public void run() {
BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
StringBuilder buf = new StringBuilder();
String line;
try {
while ((line = err.readLine()) != null)
if (!line.trim().equals(""))
buf.append(line).append('\n');
err.close();
msg.output = buf.toString(); // Store output stream
} catch (IOException ex) {
ex.printStackTrace(new PrintStream(System.out));
}
}
};
/*
* Thread to process the STDOUT of gnuplot
*/
err_thread.start();
Thread out_thread = new Thread() {
@Override
public void run() {
msg.process = term.processOutput(proc.getInputStream()); // Execute terminal specific output parsing
}
};
out_thread.start();
if (interactive){
this.proc = proc;
this.tmpfile = command[1];
return;
}
try {
proc.waitFor(); // wait for process to finish
out_thread.join(); // wait for output (terminal related) thread to finish
err_thread.join(); // wait for error (messages) output to finish
} catch (InterruptedException ex) {
throw new GNUPlotException("Interrupted execution of gnuplot");
}
new File(command[1]).delete();
/*
* Find the error message, if any, with precendence to the error
* thread
*/
String message = msg.error != null ? msg.error : msg.process;
/*
* Determine if error stream should be dumbed or not
*/
int level = Debug.VERBOSE;
if (message != null)
level = Debug.ERROR;
GNUPlot.getDebugger().msg("** Start of error stream **", level);
GNUPlot.getDebugger().msg(msg.output, level);
GNUPlot.getDebugger().msg("** End of error stream **", level);
/*
* Throw an exception if an error occured
*/
if (message != null)
throw new GNUPlotException(message);
} catch (IOException ex) {
throw new GNUPlotException("IOException while executing \"" + getGNUPlotPath() + "\":" + ex.getLocalizedMessage());
}
}
void setPersist(boolean persist) {
ispersist = persist;
}
public void setInteractive(boolean interactive) {
this.interactive = interactive;
}
public void close(){
if (proc == null){
return;
}
try {
proc.getOutputStream().close();
proc.getInputStream().close();
proc.getErrorStream().close();
} catch (IOException e) {
e.printStackTrace();
}
try {
proc.waitFor(); // wait for process to finish
} catch (InterruptedException ex) {
throw new GNUPlotException("Interrupted execution of gnuplot");
}
new File(tmpfile).delete();
proc.destroy();
proc = null;
}
private class Messages {
String output = "";
String error = null;
String process = null;
}
}