]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.gnuplot/src/org/simantics/gnuplot/Gnuplot.java
f1321796ab6fdd6b5f3407e3415f9d1dfa2e08ee
[simantics/platform.git] / bundles / org.simantics.gnuplot / src / org / simantics / gnuplot / Gnuplot.java
1 package org.simantics.gnuplot;
2
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;
9
10 /**
11  * @author Tuukka Lehtonen
12  * @since 1.24
13  */
14 public class Gnuplot {
15
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";
19
20     private Path executable;
21
22     public Gnuplot(Path executable) {
23         this.executable = executable;
24     }
25
26     public static Gnuplot detect() throws IOException {
27         try {
28             return new Gnuplot(findGnuplotPath());
29         } catch (InterruptedException e) {
30             throw new IOException(e);
31         }
32     }
33
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) {
37             int c;
38             c = in.read();
39             if(c <= 0)
40                 break;
41             sw.write(c);
42         }
43         return sw.toString();
44     }
45
46     private static boolean testExecutable(Path exe) throws IOException, InterruptedException {
47         Process process = new ProcessBuilder(exe.toString(), "-V").start();
48         try {
49             if (GNUPLOT_VERSION_STRING_STARTS_WITH.startsWith( readInput(process.getInputStream()) ))
50                 return true;
51             return false;
52         } finally {
53             process.getInputStream().close();
54             process.getErrorStream().close();
55             process.waitFor();
56         }
57     }
58
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)) {
65                 return exe;
66             }
67         }
68         if (fail)
69             throw new UnsupportedOperationException("Couldn't find executable '" + executableName + "' on the system path.");
70         return null;
71     }
72
73     private static Path findExecutable(String path, boolean splitPath, boolean fail) throws IOException, InterruptedException {
74         switch (OSType.calculate()) {
75         case APPLE:
76         case SUN:
77         case LINUX:
78             return findExecutable(splitPath ? path.split(":") : new String[] { path }, "gnuplot", fail);
79         case WINDOWS:
80             return findExecutable(splitPath ? path.split(";") : new String[] { path }, "gnuplot.exe", fail);
81         default:
82             throw new UnsupportedOperationException("unsupported platform");
83         }
84     }
85
86     private static Path findGnuplotPath() throws IOException, InterruptedException {
87         String path = System.getenv(GNUPLOT_ENV);
88         if (path != null) {
89             // Does GNUPLOT point directly to the executable?
90             Path p = findExecutable(new String[] { path }, null, false);
91             if (p != null)
92                 return p;
93             // Does GNUPLOT point to the gnuplot installation bin directory?
94             p = findExecutable(path, false, false);
95             if (p != null)
96                 return p;
97             // Does GNUPLOT point to the gnuplot installation root directory?
98             p = findExecutable(path + "/bin", false, false);
99             if (p != null)
100                 return p;
101         }
102         path = System.getenv(PATH_ENV);
103         return findExecutable(path, true, true);
104     }
105
106     private void execute0(Path workingDirectory, Path stdout, Path stderr, String... cmdline) throws IOException {
107         Process process = new ProcessBuilder(cmdline)
108                 .directory(workingDirectory.toFile())
109                 .start();
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();
115         try {
116             stdoutDumper.join();
117             stderrDumper.join();
118             process.waitFor();
119         } catch (InterruptedException e) {
120             throw new IOException(e);
121         }
122     }
123
124     public void execute(Path workingDirectory, Path stdout, Path stderr, Path script) throws IOException {
125         execute0(workingDirectory, stdout, stderr, executable.toString(), "-c", script.toString());
126     }
127
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) {
132             if (!first)
133                 e.append("; ");
134             first = false;
135             e.append(cmd);
136         }
137         e.append('"');
138         execute0(workingDirectory, stdout, stderr, executable.toString(), "-e", e.toString());
139     }
140
141     public GnuplotSession newSession(Path workingDirectory, Path stdout, Path stderr) throws IOException {
142         Process process = new ProcessBuilder(executable.toString())
143                 .directory(workingDirectory.toFile())
144                 .start();
145         return new GnuplotSession(workingDirectory, stdout, stderr, process);
146     }
147
148     static enum OSType {
149         APPLE, LINUX, SUN, WINDOWS, UNKNOWN;
150
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"))
156                 return APPLE;
157             if (osName.startsWith("windows"))
158                 return WINDOWS;
159             if (osName.startsWith("linux"))
160                 return LINUX;
161             if (osName.startsWith("sun"))
162                 return SUN;
163             return UNKNOWN;
164         }
165     }
166
167 }