1 package org.antmod.util; 2 3 import java.io.*; 4 import java.util.ArrayList ; 5 import java.util.Iterator ; 6 import java.util.logging.Level ; 7 import java.util.logging.Logger ; 8 9 15 public final class ProcessLauncher { 16 17 private final static Logger LOGGER = Logger.getLogger(ProcessLauncher.class.getName()); 18 19 private String commandLine; 20 private String [] commandArray; 21 private File baseDir; 22 23 private ArrayList listeners = new ArrayList (1); 24 25 private Process subProcess; 26 private boolean finished = false; 27 28 StringBuffer out = new StringBuffer (); 29 StringBuffer err = new StringBuffer (); 30 31 34 public ProcessLauncher(String commandLine) { 35 this(commandLine, null); 36 } 37 public ProcessLauncher(String commandLine, File baseDir) { 38 this.commandLine = commandLine; 39 this.baseDir = baseDir; 40 } 41 42 45 public ProcessLauncher(String [] commandArray) { 46 this(commandArray, null); 47 } 48 public ProcessLauncher(String [] commandArray, File baseDir) { 49 this.commandArray = commandArray; 50 this.baseDir = baseDir; 51 } 52 53 56 public ProcessLauncher(ArrayList commandList) { 57 this(commandList, null); 58 } 59 public ProcessLauncher(ArrayList commandList, File baseDir) { 60 this(toStringArray(commandList), baseDir); 61 } 62 63 private static String [] toStringArray(ArrayList list) { 64 String [] result = new String [list.size()]; 65 Iterator iter = list.iterator(); 66 int arrayIndex = 0; 67 while (iter.hasNext()) { 68 result[arrayIndex++] = iter.next().toString(); 69 } 70 return result; 71 } 72 73 77 public interface OutputListener { 78 public void standardOutput(char[] output); 79 80 public void errorOutput(char[] output); 81 } 82 83 86 public void addOutputListener(OutputListener listener) { 87 this.listeners.add(listener); 88 } 89 90 91 private void fireErr(char[] err) { 92 if (this.listeners.isEmpty()) { 93 this.err.append(out); 94 } 95 96 Iterator iter = this.listeners.iterator(); 97 while (iter.hasNext()) { 98 ((OutputListener)iter.next()).errorOutput(err); 99 } 100 } 101 102 103 private void fireOut(char[] out) { 104 if (this.listeners.isEmpty()) { 105 this.out.append(out); 106 } 107 108 Iterator iter = this.listeners.iterator(); 109 while (iter.hasNext()) { 110 ((OutputListener)iter.next()).standardOutput(out); 111 } 112 } 113 114 117 public String getStandardOutput() { 118 if (!this.listeners.isEmpty()) { 119 throw new IllegalStateException ("Cannot get standard output, because outputlisteners have been registered."); 120 } 121 return this.out.toString(); 122 } 123 124 127 public String getErrorOutput() { 128 if (!this.listeners.isEmpty()) { 129 throw new IllegalStateException ("Cannot get error output, because outputlisteners have been registered."); 130 } 131 return this.err.toString(); 132 } 133 134 137 public String getCommandLine() { 138 String usedCommand = this.commandLine; 139 if (this.commandLine == null && this.commandArray != null) { 140 usedCommand = ""; 141 for (int i = 0; i < this.commandArray.length; i++) { 142 if (i > 0) { 143 usedCommand += " "; 144 } 145 usedCommand += this.commandArray[i]; 146 } 147 } 148 return usedCommand; 149 } 150 151 154 public boolean hasFinished() { 155 return finished; 156 } 157 158 162 public int launch() throws CommandNotExistsException { 163 this.err.setLength(0); 164 this.out.setLength(0); 165 166 BackgroundPrinter stdout = null; 167 BackgroundPrinter stderr = null; 168 try { 169 if (this.commandArray != null) { 170 this.subProcess = Runtime.getRuntime().exec(this.commandArray, null, this.baseDir); 171 } 172 else { 173 this.subProcess = Runtime.getRuntime().exec(this.commandLine, null, this.baseDir); 174 } 175 176 stdout = new BackgroundPrinter(subProcess.getInputStream(), false); 177 stderr = new BackgroundPrinter(subProcess.getErrorStream(), true); 178 stdout.start(); 179 stderr.start(); 180 181 int exitValue = this.subProcess.waitFor(); 183 stdout.join(10000); 184 stderr.join(10000); 185 186 191 192 return exitValue; 193 } 194 catch (IOException ioe) { 195 throw new CommandNotExistsException("Command probably does not exist: " + ioe); 197 } 198 catch (Exception e) { 199 LOGGER.log(Level.SEVERE, "Exception while running/launching \"" + getCommandLine() + "\".", e); 200 } 201 finally { 202 if (this.subProcess != null) { 203 this.subProcess.destroy(); 204 this.subProcess = null; 205 } 206 if (stdout != null) { 207 stdout.close(); 208 } 209 if (stderr != null) { 210 stderr.close(); 211 } 212 this.finished = true; 213 } 214 return -1; 215 } 216 217 220 public void abort() { 221 if (this.subProcess != null) { 222 this.subProcess.destroy(); 223 this.subProcess = null; 224 } 225 } 226 227 233 private class BackgroundPrinter extends Thread { 234 private InputStream in; 235 boolean isErrorOutput; 236 237 public BackgroundPrinter(InputStream in, boolean isErrorOutput) { 238 this.in = in; 239 this.isErrorOutput = isErrorOutput; 240 } 241 242 public void run() { 243 try { 244 BufferedReader reader = new BufferedReader(new InputStreamReader(this.in)); 245 246 char[] buf = new char[1024]; 248 249 int numberOfReadBytes; 251 while ((numberOfReadBytes = reader.read(buf)) != -1) { 252 char[] clearedbuf = new char[numberOfReadBytes]; 253 System.arraycopy(buf, 0, clearedbuf, 0, numberOfReadBytes); 254 255 if (this.isErrorOutput) { 256 fireErr(clearedbuf); 257 } 258 else { 259 fireOut(clearedbuf); 260 } 261 } 262 267 } 268 catch (Exception e) { 269 LOGGER.log(Level.FINE, "Exception while reading from stream from subprocess.", e); 270 } 271 } 272 273 public void close() { 274 try { 275 this.in.close(); 276 } 277 catch (Exception e) { 278 LOGGER.log(Level.WARNING, "Closing background stream for launched process caused exception.", e); 279 } 280 } 281 } 282 283 288 public static class CommandNotExistsException extends RuntimeException { 289 293 public CommandNotExistsException(String msg) { 294 super(msg); 295 } 296 } 297 } 298 | Popular Tags |