1 package org.objectweb.celtix.common.commands; 2 3 import java.io.*; 4 import java.util.StringTokenizer ; 5 import java.util.logging.Level ; 6 import java.util.logging.Logger ; 7 8 import org.objectweb.celtix.common.i18n.Message; 9 10 11 public class ForkedCommand extends Thread { 12 public static final String EXE_SUFFIX; 13 public static final int DEFAULT_TIMEOUT = 0; 14 private static final Logger LOG = Logger.getLogger(ForkedCommand.class.getName()); 15 private String [] arguments; 16 private String [] environment; 17 private PrintStream outputStream; 18 private PrintStream errorStream; 19 private java.lang.Process proc; 20 private boolean completed; 21 private boolean killed; 22 private boolean joinErrOut = true; 23 24 static { 25 if (System.getProperty("os.name").startsWith("Windows")) { 26 EXE_SUFFIX = ".exe"; 27 } else { 28 EXE_SUFFIX = ""; 29 } 30 } 31 public ForkedCommand() { 32 } 33 34 public ForkedCommand(String [] args) { 35 arguments = args; 36 } 37 38 protected void setArgs(String [] args) { 39 arguments = args; 40 } 41 42 public void setEnvironment(String [] env) { 43 environment = env; 44 } 45 46 public String toString() { 47 if (null == arguments) { 48 return null; 49 } 50 StringBuffer buf = new StringBuffer (); 51 for (int i = 0; i < arguments.length; i++) { 52 if (i > 0) { 53 buf.append(" "); 54 } 55 boolean quotesNeeded = false; 56 if (arguments[i] != null) { 57 StringTokenizer st = new StringTokenizer (arguments[i]); 58 quotesNeeded = st.countTokens() > 1; 59 } 60 if (quotesNeeded) { 61 buf.append("\""); 62 } 63 buf.append(arguments[i]); 64 if (quotesNeeded) { 65 buf.append("\""); 66 } 67 } 68 return buf.length() > 0 ? buf.toString() : ""; 69 } 70 71 77 public void joinErrOut(boolean flag) { 78 this.joinErrOut = flag; 79 } 80 81 public int execute() { 82 return execute(DEFAULT_TIMEOUT); 83 } 84 85 93 public int execute(int timeout) { 94 if (null == arguments || arguments.length == 0) { 95 throw new ForkedCommandException(new Message("NO_ARGUMENTS_EXC", LOG)); 96 } 97 if (LOG.isLoggable(Level.FINE)) { 98 LOG.fine("Executing command: " + this); 99 } 100 try { 101 Runtime rt = Runtime.getRuntime(); 102 if (environment == null) { 103 proc = rt.exec(arguments); 104 } else { 105 StringBuffer msg = null; 106 if (LOG.isLoggable(Level.FINE)) { 107 msg = new StringBuffer (); 108 msg.append("Process environment: "); 109 110 for (int i = 0; i < environment.length; i++) { 111 msg.append(environment[i]); 112 msg.append(" "); 113 } 114 LOG.fine(msg.toString()); 115 } 116 117 proc = rt.exec(arguments, environment); 118 } 119 } catch (IOException ex) { 120 throw new ForkedCommandException(new Message("EXECUTE_EXC", LOG, this), ex); 121 } 122 123 ForkedCommandStreamHandler cmdOut = new ForkedCommandStreamHandler(proc.getInputStream(), 125 outputStream == null 126 ? System.out : outputStream); 127 ForkedCommandStreamHandler cmdErr = new ForkedCommandStreamHandler(proc.getErrorStream(), 128 errorStream == null 129 ? System.err : errorStream); 130 cmdErr.start(); 131 cmdOut.start(); 132 133 start(); 135 136 try { 138 if (timeout > 0) { 139 if (LOG.isLoggable(Level.FINE)) { 140 LOG.fine("Waiting " + timeout + " seconds for process to complete"); 141 } 142 join(timeout * 1000); 143 } else { 144 if (LOG.isLoggable(Level.FINE)) { 145 LOG.fine("Waiting for process to complete"); 146 } 147 join(); 148 } 149 } catch (InterruptedException ex) { 150 ex.printStackTrace(); 151 } finally { 152 if (completed) { 153 if (LOG.isLoggable(Level.FINE)) { 154 LOG.fine("Process completed in time"); 155 } 156 } else { 157 proc.destroy(); 158 killed = true; 159 LOG.fine("Process timed out and was killed"); 160 } 161 162 if (joinErrOut) { 164 if (LOG.isLoggable(Level.FINE)) { 165 LOG.info("Waiting a further 10 seconds for process " 166 + " stdout/stderr streams to be flushed"); 167 } 168 try { 169 cmdErr.join(10 * 1000); 170 cmdOut.join(10 * 1000); 171 } catch (InterruptedException ex) { 172 } 174 } 175 } 176 177 if (killed) { 178 throw new ForkedCommandException(new Message("TIMEOUT_EXC", LOG, timeout)); 179 } 180 int exitVal = proc.exitValue(); 181 if (LOG.isLoggable(Level.FINE)) { 182 LOG.fine("Process exited with value: " + exitVal); 183 } 184 185 return exitVal; 186 } 187 188 192 public void run() { 193 try { 194 proc.waitFor(); 195 completed = true; 196 } catch (InterruptedException ex) { 197 ex.printStackTrace(); 199 } 200 } 201 202 public void setOutputStream(PrintStream os) { 203 outputStream = os; 204 } 205 206 public void setErrorStream(PrintStream es) { 207 errorStream = es; 208 } 209 } 210 211 class ForkedCommandStreamHandler extends Thread { 212 213 private final InputStream is; 214 private final PrintStream ps; 215 216 ForkedCommandStreamHandler(InputStream i, PrintStream p) { 217 is = i; 218 ps = p; 219 } 220 221 public void run() { 222 try { 223 InputStreamReader isr = new InputStreamReader(is); 224 BufferedReader br = new BufferedReader(isr); 225 String line = br.readLine(); 226 while (line != null) { 227 ps.println(line); 228 line = br.readLine(); 229 } 230 } catch (IOException ioe) { 231 } 233 } 234 } 235 | Popular Tags |