/*
* Created on May 4, 2006
*/
package com.openedit.util;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.openedit.OpenEditException;
public class AltExec
{
private static final Log log = LogFactory.getLog(AltExec.class);
protected String fieldErrorOutput;
protected String fieldStandardOutput;
protected int timelimit; // an optional timelimit on the exececution time
protected boolean fieldTimeLimited = false;// set a time limit for this process to complete
public int getTimelimit()
{
return timelimit;
}
public void setTimelimit(int inTimelimit)
{
setTimeLimited( inTimelimit > 0 );
timelimit = inTimelimit;
}
public boolean isTimeLimited()
{
return fieldTimeLimited;
}
public void setTimeLimited(boolean inTimeLimited)
{
fieldTimeLimited = inTimeLimited;
}
public boolean runExec(List args) throws OpenEditException
{
setErrorOutput(null);
setStandardOutput(null);
long start = System.currentTimeMillis();
final ProcessContainer container = new ProcessContainer();
container.setCommands( args );
try
{
log.info("Running: " + args);
Thread execThread = container.getThread();
if( isTimeLimited() )
{
// wait for notification from the execThread
Thread timerThread = createTimerThread( container );
timerThread.start();
execThread.start();
synchronized ( container )
{
container.wait();
}
}
else
{
execThread.start();
execThread.join();
}
}
catch (Exception ex)
{
throw new OpenEditException(ex);
}
setStandardOutput( container.getStandardOut() );
setErrorOutput( container.getErrors() );
long duration = System.currentTimeMillis() - start;
log.info( "Exec process " + args + " exiting with return code " + container.getReturnCode() + " in " + duration + "ms" );
return container.getReturnCode() == 0;
}
protected Thread createTimerThread( final ProcessContainer container )
{
Thread timerThread = new Thread( new Runnable( )
{
public void run()
{
boolean timedOut = false;
int count = 0;
try
{
log.info( "Starting " + getTimelimit() + "ms process timer..." );
// Neat... if the increment is too small (<10ms), the timer
// accuracy suffers because this thread does not permit the process
// thread time to execute.
int increment = 100;
while ( !container.isFinished() && count < getTimelimit() )
{
count = count + increment;
Thread.sleep( increment );
}
timedOut = count >= getTimelimit();
}
catch ( InterruptedException e )
{
log.error( e );
}
finally
{
if ( timedOut )
{
log.info( "Process timed out, terminating... " );
}
container.terminate();
synchronized ( container )
{
container.notify();
}
if ( !timedOut )
{
log.info( "Exiting timer thread in " + count + "ms" );
}
}
}
} );
return timerThread;
}
public String getErrorOutput()
{
return fieldErrorOutput;
}
public void setErrorOutput(String inErrorOutput)
{
fieldErrorOutput = inErrorOutput;
}
public String getStandardOutput()
{
return fieldStandardOutput;
}
public void setStandardOutput(String inStandardOutput)
{
fieldStandardOutput = inStandardOutput;
}
}