/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.oodt.commons;

import java.io.*;
import java.util.*;

/** An executable object.
 *
 * Objects of this class are programs that can be executed asynchronously.  Their standard
 * output and standard error streams are shared with the parent process' standard output
 * and error streams.
 *
 * @author Kelly
 */
public abstract class Executable {
	/** Construct an executable.
	 */
	public Executable() {}

	/** Get the command-line.
	 *
	 * @return Command-line.
	 */
	protected abstract String[] getCommandLine();

	/** Start executing this program.
	 *
	 * If any error occurs while launching the program, this method notes a message to
	 * stderr, but otherwise takes no further action.
	 */
	public void execute() {
		// We force program execution to be asynchronous by cutting a new thread.
		new Thread() {
			public void run() {
				try {
					process = Runtime.getRuntime().exec(getCommandLine());
					
					// Read all output (standard and error output)
					// from the process and pass it to the user.
					redirect(process.getErrorStream(), System.err);
					redirect(process.getInputStream(), System.out);
				} catch (IOException ex) {
					System.err.println("Can't execute command \"" + getCommandLine()[0] + "\": "
						+ ex.getMessage());
				}
			}

			/** Redirect the given input onto the given output.
			 *
			 * @param in The stream to read.
			 * @param out Where to write it.
			 */
			private void redirect(final InputStream in, final OutputStream out) {
				// Do this in the background, too.
				new Thread() {
					public void run() {
						try {
							byte[] buf = new byte[1024];
							for (;;) {
								int numRead = in.read(buf);
								if (numRead == -1) {
									in.close();
									break;
								}
								out.write(buf, 0, numRead);
							}
						} catch (IOException ex) {
							try {
								in.close();
							} catch (IOException ignore) {}
						}
					}
				}.start();
			}
		}.start();

		// Spin until the process field is set.
		while (process == null)
			Thread.yield();
	}

	/** Wait for the process to terminate.
	 *
	 * @throws InterruptedException If the thread waiting for the termination is interrupted.
	 * @return The exit value of the process.
	 */
	public int waitFor() throws InterruptedException {
		return process.waitFor();
	}

	/** Terminate this process.
	 */
	public void terminate() {
		process.destroy();
	}

	/** The process backing this executable. */
	protected Process process;

}
