diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/framework/exec/DefaultExecManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/framework/exec/DefaultExecManager.java new file mode 100644 index 000000000..4269e7469 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/framework/exec/DefaultExecManager.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. + * + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE.txt file. + */ +package org.apache.myrmidon.framework.exec; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Locale; +import org.apache.avalon.excalibur.io.FileUtil; +import org.apache.myrmidon.framework.Os; +import org.apache.myrmidon.framework.exec.launchers.DefaultCommandLauncher; +import org.apache.myrmidon.framework.exec.launchers.MacCommandLauncher; +import org.apache.myrmidon.framework.exec.launchers.ScriptCommandLauncher; +import org.apache.myrmidon.framework.exec.launchers.WinNTCommandLauncher; + +/** + * Default implementation of ExecManager. + * Used to run processes in the ant environment. + * + * @author Peter Donald + * @version $Revision$ $Date$ + * @author Thomas Haas + * @see ExecManager + * @see ExecMetaData + */ +public class DefaultExecManager + implements ExecManager +{ + /** + * Used to destroy processes when the VM exits. + */ + private final ProcessDestroyer m_processDestroyer = new ProcessDestroyer(); + + private final CommandLauncher m_launcher; + private final CommandLauncher m_shellLauncher; + + public DefaultExecManager( final File antDir ) + throws ExecException + { + m_launcher = new DefaultCommandLauncher(); + m_shellLauncher = createShellLauncher( antDir ); + } + + /** + * Execute a process and wait for it to finish before + * returning. + */ + public int execute( final ExecMetaData metaData, + final InputStream input, + final OutputStream output, + final OutputStream error, + final long timeout ) + throws IOException, ExecException + { + final CommandLauncher launcher = getLauncher( metaData ); + final Process process = launcher.exec( metaData ); + final ProcessMonitor monitor = + new ProcessMonitor( process, input, output, error, timeout ); + + final Thread thread = new Thread( monitor, "ProcessMonitor" ); + thread.start(); + + // add the process to the list of those to destroy if the VM exits + m_processDestroyer.add( process ); + + waitFor( process ); + + //Now wait for monitor to finish aswell + try { thread.join(); } + catch( InterruptedException e ) + { + //should never occur. + } + + // remove the process to the list of those to destroy if the VM exits + m_processDestroyer.remove( process ); + + if( monitor.didProcessTimeout() ) + { + throw new ExecException( "Process Timed out" ); + } + + return process.exitValue(); + } + + private void waitFor( final Process process ) + { + //Should loop around until process is terminated. + try + { + process.waitFor(); + } + catch( final InterruptedException ie ) + { + //should never happen + } + } + + private CommandLauncher getLauncher( final ExecMetaData metaData ) + { + CommandLauncher launcher = m_launcher; + if( false ) //!m_useVMLauncher ) + { + launcher = m_shellLauncher; + } + return launcher; + } + + private CommandLauncher createShellLauncher( final File antDir ) + throws ExecException + { + CommandLauncher launcher = null; + + if( Os.isFamily( "mac" ) ) + { + // Mac + launcher = new MacCommandLauncher(); + } + else if( Os.isFamily( "os/2" ) ) + { + // OS/2 - use same mechanism as Windows 2000 + launcher = new WinNTCommandLauncher(); + } + else if( Os.isFamily( "windows" ) ) + { + // Windows. Need to determine which JDK we're running in + + // Determine if we're running under 2000/NT or 98/95 + final String osname = + System.getProperty( "os.name" ).toLowerCase( Locale.US ); + + if( osname.indexOf( "nt" ) >= 0 || osname.indexOf( "2000" ) >= 0 ) + { + // Windows 2000/NT + launcher = new WinNTCommandLauncher(); + } + else + { + // Windows 98/95 - need to use an auxiliary script + final String script = resolveCommand( antDir, "bin/antRun.bat" ); + launcher = new ScriptCommandLauncher( script ); + } + } + else if( ( new Os( "netware" ) ).eval() ) + { + // NetWare. Need to determine which JDK we're running in + final String perlScript = resolveCommand( antDir, "bin/antRun.pl" ); + final String[] script = new String[]{"perl", perlScript}; + launcher = new ScriptCommandLauncher( script ); + } + else + { + // Generic + final String script = resolveCommand( antDir, "bin/antRun" ); + launcher = new ScriptCommandLauncher( script ); + } + + return launcher; + } + + private String resolveCommand( final File antDir, final String command ) + { + return FileUtil.resolveFile( antDir, command ).toString(); + } +}