1 package org.simantics.gnuplot;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.StringWriter;
6 import java.nio.file.Files;
7 import java.nio.file.Path;
8 import java.nio.file.Paths;
11 * @author Tuukka Lehtonen
14 public class Gnuplot {
16 private static final String GNUPLOT_VERSION_STRING_STARTS_WITH = "gnuplot ";
17 private static final String GNUPLOT_ENV = "GNUPLOT";
18 private static final String PATH_ENV = "PATH";
20 private Path executable;
22 public Gnuplot(Path executable) {
23 this.executable = executable;
26 public static Gnuplot detect() throws IOException {
28 return new Gnuplot(findGnuplotPath());
29 } catch (InterruptedException e) {
30 throw new IOException(e);
34 private static String readInput(InputStream in) throws IOException {
35 StringWriter sw = new StringWriter();
36 for (int l = 0; l < GNUPLOT_VERSION_STRING_STARTS_WITH.length(); ++l) {
46 private static boolean testExecutable(Path exe) throws IOException, InterruptedException {
47 Process process = new ProcessBuilder(exe.toString(), "-V").start();
49 if (GNUPLOT_VERSION_STRING_STARTS_WITH.startsWith( readInput(process.getInputStream()) ))
53 process.getInputStream().close();
54 process.getErrorStream().close();
59 private static Path findExecutable(String[] paths, String executableName, boolean fail) throws IOException, InterruptedException {
60 for (String p : paths) {
61 Path exe = Paths.get(p);
62 if (executableName != null)
63 exe = exe.resolve(executableName);
64 if (Files.exists(exe) && Files.isExecutable(exe) && testExecutable(exe)) {
69 throw new UnsupportedOperationException("Couldn't find executable '" + executableName + "' on the system path.");
73 private static Path findExecutable(String path, boolean splitPath, boolean fail) throws IOException, InterruptedException {
74 switch (OSType.calculate()) {
78 return findExecutable(splitPath ? path.split(":") : new String[] { path }, "gnuplot", fail);
80 return findExecutable(splitPath ? path.split(";") : new String[] { path }, "gnuplot.exe", fail);
82 throw new UnsupportedOperationException("unsupported platform");
86 private static Path findGnuplotPath() throws IOException, InterruptedException {
87 String path = System.getenv(GNUPLOT_ENV);
89 // Does GNUPLOT point directly to the executable?
90 Path p = findExecutable(new String[] { path }, null, false);
93 // Does GNUPLOT point to the gnuplot installation bin directory?
94 p = findExecutable(path, false, false);
97 // Does GNUPLOT point to the gnuplot installation root directory?
98 p = findExecutable(path + "/bin", false, false);
102 path = System.getenv(PATH_ENV);
103 return findExecutable(path, true, true);
106 private void execute0(Path workingDirectory, Path stdout, Path stderr, String... cmdline) throws IOException {
107 Process process = new ProcessBuilder(cmdline)
108 .directory(workingDirectory.toFile())
110 process.getOutputStream().close();
111 Thread stdoutDumper = new Thread(new InputStreamToFileCopier(process.getInputStream(), stdout));
112 Thread stderrDumper = new Thread(new InputStreamToFileCopier(process.getErrorStream(), stderr));
113 stdoutDumper.start();
114 stderrDumper.start();
119 } catch (InterruptedException e) {
120 throw new IOException(e);
124 public void execute(Path workingDirectory, Path stdout, Path stderr, Path script) throws IOException {
125 execute0(workingDirectory, stdout, stderr, executable.toString(), "-c", script.toString());
128 public void execute(Path workingDirectory, Path stdout, Path stderr, String... commands) throws IOException {
129 StringBuilder e = new StringBuilder().append('"');
130 boolean first = true;
131 for (String cmd : commands) {
138 execute0(workingDirectory, stdout, stderr, executable.toString(), "-e", e.toString());
141 public GnuplotSession newSession(Path workingDirectory, Path stdout, Path stderr) throws IOException {
142 Process process = new ProcessBuilder(executable.toString())
143 .directory(workingDirectory.toFile())
145 return new GnuplotSession(workingDirectory, stdout, stderr, process);
149 APPLE, LINUX, SUN, WINDOWS, UNKNOWN;
151 public static OSType calculate() {
152 String osName = System.getProperty("os.name");
153 assert osName != null;
154 osName = osName.toLowerCase();
155 if (osName.startsWith("mac os x"))
157 if (osName.startsWith("windows"))
159 if (osName.startsWith("linux"))
161 if (osName.startsWith("sun"))