Command: make reliance on system default encoding for reading streams explicit.
[cfb.git] / prod / net / jaekl / cfb / util / Command.java
1 package net.jaekl.cfb.util;
2
3 // Copyright (C) 2015 Christian Jaekl
4
5 import java.io.BufferedReader;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.InputStreamReader;
9 import java.nio.charset.Charset;
10 import java.nio.charset.IllegalCharsetNameException;
11 import java.nio.charset.UnsupportedCharsetException;
12
13 public class Command {
14         public static final String UTF_8 = "UTF-8";
15         private Charset m_charset;
16         
17         public static class Result
18         {
19                 private int m_retCode;
20                 private String m_stdout;
21                 private String m_stderr;
22                 
23                 Result(int retCode, String stdout, String stderr) {
24                         m_retCode = retCode;
25                         m_stdout = stdout;
26                         m_stderr = stderr;
27                 }
28                 
29                 public int getRetCode() { return m_retCode; }
30                 public String getStdout() { return m_stdout; }
31                 public String getStderr() { return m_stderr; }
32         }
33         
34         private class StreamGobbler extends Thread {
35                 
36                 private StringBuilder m_sb;
37                 private BufferedReader m_br;
38                 
39                 public StreamGobbler(InputStream is) {
40                         m_sb = new StringBuilder();
41                         m_br = new BufferedReader(new InputStreamReader(is, m_charset));
42                 }
43                 
44                 @Override
45                 public void run() {
46                         String line;
47                         try {
48                                 line = m_br.readLine();
49                                 while (null != line) {
50                                         m_sb.append(line).append(System.lineSeparator());
51                                         line = m_br.readLine();
52                                 }
53                         } catch (IOException exc) {
54                                 m_sb.append(Util.stringify(exc));
55                         }
56                         finally {
57                                 try {
58                                         m_br.close();
59                                 } catch (IOException exc) {
60                                         m_sb.append(Util.stringify(exc));
61                                 }
62                         }
63                 }
64                 
65                 public String getOutput() { return m_sb.toString(); }
66         }
67         
68         public Command() 
69         {
70                 try {
71                         m_charset = Charset.forName(System.getProperty("file.encoding", UTF_8));
72                 }
73                 catch (IllegalCharsetNameException | UnsupportedCharsetException exc) {
74                         m_charset = Charset.forName(UTF_8);
75                 }
76         }
77         
78         public Result exec(String cmd) throws IOException 
79         {
80                 int retCode = 0;
81                 String stdout = "";
82                 String stderr = "";
83                 
84                 Process proc = doRuntimeExec(cmd);
85                 assert( null != proc );
86                 
87                 StreamGobbler stdoutGobbler = new StreamGobbler(proc.getInputStream());
88                 StreamGobbler stderrGobbler = new StreamGobbler(proc.getErrorStream());
89                 
90                 stdoutGobbler.start();
91                 stderrGobbler.start();
92                 
93                 try {
94                         retCode = proc.waitFor();
95                         stdoutGobbler.join();
96                         stderrGobbler.join();
97                         
98                         stdout = stdoutGobbler.getOutput();
99                         stderr = stdoutGobbler.getOutput();
100                         
101                 } catch (InterruptedException exc) {
102                         stderr += Util.stringify(exc);
103                 }
104                 
105                 return new Result(retCode, stdout, stderr);
106         }
107         
108         Process doRuntimeExec(String cmd) throws IOException {
109                 return Runtime.getRuntime().exec(cmd);
110         }
111 }