1 package org.oddjob.jobs; 2 3 4 import java.io.BufferedInputStream ; 5 import java.io.File ; 6 import java.io.IOException ; 7 import java.io.InputStream ; 8 import java.io.ObjectInputStream ; 9 import java.io.ObjectOutputStream ; 10 import java.io.OutputStream ; 11 import java.util.Vector ; 12 13 import org.oddjob.Stoppable; 14 import org.oddjob.framework.SimpleJob; 15 import org.oddjob.logging.ConsoleArchive; 16 import org.oddjob.logging.ConsoleArchiveImpl; 17 import org.oddjob.logging.LogArchive; 18 import org.oddjob.logging.LogLevel; 19 import org.oddjob.logging.LoggingOutputStream; 20 import org.oddjob.util.IO; 21 import org.oddjob.util.OddjobConfigException; 22 23 78 public class ExecJob extends SimpleJob implements Stoppable, ConsoleArchive { 79 80 private transient ConsoleArchiveImpl consoleArchiver; 81 82 85 public ExecJob() { 86 completeConstruction(); 87 } 88 89 92 private void completeConstruction() { 93 consoleArchiver = new ConsoleArchiveImpl(); 94 } 95 96 101 private File dir; 102 103 109 private String command; 110 111 116 private String [] args; 117 118 125 private final Vector envs = new Vector (); 126 127 133 private InputStream stdin; 134 135 141 private OutputStream stdout; 142 143 149 private OutputStream stderr; 150 151 154 private volatile Process proc; 155 156 private volatile Thread thread; 157 158 163 public void setArgs(String [] args) { 164 this.args = args; 165 } 166 167 172 public void setCommand(String command) { 173 this.command = command; 174 } 175 176 181 public String getCommand() { 182 return command; 183 } 184 185 190 public void setDir(File dir) { 191 this.dir = dir; 192 } 193 194 199 public void setEnvironment(String name, String value) { 200 this.envs.add(name + "=" + value); 201 } 202 203 209 public void setStdin(InputStream stdin) { 210 this.stdin = stdin; 211 } 212 213 219 public InputStream getStdin() { 220 return stdin; 221 } 222 223 229 public void setStdout(OutputStream stdout) { 230 this.stdout = stdout; 231 } 232 233 239 public OutputStream getStdout() { 240 return stdout; 241 } 242 243 249 public void setStderr(OutputStream stderr) { 250 this.stderr = stderr; 251 } 252 253 259 public OutputStream getStderr() { 260 return stderr; 261 } 262 263 267 protected int execute() throws Exception { 268 String envp[] = (String [])envs.toArray(new String [0]); 269 270 if (envp.length == 0) { 271 envp = null; 272 } 273 274 Runtime rt = Runtime.getRuntime(); 275 if (args == null || args.length == 0) { 276 if (command == null) { 277 throw new OddjobConfigException("No command given."); 278 } 279 proc = rt.exec(command, envp, dir); 280 } 281 else { 282 proc = rt.exec(args, envp, dir); 283 } 284 285 final InputStream es = proc.getErrorStream(); 286 final InputStream is = proc.getInputStream(); 287 288 Thread outT = new Thread (new Runnable () { 289 public void run() { 290 try { 291 BufferedInputStream bis = new BufferedInputStream (is); 292 OutputStream os = new LoggingOutputStream(stdout, LogLevel.INFO, 293 consoleArchiver.consoleLog()); 294 IO.copy(bis, os); 295 os.close(); 296 } catch (IOException e) { 297 logger().error("Failed copying stream.", e); 298 } 299 } 300 }); 301 302 Thread errT = new Thread (new Runnable () { 303 304 public void run() { 305 try { 306 BufferedInputStream bis = new BufferedInputStream (es); 307 OutputStream os = new LoggingOutputStream(stderr, LogLevel.ERROR, 308 consoleArchiver.consoleLog()); 309 IO.copy(bis, os); 310 os.close(); 311 } catch (IOException e) { 312 logger().error("Failed copying stream.", e); 313 } 314 } 315 }); 316 317 outT.start(); 318 errT.start(); 319 320 if (stdin != null) { 322 OutputStream os = proc.getOutputStream(); 323 IO.copy(stdin, os); 324 os.close(); 325 } 326 327 thread = Thread.currentThread(); 328 try { 329 proc.waitFor(); 330 331 outT.join(); 332 errT.join(); 333 334 if (proc == null) { 335 return 1; 337 } 338 else { 339 return proc.exitValue(); 340 } 341 } 342 finally { 343 thread = null; 344 synchronized (this) { 345 notifyAll(); 347 } 348 } 349 } 350 351 355 public void onStop() { 356 if (proc != null) { 357 proc.destroy(); 358 proc = null; 359 } 360 for (int i = 0; i < 3 && thread != null; ++i) { 361 synchronized (this) { 362 try { 363 logger().debug("Waiting for process to die."); 364 wait(1000); 365 } 366 catch (InterruptedException e) { 367 return; 368 } 369 } 370 } 371 if (thread != null) { 372 logger().warn("Process failed to die - needs to be manually killed."); 373 thread.interrupt(); 374 } 375 } 376 377 380 public File getDir() { 381 return dir; 382 } 383 384 385 public LogArchive consoleLog() { 386 return consoleArchiver.consoleLog(); 387 } 388 389 392 private void writeObject(ObjectOutputStream s) 393 throws IOException { 394 s.defaultWriteObject(); 395 } 396 397 400 private void readObject(ObjectInputStream s) 401 throws IOException , ClassNotFoundException { 402 s.defaultReadObject(); 403 completeConstruction(); 404 } 405 406 } 407 | Popular Tags |