package org.openslx.satserver.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class Exec
{
/**
* Run command, return exit status of process, or -1 on error
*
* @param timeoutSec maximum time in seconds to wait for process to finish
* @param command Command and arguments
* @return exit code
*/
public static int sync( int timeoutSec, ExecCallback callback, String... command )
{
return syncAt( timeoutSec, callback, "/", command );
}
public static int sync( int timeoutSec, String... command )
{
return sync( timeoutSec, null, command );
}
public static int syncAt( int timeoutSec, ExecCallback callback, String cwd, String... command )
{
ProcessBuilder pb = new ProcessBuilder( command );
pb.directory( new File( cwd ) );
Process p = null;
Thread[] list = null;
try {
p = pb.start();
if ( callback != null ) {
list = setupCallback( p, callback );
}
if ( timeoutSec <= 0 ) {
return p.waitFor();
} else {
for ( int i = 0; i < timeoutSec * 10; ++i ) {
Thread.sleep( 100 );
try {
return p.exitValue();
} catch ( IllegalThreadStateException e ) {
// Wait...
}
}
// Timeout
return -1;
}
} catch ( IOException | InterruptedException e ) {
return -2;
} finally {
try {
if ( p != null ) {
Util.multiClose( p.getOutputStream(), p.getErrorStream() );
p.destroy();
}
} catch ( Exception e ) {
//
}
if ( list != null ) {
for ( Thread t : list ) {
try {
t.interrupt();
} catch ( Exception e ) {
//
}
}
}
}
}
public static int syncAt( int timeoutSec, String cwd, String... command )
{
return syncAt( timeoutSec, null, cwd, command );
}
private static Thread[] setupCallback( final Process p, final ExecCallback cb )
{
// Read its stdout
Thread stdout = new Thread( new Runnable() {
@Override
public void run()
{
try {
BufferedReader reader = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
String line;
while ( ( line = reader.readLine() ) != null ) {
synchronized ( p ) {
cb.processStdOut( line );
}
}
} catch ( Exception e ) {
}
}
} );
// Read its stderr
Thread stderr = new Thread( new Runnable() {
@Override
public void run()
{
try {
BufferedReader reader = new BufferedReader( new InputStreamReader( p.getErrorStream() ) );
String line;
while ( ( line = reader.readLine() ) != null ) {
synchronized ( p ) {
cb.processStdErr( line );
}
}
} catch ( Exception e ) {
}
}
} );
stdout.start();
stderr.start();
Thread[] t = new Thread[] { stdout, stderr };
return t;
}
/**/
public interface ExecCallback
{
public void processStdOut( String line );
public void processStdErr( String line );
}
}