blob: dc3940a4af0bbac700c81d9b8bb1d89ec3df9432 [file] [log] [blame]
/*
* 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;
}