001package net.bramp.ffmpeg.io;
002
003import java.util.concurrent.TimeUnit;
004import java.util.concurrent.TimeoutException;
005
006/**
007 * @author bramp
008 */
009public final class ProcessUtils {
010
011  private ProcessUtils() {
012    throw new AssertionError("No instances for you!");
013  }
014
015  private static class ProcessThread extends Thread {
016    final Process p;
017    boolean finished = false;
018    int exitValue = -1;
019
020    private ProcessThread(Process p) {
021      this.p = p;
022    }
023
024    @Override
025    public void run() {
026      try {
027        exitValue = p.waitFor();
028        finished = true;
029      } catch (InterruptedException e) {
030        Thread.currentThread().interrupt();
031      }
032    }
033
034    public boolean hasFinished() {
035      return finished;
036    }
037
038    public int exitValue() {
039      return exitValue;
040    }
041  }
042
043  /**
044   * Waits until a process finishes or a timeout occurs
045   *
046   * @param p process
047   * @param timeout timeout in given unit
048   * @param unit time unit
049   * @return the process exit value
050   * @throws TimeoutException if a timeout occurs
051   */
052  public static int waitForWithTimeout(final Process p, long timeout, TimeUnit unit)
053      throws TimeoutException {
054
055    ProcessThread t = new ProcessThread(p);
056    t.start();
057    try {
058      unit.timedJoin(t, timeout);
059
060    } catch (InterruptedException e) {
061      t.interrupt();
062      Thread.currentThread().interrupt();
063    }
064
065    if (!t.hasFinished()) {
066      throw new TimeoutException("Process did not finish within timeout");
067    }
068
069    return t.exitValue();
070  }
071}