]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.gnuplot/src/org/simantics/gnuplot/Gnuplot.java
Removed rubbish included in previous commit
[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) throws IOException {
23         if (!Files.exists(executable))
24             throw new IOException("Provided gnuplot executable does not exist: " + executable);
25         if (!Files.isExecutable(executable))
26             throw new IOException("Provided gnuplot executable is not marked executable: " + executable);
27         this.executable = executable;
28     }
29
30     @Override
31     public String toString() {
32         return executable.toString();
33     }
34
35     public static Gnuplot detect() throws IOException {
36         try {
37             return new Gnuplot(findGnuplotPath());
38         } catch (InterruptedException e) {
39             throw new IOException(e);
40         }
41     }
42
43     private static String readInput(InputStream in) throws IOException {
44         StringWriter sw = new StringWriter();
45         for (int l = 0; l < GNUPLOT_VERSION_STRING_STARTS_WITH.length(); ++l) {
46             int c;
47             c = in.read();
48             if(c <= 0)
49                 break;
50             sw.write(c);
51         }
52         return sw.toString();
53     }
54
55     private static boolean testExecutable(Path exe) throws IOException, InterruptedException {
56         Process process = new ProcessBuilder(exe.toString(), "-V").start();
57         try {
58             if (GNUPLOT_VERSION_STRING_STARTS_WITH.startsWith( readInput(process.getInputStream()) ))
59                 return true;
60             return false;
61         } finally {
62             process.getInputStream().close();
63             process.getErrorStream().close();
64             process.waitFor();
65         }
66     }
67
68     private static Path findExecutable(String[] paths, String executableName, boolean fail) throws IOException, InterruptedException {
69         for (String p : paths) {
70             Path exe = Paths.get(p);
71             if (executableName != null)
72                 exe = exe.resolve(executableName);
73             if (Files.exists(exe) && Files.isExecutable(exe) && testExecutable(exe)) {
74                 return exe;
75             }
76         }
77         if (fail)
78             throw new UnsupportedOperationException("Couldn't find executable '" + executableName + "' on the system path.");
79         return null;
80     }
81
82     private static Path findExecutable(String path, boolean splitPath, boolean fail) throws IOException, InterruptedException {
83         switch (OSType.calculate()) {
84         case APPLE:
85         case SUN:
86         case LINUX:
87             return findExecutable(splitPath ? path.split(":") : new String[] { path }, "gnuplot", fail);
88         case WINDOWS:
89             return findExecutable(splitPath ? path.split(";") : new String[] { path }, "gnuplot.exe", fail);
90         default:
91             throw new UnsupportedOperationException("unsupported platform");
92         }
93     }
94
95     private static Path findGnuplotPath() throws IOException, InterruptedException {
96         String path = System.getenv(GNUPLOT_ENV);
97         if (path != null) {
98             // Does GNUPLOT point directly to the executable?
99             Path p = findExecutable(new String[] { path }, null, false);
100             if (p != null)
101                 return p;
102             // Does GNUPLOT point to the gnuplot installation bin directory?
103             p = findExecutable(path, false, false);
104             if (p != null)
105                 return p;
106             // Does GNUPLOT point to the gnuplot installation root directory?
107             p = findExecutable(path + "/bin", false, false);
108             if (p != null)
109                 return p;
110         }
111         path = System.getenv(PATH_ENV);
112         return findExecutable(path, true, true);
113     }
114
115     private void execute0(Path workingDirectory, Path stdout, Path stderr, String... cmdline) throws IOException {
116         ProcessBuilder builder = new ProcessBuilder(cmdline)
117                 .directory(workingDirectory.toFile());
118
119         if (stdout != null)
120             builder.redirectOutput(stdout.toFile());
121         if (stderr != null)
122             builder.redirectError(stderr.toFile());
123
124         Process process = builder.start();
125         Thread stdoutDumper = stdout == null ? new Thread(new InputStreamToFileCopier(process.getInputStream(), null)) : null;
126         Thread stderrDumper = stderr == null ? new Thread(new InputStreamToFileCopier(process.getErrorStream(), null)) : null;
127         if (stdoutDumper != null)
128             stdoutDumper.start();
129         if (stderrDumper != null)
130             stderrDumper.start();
131
132         process.getOutputStream().close();
133         try {
134             if (stdoutDumper != null)
135                 stdoutDumper.join();
136             if (stderrDumper != null)
137                 stderrDumper.join();
138             process.waitFor();
139         } catch (InterruptedException e) {
140             throw new IOException(e);
141         }
142     }
143
144     public void execute(Path workingDirectory, Path stdout, Path stderr, boolean redirectStderr, InputStream input, String charset) throws IOException {
145         try (GnuplotSession session = newSession(workingDirectory, stdout, stderr, redirectStderr)) {
146             session.evaluateStream(input, charset);
147         }
148     }
149
150     public void execute(Path workingDirectory, Path stdout, Path stderr, Path script) throws IOException {
151         execute0(workingDirectory, stdout, stderr, executable.toString(), "-c", script.toString());
152     }
153
154     public void execute(Path workingDirectory, Path stdout, Path stderr, String... commands) throws IOException {
155         StringBuilder e = new StringBuilder().append('"');
156         boolean first = true;
157         for (String cmd : commands) {
158             if (!first)
159                 e.append("; ");
160             first = false;
161             e.append(cmd);
162         }
163         e.append('"');
164         execute0(workingDirectory, stdout, stderr, executable.toString(), "-e", e.toString());
165     }
166
167     private ProcessBuilder buildSessionProcess(Path workingDirectory, Path stdout, Path stderr, boolean redirectErrorStream) {
168         ProcessBuilder builder = new ProcessBuilder(executable.toString())
169                 .directory(workingDirectory != null ? workingDirectory.toFile() : null)
170                 .redirectErrorStream(redirectErrorStream);
171         if (stdout != null)
172             builder.redirectOutput(stdout.toFile());
173         if (stderr != null)
174             builder.redirectError(stderr.toFile());
175         return builder;
176     }
177
178     public GnuplotSession newSession(Path workingDirectory, Path stdout) throws IOException {
179         return newSession(workingDirectory, stdout, null, true);
180     }
181
182     public GnuplotSession newSession(Path workingDirectory, Path stdout, Path stderr, boolean redirectStderr) throws IOException {
183         return new GnuplotSession(workingDirectory, stdout == null, stderr == null,
184                 buildSessionProcess(workingDirectory, stdout, stderr, redirectStderr).start());
185     }
186
187     static enum OSType {
188         APPLE, LINUX, SUN, WINDOWS, UNKNOWN;
189
190         public static OSType calculate() {
191             String osName = System.getProperty("os.name");
192             assert osName != null;
193             osName = osName.toLowerCase();
194             if (osName.startsWith("mac os x"))
195                 return APPLE;
196             if (osName.startsWith("windows"))
197                 return WINDOWS;
198             if (osName.startsWith("linux"))
199                 return LINUX;
200             if (osName.startsWith("sun"))
201                 return SUN;
202             return UNKNOWN;
203         }
204     }
205
206 }