// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.enterprise.adaptor.prebuilt;

import com.google.enterprise.adaptor.IOHelper;

import java.io.*;

/**
 * Exec helper that allows easy handling of stdin, stdout, and stderr. Normally
 * you have to worry about deadlock when dealing with those streams (as
 * mentioned briefly in {@link Process}), so this class handles that for you.
 * This class is very similar to {@link Command}, except it allows streaming
 * stdin, stdout, and stderr, instead of buffering them.
 */
public class StreamingCommand {
  private static final InputSource NO_INPUT_SOURCE = new NoInputSource();
  private static final OutputSink DROP_OUTPUT_SINK = new DropOutputSink();

  // Prevent instantiation.
  private StreamingCommand() {}

  /**
   * Same as {@code exec(command, null, stdin, stdout, stderr)}.
   *
   * @see #exec(String[], File, InputSource, OutputSink, OutputSink)
   */
  public static int exec(String[] command, InputSource stdin, OutputSink stdout,
      OutputSink stderr) throws IOException, InterruptedException {
    return exec(command, null, stdin, stdout, stderr);
  }

  /**
   * Create process {@code command} starting in the {@code workingDir} and
   * providing {@code stdin} as input. This method blocks until the process
   * exits. Stdout and stderr must be consumed via the {@link OutputSink}s. If
   * {@code stdin}, {@code stdout}, or {@code stderr} is {@code null}, then a
   * bare implemention will be used.
   *
   * @return Process return code
   * @throws IOException if creating process fails
   */
  public static int exec(String[] command, File workingDir, InputSource stdin,
      OutputSink stdout, OutputSink stderr)
      throws IOException, InterruptedException {
    if (stdin == null) {
      stdin = NO_INPUT_SOURCE;
    }
    if (stdout == null) {
      stdout = DROP_OUTPUT_SINK;
    }
    if (stderr == null) {
      stderr = DROP_OUTPUT_SINK;
    }

    Process proc = Runtime.getRuntime().exec(command, null, workingDir);
    Thread in, out, err;
    in = new Thread(new InputSourceRunnable(stdin, proc.getOutputStream()));
    in.setDaemon(true);
    in.start();

    out = new Thread(new OutputSinkRunnable(proc.getInputStream(), stdout));
    out.setDaemon(true);
    out.start();

    err = new Thread(new OutputSinkRunnable(proc.getErrorStream(), stderr));
    err.setDaemon(true);
    err.start();

    int returnCode;
    try {
      in.join();
      out.join();
      err.join();

      returnCode = proc.waitFor();
    } catch (InterruptedException ex) {
      // Our threads should stop once the process closes.
      // This destroy() is quite rude to the subprocess, but there is not any
      // way to inform it to abort.
      proc.destroy();
      throw ex;
    }

    return returnCode;
  }

  /**
   * {@link InputStream} to {@link InputSource} adaptor.
   */
  public static InputSource streamInputSource(InputStream in) {
    return new StreamInputSource(in);
  }

  /**
   * {@link OutputStream} to {@link OutputSink} adaptor.
   */
  public static OutputSink streamOutputSink(OutputStream out) {
    return new StreamOutputSink(out);
  }

  private static void silentClose(Closeable closeable) {
    try {
      closeable.close();
    } catch (IOException ex) {
      // ignore
    }
  }

  /**
   * Content source that generates content at the rate it can be consumed.
   */
  public static interface InputSource {
    /**
     * Generate content and write it to {@code out}.
     */
    public void source(OutputStream out) throws IOException;
  }

  /**
   * Content sink that consumes content as soon as it becomes available.
   */
  public static interface OutputSink {
    /**
     * Consume content from {@code in}.
     */
    public void sink(InputStream in) throws IOException;
  }

  private static class NoInputSource implements InputSource {
    public void source(OutputStream out) {
      // Don't write anything out.
    }
  }

  private static class DropOutputSink implements OutputSink {
    public void sink(InputStream in) throws IOException {
      byte[] buffer = new byte[1024];
      while (in.read(buffer) != -1) {
        // Do nothing with input.
      }
    }
  }

  private static class StreamInputSource implements InputSource {
    private final InputStream in;

    public StreamInputSource(InputStream in) {
      this.in = in;
    }

    @Override
    public void source(OutputStream out) throws IOException {
      IOHelper.copyStream(in, out);
    }
  }

  private static class StreamOutputSink implements OutputSink {
    private final OutputStream out;

    public StreamOutputSink(OutputStream out) {
      this.out = out;
    }

    @Override
    public void sink(InputStream in) throws IOException {
      IOHelper.copyStream(in, out);
    }
  }

  private static class InputSourceRunnable implements Runnable {
    private final InputSource source;
    private final OutputStream out;

    public InputSourceRunnable(InputSource source, OutputStream out) {
      this.source = source;
      this.out = out;
    }

    @Override
    public void run() {
      try {
        source.source(out);
      } catch (IOException ex) {
        // Ignore, but stop thread.
      } finally {
        silentClose(out);
      }
    }
  }

  private static class OutputSinkRunnable implements Runnable {
    private final InputStream in;
    private final OutputSink sink;

    public OutputSinkRunnable(InputStream in, OutputSink sink) {
      this.in = in;
      this.sink = sink;
    }

    @Override
    public void run() {
      try {
        sink.sink(in);
      } catch (IOException ex) {
        // Ignore, but stop thread.
      } finally {
        silentClose(in);
      }
    }
  }
}
