ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dona...@apache.org
Subject cvs commit: jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/launchers DefaultCommandLauncher.java ExecUtil.java MacCommandLauncher.java Resources.properties ScriptCommandLauncher.java WinNTCommandLauncher.java
Date Sat, 12 Jan 2002 04:51:08 GMT
donaldp     02/01/11 20:51:08

  Added:       proposal/myrmidon/src/java/org/apache/aut/nativelib
                        CommandLauncher.java DefaultExecOutputHandler.java
                        Environment.java ExecException.java
                        ExecManager.java ExecMetaData.java
                        ExecOutputHandler.java Os.java
               proposal/myrmidon/src/java/org/apache/aut/nativelib/impl
                        DefaultExecManager.java LogOutputStream.java
                        ProcessDestroyer.java ProcessMonitor.java
               proposal/myrmidon/src/java/org/apache/aut/nativelib/launchers
                        DefaultCommandLauncher.java ExecUtil.java
                        MacCommandLauncher.java Resources.properties
                        ScriptCommandLauncher.java
                        WinNTCommandLauncher.java
  Log:
  Migrate all the ant-independent code for
  
  native execution
  environment loading
  os detection
  
  into a new hierarchy aut.
  
  AUT basically being completely independent of Ant.
  
  Revision  Changes    Path
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/CommandLauncher.java
  
  Index: CommandLauncher.java
  ===================================================================
  /*
   * 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.aut.nativelib;
  
  import java.io.IOException;
  
  /**
   * This is the interface implemented by objects which are capable of
   * lauching a native command. Each different implementation is likely
   * to have a different strategy or be restricted to specific platform.
   *
   * <p>It is expected that the user will get a reference to the
   * <code>CommandLauncher</code> most appropriate for their environment.</p>
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:07 $
   */
  public interface CommandLauncher
  {
      /**
       * Execute the specified native command.
       *
       * @param metaData the native command to execute
       * @return the Process launched by the CommandLauncher
       * @exception IOException is thrown when the native code can not
       *            launch the application for some reason. Usually due
       *            to the command not being fully specified and not in
       *            the PATH env var.
       * @exception ExecException if the command launcher detects that
       *            it can not execute the native command for some reason.
       */
      Process exec( ExecMetaData metaData )
          throws IOException, ExecException;
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/DefaultExecOutputHandler.java
  
  Index: DefaultExecOutputHandler.java
  ===================================================================
  /*
   * 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.aut.nativelib;
  
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  
  /**
   * This class is used to receive notifications of what the native
   * process outputs to standard output and standard error.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:07 $
   */
  public class DefaultExecOutputHandler
      extends AbstractLogEnabled
      implements ExecOutputHandler
  {
      /**
       * Receive notification about the process writing
       * to standard output.
       */
      public void stdout( final String line )
      {
          getLogger().info( line );
      }
  
      /**
       * Receive notification about the process writing
       * to standard error.
       */
      public void stderr( final String line )
      {
          getLogger().warn( line );
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/Environment.java
  
  Index: Environment.java
  ===================================================================
  /*
   * 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.aut.nativelib;
  
  import java.io.BufferedReader;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.StringReader;
  import java.util.Iterator;
  import java.util.Locale;
  import java.util.Properties;
  import org.apache.avalon.excalibur.util.StringUtil;
  import org.apache.myrmidon.api.TaskException;
  import org.apache.tools.ant.taskdefs.exec.Execute;
  
  /**
   * This is the class that can be used to retrieve the environment
   * variables of the native process.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:thomas.haas@softwired-inc.com">Thomas Haas</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:07 $
   */
  public final class Environment
  {
      private static final String[] COMMAND_COM = new String[]{"command.com", "/c", "set"};
      private static final String[] CMD_EXE = new String[]{"cmd", "/c", "set"};
  
      // Alternatively one could use: /bin/sh -c env
      private static final String[] ENV_CMD = new String[]{"/usr/bin/env"};
      private static final String[] ENV_RAW = new String[]{"env"};
  
      private static Properties c_procEnvironment;
  
      /**
       * Private constructor to block instantiation.
       */
      private Environment()
      {
      }
  
      public static void addNativeEnvironment( final Properties environment )
          throws ExecException, IOException
      {
          final Properties nativeEnvironment = getEnvironmentVariables();
          final Iterator nativeKeys = nativeEnvironment.keySet().iterator();
          while( nativeKeys.hasNext() )
          {
              final String key = (String)nativeKeys.next();
              if( environment.contains( key ) )
              {
                  //Skip environment variables that are overidden
                  continue;
              }
  
              final String value = nativeEnvironment.getProperty( key );
              environment.setProperty( key, value );
          }
      }
  
      /**
       * Retrieve a Properties object that contains the list of all
       * native EnvironmentData Variables for the current process.
       */
      public static Properties getNativeEnvironment()
          throws IOException, ExecException
      {
          final Properties properties = new Properties();
          properties.putAll( getEnvironmentVariables() );
          return properties;
      }
  
      /**
       * Get the Property object with all environment variables and
       * attempt to load it if it has not already been loaded.
       */
      private synchronized static Properties getEnvironmentVariables()
          throws IOException, ExecException
      {
          if( null == c_procEnvironment )
          {
              c_procEnvironment = retrieveEnvironmentVariables();
          }
  
          return c_procEnvironment;
      }
  
      /**
       * Retrieve a last of environment variables from the native OS.
       */
      private static synchronized Properties retrieveEnvironmentVariables()
          throws IOException, ExecException
      {
          final String data = getEnvironmentText();
  
          final Properties properties = new Properties();
          final BufferedReader in = new BufferedReader( new StringReader( data ) );
          String var = null;
          String line;
          while( ( line = in.readLine() ) != null )
          {
              if( line.indexOf( '=' ) == -1 )
              {
                  // Chunk part of previous env var (UNIX env vars can
                  // contain embedded new lines).
                  if( var == null )
                  {
                      var = StringUtil.LINE_SEPARATOR + line;
                  }
                  else
                  {
                      var += StringUtil.LINE_SEPARATOR + line;
                  }
              }
              else
              {
                  // New env var...append the previous one if we have it.
                  if( var != null )
                  {
                      addProperty( properties, var );
                  }
                  var = line;
              }
          }
  
          // Since we "look ahead" before adding, there's one last env var.
          if( null != var )
          {
              addProperty( properties, var );
          }
          return properties;
      }
  
      /**
       * Parse the specified data into a key=value pair. If there is no
       * '=' character then generate an exception. After parsed data place
       * the key-value pair into the specified Properties object.
       */
      private static void addProperty( final Properties properties,
                                       final String data )
          throws ExecException
      {
          final int index = data.indexOf( '=' );
          if( -1 == index )
          {
              //Our env variable does not have any = in it.
              final String message = "EnvironmentData variable '" + data +
                  "' does not have a '=' character in it";
              throw new ExecException( message );
          }
          else
          {
              final String key = data.substring( 0, index );
              final String value = data.substring( index + 1 );
              properties.setProperty( key, value );
          }
      }
  
      /**
       * Retrieve the text of data that is the result of
       * running the environment command.
       */
      private static String getEnvironmentText()
          throws IOException, ExecException
      {
          final ByteArrayOutputStream output = new ByteArrayOutputStream();
          final Execute exe = new Execute();
          exe.setOutput( output );
          exe.setError( output );
  
          exe.setCommandline( getEnvCommand() );
  
          // Make sure we do not recurse forever
          exe.setNewenvironment( true );
  
          try
          {
              final int retval = exe.execute();
              if( retval != 0 )
              {
                  // Just try to use what we got
              }
          }
          catch( final TaskException te )
          {
              throw new ExecException( te.getMessage(), te );
          }
  
          return output.toString();
      }
  
      /**
       * Retrieve the command that will display a list of environment
       * variables.
       */
      private static String[] getEnvCommand()
          throws ExecException
      {
          if( Os.isFamily( "os/2" ) )
          {
              // OS/2 - use same mechanism as Windows 2000
              return CMD_EXE;
          }
          else if( Os.isFamily( "windows" ) )
          {
              final String osname =
                  System.getProperty( "os.name" ).toLowerCase( Locale.US );
              // Determine if we're running under 2000/NT or 98/95
              if( osname.indexOf( "nt" ) >= 0 || osname.indexOf( "2000" ) >= 0 )
              {
                  // Windows 2000/NT
                  return CMD_EXE;
              }
              else
              {
                  // Windows 98/95 - need to use an auxiliary script
                  return COMMAND_COM;
              }
          }
          else if( Os.isFamily( "unix" ) )
          {
              // Generic UNIX
              return ENV_CMD;
          }
          else if( Os.isFamily( "netware" ) )
          {
              return ENV_RAW;
          }
          else
          {
              final String message =
                  "Unable to determine native environment variables";
              throw new ExecException( message );
          }
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/ExecException.java
  
  Index: ExecException.java
  ===================================================================
  /*
   * 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.aut.nativelib;
  
  import org.apache.avalon.framework.CascadingException;
  
  /**
   * ExecException indicates there was an error executing native process.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   */
  public class ExecException
      extends CascadingException
  {
      /**
       * Basic constructor for exception that does not specify a message
       */
      public ExecException()
      {
          this( "", null );
      }
  
      /**
       * Basic constructor with a message
       *
       * @param message the message
       */
      public ExecException( final String message )
      {
          this( message, null );
      }
  
      /**
       * Constructor that builds cascade so that other exception information can be retained.
       *
       * @param message the message
       * @param throwable the throwable
       */
      public ExecException( final String message, final Throwable throwable )
      {
          super( message, throwable );
      }
  }
  
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/ExecManager.java
  
  Index: ExecManager.java
  ===================================================================
  /*
   * 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.aut.nativelib;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  
  /**
   * Interface via which clients can request that a native
   * process be executed. This manages all aspects of running
   * a native command including such things as;
   *
   * <ul>
   *   <li>Destroying a process if it times out</li>
   *   <li>Reading data from supplied input stream and
   *       writing it to processes standard input</li>
   *   <li>Reading data from processes standard output
   *       and error streams and writing it to supplied
   *       streams</li>
   * </ul>
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:07 $
   */
  public interface ExecManager
  {
      /**
       * Execute a process and wait for it to finish before
       * returning.
       *
       * @param  execMetaData the metaData for native command to execute
       * @param  input the stream to read from and write to standard input.
       *         May be null in which case nothing will be written to standard.
       *         input
       * @param  output the stream to write the processes standard output to.
       *         May be null in which case that output will go into the void.
       * @param  error the stream to write the processes standard error to.
       *         May be null in which case that error will go into the void.
       * @param  timeout the maximum duration in milliseconds that a process
       *         can execute. The value must be positive or zero. If it is zero
       *         then the process will not timeout. If the process times out it
       *         will be forcibly shutdown and a TimeoutException thrown
       */
      int execute( ExecMetaData execMetaData,
                   InputStream input,
                   OutputStream output,
                   OutputStream error,
                   long timeout )
          throws IOException, ExecException /*TimeoutException*/;
  
      /**
       * Execute a process and wait for it to finish before
       * returning. Note that this version of execute() does not allow you
       * to specify input.
       *
       * @param  execMetaData the metaData for native command to execute
       * @param  handler the handler to which line-orientated output of
       *         process is directed for standard output and standard error
       * @param  timeout the maximum duration in milliseconds that a process
       *         can execute. The value must be positive or zero. If it is zero
       *         then the process will not timeout. If the process times out it
       *         will be forcibly shutdown and a TimeoutException thrown
       */
      int execute( ExecMetaData execMetaData,
                   ExecOutputHandler handler,
                   long timeout )
          throws IOException, ExecException /*TimeoutException*/;
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/ExecMetaData.java
  
  Index: ExecMetaData.java
  ===================================================================
  /*
   * 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.aut.nativelib;
  
  import java.io.File;
  import java.util.Properties;
  
  /**
   * This class holds meta data that is used to launch a native executable.
   * This class should be populated with valid data and passed to the
   * <code>ExecManager</code> and it will be the responsibility of the
   * <code>ExecManager</code> to actually launch the native executable.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:07 $
   */
  public class ExecMetaData
  {
      /**
       * The working directory in which the applicaiton is launched.
       */
      private File m_workingDirectory;
  
      /**
       * The array of strings that make up the command line for the command.
       */
      private String[] m_command;
  
      /**
       * The array of strings that make up the command line for the command.
       * Note that these variables are in the ugly format expected by the
       * Runtime.exec() call. For most systems this means that each entry
       * must be of the form <code>key=value</code>
       *
       * <p>This set of variables is combined with the environment of current
       * process if <code>isEnvironmentAdditive=true</code> else it specifies
       * full environment.
       */
      private Properties m_environment;
  
      /**
       * If this variable is true then then the environment specified is
       * added to the environment variables for current process. If this
       * value is false then the specified environment replaces the environment
       * for the command.
       */
      private boolean m_isEnvironmentAdditive;
  
      /**
       * Construct the meta data for executable as appropriate.
       * Note that it is invalid to specify a <code>null</code>
       * workingDirectory or command. It is also invalid to specify
       * a null environment and an additive environment.
       */
      public ExecMetaData( final String[] command,
                           final Properties environment,
                           final File workingDirectory,
                           final boolean environmentAdditive )
      {
          m_command = command;
          m_environment = environment;
          m_workingDirectory = workingDirectory;
          m_isEnvironmentAdditive = environmentAdditive;
  
          if( null == m_workingDirectory )
          {
              throw new NullPointerException( "workingDirectory" );
          }
  
          if( null == m_command )
          {
              throw new NullPointerException( "command" );
          }
  
          if( null == m_environment && m_isEnvironmentAdditive )
          {
              throw new IllegalArgumentException( "isEnvironmentAdditive" );
          }
      }
  
      public File getWorkingDirectory()
      {
          return m_workingDirectory;
      }
  
      public String[] getCommand()
      {
          return m_command;
      }
  
      public Properties getEnvironment()
      {
          return m_environment;
      }
  
      public boolean isEnvironmentAdditive()
      {
          return m_isEnvironmentAdditive;
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/ExecOutputHandler.java
  
  Index: ExecOutputHandler.java
  ===================================================================
  /*
   * 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.aut.nativelib;
  
  /**
   * This class is used to receive notifications of what the native
   * process outputs to standard output and standard error.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:07 $
   */
  public interface ExecOutputHandler
  {
      /**
       * Receive notification about the process writing
       * to standard output.
       */
      void stdout( String line );
  
      /**
       * Receive notification about the process writing
       * to standard error.
       */
      void stderr( String line );
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/Os.java
  
  Index: Os.java
  ===================================================================
  /*
   * 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.aut.nativelib;
  
  import java.util.Locale;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  
  /**
   * Class to help determining the OS.
   *
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a>
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   */
  public class Os
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( Os.class );
  
      private final static String OS_NAME =
          System.getProperty( "os.name" ).toLowerCase( Locale.US );
      private final static String OS_ARCH =
          System.getProperty( "os.arch" ).toLowerCase( Locale.US );
      private final static String OS_VERSION =
          System.getProperty( "os.version" ).toLowerCase( Locale.US );
      private final static String PATH_SEP =
          System.getProperty( "path.separator" );
  
      /**
       * Private constructor to block instantiation.
       */
      private Os()
      {
      }
  
      /**
       * Determines if the OS on which Ant is executing matches the given OS
       * version.
       */
      public static boolean isVersion( final String version )
      {
          return isOs( null, null, null, version );
      }
  
      /**
       * Determines if the OS on which Ant is executing matches the given OS
       * architecture.
       *
       * @param arch Description of Parameter
       * @return The Arch value
       */
      public static boolean isArch( final String arch )
      {
          return isOs( null, null, arch, null );
      }
  
      /**
       * Determines if the OS on which Ant is executing matches the given OS
       * family.
       *
       * @param family Description of Parameter
       * @return The Family value
       * @since 1.5
       */
      public static boolean isFamily( final String family )
      {
          return isOs( family, null, null, null );
      }
  
      /**
       * Determines if the OS on which Ant is executing matches the given OS name.
       *
       * @param name Description of Parameter
       * @return The Name value
       * @since 1.7
       */
      public static boolean isName( final String name )
      {
          return isOs( null, name, null, null );
      }
  
      /**
       * Determines if the OS on which Ant is executing matches the given OS
       * family, name, architecture and version
       *
       * @param family The OS family
       * @param name The OS name
       * @param arch The OS architecture
       * @param version The OS version
       * @return The Os value
       */
      public static boolean isOs( final String family,
                                  final String name,
                                  final String arch,
                                  final String version )
      {
          if( family != null || name != null || arch != null || version != null )
          {
              final boolean isFamily = familyMatches( family );
              final boolean isName = nameMatches( name );
              final boolean isArch = archMatches( arch );
              final boolean isVersion = versionMatches( version );
  
              return isFamily && isName && isArch && isVersion;
          }
          else
          {
              return false;
          }
      }
  
      private static boolean versionMatches( final String version )
      {
          boolean isVersion = true;
          if( version != null )
          {
              isVersion = version.equals( OS_VERSION );
          }
          return isVersion;
      }
  
      private static boolean archMatches( final String arch )
      {
          boolean isArch = true;
          if( arch != null )
          {
              isArch = arch.equals( OS_ARCH );
          }
          return isArch;
      }
  
      private static boolean nameMatches( final String name )
      {
          boolean isName = true;
          if( name != null )
          {
              isName = name.equals( OS_NAME );
          }
          return isName;
      }
  
      private static boolean familyMatches( final String family )
      {
          boolean isFamily = true;
          if( family != null )
          {
              if( family.equals( "windows" ) )
              {
                  isFamily = OS_NAME.indexOf( "windows" ) > -1;
              }
              else if( family.equals( "os/2" ) )
              {
                  isFamily = OS_NAME.indexOf( "os/2" ) > -1;
              }
              else if( family.equals( "netware" ) )
              {
                  isFamily = OS_NAME.indexOf( "netware" ) > -1;
              }
              else if( family.equals( "dos" ) )
              {
                  isFamily = PATH_SEP.equals( ";" ) && !isFamily( "netware" );
              }
              else if( family.equals( "mac" ) )
              {
                  isFamily = OS_NAME.indexOf( "mac" ) > -1;
              }
              else if( family.equals( "unix" ) )
              {
                  isFamily = PATH_SEP.equals( ":" ) &&
                      ( !isFamily( "mac" ) || OS_NAME.endsWith( "x" ) );
              }
              else
              {
                  final String message = REZ.getString( "unknown-os-family", family );
                  throw new IllegalArgumentException( message );
              }
          }
          return isFamily;
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/impl/DefaultExecManager.java
  
  Index: DefaultExecManager.java
  ===================================================================
  /*
   * 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.aut.nativelib.impl;
  
  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.aut.nativelib.Os;
  import org.apache.aut.nativelib.CommandLauncher;
  import org.apache.aut.nativelib.ExecException;
  import org.apache.aut.nativelib.ExecManager;
  import org.apache.aut.nativelib.ExecMetaData;
  import org.apache.aut.nativelib.ExecOutputHandler;
  import org.apache.aut.nativelib.launchers.DefaultCommandLauncher;
  import org.apache.aut.nativelib.launchers.MacCommandLauncher;
  import org.apache.aut.nativelib.launchers.ScriptCommandLauncher;
  import org.apache.aut.nativelib.launchers.WinNTCommandLauncher;
  
  /**
   * Default implementation of <code>ExecManager</code>.
   * Used to run processes in the ant environment.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:thomas.haas@softwired-inc.com">Thomas Haas</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:08 $
   * @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 execMetaData,
                          final ExecOutputHandler handler,
                          long timeout )
          throws IOException, ExecException /*TimeoutException*/
      {
          final LogOutputStream output = new LogOutputStream( handler, false );
          final LogOutputStream error = new LogOutputStream( handler, true );
          return execute( execMetaData, null, output, error, timeout );
      }
  
      /**
       * 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( Os.isFamily( "netware" ) )
          {
              // 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();
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/impl/LogOutputStream.java
  
  Index: LogOutputStream.java
  ===================================================================
  /*
   * 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.aut.nativelib.impl;
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import org.apache.aut.nativelib.ExecOutputHandler;
  import org.apache.avalon.framework.logger.Logger;
  
  /**
   * Logs each line written to this stream to the specified
   * <code>ExecOutputHandler</code>. Tries to be smart about
   * line separators.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:08 $
   */
  class LogOutputStream
      extends OutputStream
  {
      private final boolean m_isError;
      private final ExecOutputHandler m_handler;
  
      private final ByteArrayOutputStream m_buffer = new ByteArrayOutputStream();
      private boolean m_skip;
  
      public LogOutputStream( final ExecOutputHandler handler,
                              final boolean isError )
      {
          m_handler = handler;
          m_isError = isError;
      }
  
      /**
       * Writes all remaining
       */
      public void close()
          throws IOException
      {
          if( m_buffer.size() > 0 )
          {
              processBuffer();
          }
          super.close();
      }
  
      /**
       * Write the data to the buffer and flush the buffer, if a line separator is
       * detected.
       *
       * @param ch data to log (byte).
       */
      public void write( final int ch )
          throws IOException
      {
          if( ( ch == '\n' ) || ( ch == '\r' ) )
          {
              if( !m_skip )
              {
                  processBuffer();
              }
          }
          else
          {
              m_buffer.write( (byte)ch );
          }
  
          m_skip = ( ch == '\r' );
      }
  
      /**
       * Converts the buffer to a string and sends it to <code>ExecOutputHandler</code>
       */
      private void processBuffer()
      {
          final String line = m_buffer.toString();
          if( m_isError )
          {
              m_handler.stderr( line );
          }
          else
          {
              m_handler.stdout( line );
          }
          m_buffer.reset();
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/impl/ProcessDestroyer.java
  
  Index: ProcessDestroyer.java
  ===================================================================
  /*
   * 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.aut.nativelib.impl;
  
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import java.util.Iterator;
  
  /**
   * Destroys all registered <code>Process</code>es when
   * the VM exits (if in JDK1.3) or when requested.
   *
   * @author <a href="mailto:mnewcomb@tacintel.com">Michael Newcomb</a>
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:08 $
   */
  class ProcessDestroyer
      extends Thread
  {
      private ArrayList m_processes = new ArrayList();
  
      /**
       * Constructs a <code>ProcessDestroyer</code> and registers it as a shutdown
       * hook.
       */
      public ProcessDestroyer()
      {
          try
          {
              // check to see if the method exists (support pre-JDK 1.3 VMs)
              //
              final Class[] paramTypes = {Thread.class};
              final Method addShutdownHook =
                  Runtime.class.getMethod( "addShutdownHook", paramTypes );
  
              // add the hook
              Object[] args = {this};
              addShutdownHook.invoke( Runtime.getRuntime(), args );
          }
          catch( final Exception e )
          {
              // it just won't be added as a shutdown hook... :(
          }
      }
  
      /**
       * Add process to list of processes to be shutdown.
       *
       * @param process the process to add
       */
      public synchronized void add( final Process process )
      {
          if( !m_processes.contains( process ) )
          {
              m_processes.add( process );
          }
      }
  
      /**
       * Remove process from list of processes to be shutdown.
       *
       * @param process the process to remove
       */
      public synchronized void remove( final Process process )
      {
          m_processes.remove( process );
      }
  
      /**
       * Invoked by the VM when it is exiting.
       */
      public void run()
      {
          destroyProcesses();
      }
  
      protected synchronized void destroyProcesses()
      {
          final Iterator processes = m_processes.iterator();
          while( processes.hasNext() )
          {
              ( (Process)processes.next() ).destroy();
              processes.remove();
          }
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/impl/ProcessMonitor.java
  
  Index: ProcessMonitor.java
  ===================================================================
  /*
   * 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.aut.nativelib.impl;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import org.apache.avalon.excalibur.io.IOUtil;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  
  /**
   * This class is responsible for monitoring a process.
   * It will monitor a process and if it goes longer than its timeout
   * then it will terminate it. The monitor will also read data from
   * stdout and stderr of process and pass it onto user specified streams.
   * It will also in the future do the same for stdin.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:08 $
   */
  class ProcessMonitor
      extends AbstractLogEnabled
      implements Runnable
  {
      //Time to sleep in loop while processing output
      //of command and monitoring for timeout
      private final static int SLEEP_TIME = 5;
  
      //State to indicate process is still running
      private static final int STATE_RUNNING = 0;
  
      //State to indicate process shutdown by itself
      private static final int STATE_STOPPED = 1;
  
      //State to indicate process was terminated due to timeout
      private static final int STATE_TERMINATED = 2;
  
      /**
       * The state of the process monitor and thus
       * the state of the underlying process.
       */
      private int m_state = STATE_RUNNING;
  
      /**
       * This is the process we are monitoring.
       */
      private final Process m_process;
  
      /**
       * This specifies the time at which this process will
       * timeout. 0 implies no timeout.
       */
      private final long m_timeout;
  
      /**
       * Stream from which to read standard input.
       */
      private InputStream m_input;
  
      /**
       * Stream to write standard output to.
       */
      private final OutputStream m_output;
  
      /**
       * Stream to write standard error to.
       */
      private final OutputStream m_error;
  
      public ProcessMonitor( final Process process,
                             final InputStream input,
                             final OutputStream output,
                             final OutputStream error,
                             final long timeoutDuration )
      {
          if( null == process )
          {
              throw new NullPointerException( "process" );
          }
  
          if( 0 > timeoutDuration )
          {
              throw new IllegalArgumentException( "timeoutDuration" );
          }
  
          final long now = System.currentTimeMillis();
          long timeout = 0;
          if( 0 != timeoutDuration )
          {
              timeout = now + timeoutDuration;
          }
  
          m_process = process;
          m_input = input;
          m_output = output;
          m_error = error;
          m_timeout = timeout;
      }
  
      /**
       * Utility method to check if process timed out.
       * Only valid after run() has exited.
       */
      public boolean didProcessTimeout()
      {
          return ( m_state == STATE_TERMINATED );
      }
  
      /**
       * Thread method to monitor the state of the process.
       */
      public void run()
      {
          while( STATE_RUNNING == m_state )
          {
              processStandardInput();
              processStandardOutput();
              processStandardError();
  
              if( !isProcessStopped() )
              {
                  checkTimeout();
              }
  
              try
              {
                  Thread.sleep( SLEEP_TIME );
              }
              catch( final InterruptedException ie )
              {
                  //swallow it
              }
          }
  
          IOUtil.shutdownStream( m_input );
          IOUtil.shutdownStream( m_output );
          IOUtil.shutdownStream( m_error );
      }
  
      /**
       * Check if process has stopped. If it has then update state
       * and return true, else return false.
       */
      private boolean isProcessStopped()
      {
          boolean stopped;
          try
          {
              m_process.exitValue();
              stopped = true;
          }
          catch( final IllegalThreadStateException itse )
          {
              stopped = false;
          }
  
          if( stopped )
          {
              m_state = STATE_STOPPED;
          }
  
          return stopped;
      }
  
      /**
       * Check if the process has exceeded time allocated to it.
       * If it has reached timeout then terminate the process
       * and set state to <code>STATE_TERMINATED</code>.
       */
      private void checkTimeout()
      {
          if( 0 == m_timeout )
          {
              return;
          }
  
          final long now = System.currentTimeMillis();
          if( now > m_timeout )
          {
              m_state = STATE_TERMINATED;
              m_process.destroy();
          }
      }
  
      /**
       * Process the standard input of process.
       * Reading it from user specified stream and copy it
       * to processes standard input stream.
       */
      private void processStandardInput()
      {
          if( null != m_input )
          {
              //Note can not do this as the process may block
              //when written to which will result in this whole
              //thread being blocked. Probably need to write to
              //stdin in another thread
              //copy( m_input, m_process.getOutputStream() );
  
              //Should we shutdown the processes input stream ?
              //Why not - at least for now
              IOUtil.shutdownStream( m_process.getOutputStream() );
  
              IOUtil.shutdownStream( m_input );
              m_input = null;
          }
      }
  
      /**
       * Process the standard output of process.
       * Reading it and sending it to user specified stream
       * or into the void.
       */
      private void processStandardOutput()
      {
          final InputStream input = m_process.getInputStream();
          copy( input, m_output );
      }
  
      /**
       * Process the standard error of process.
       * Reading it and sending it to user specified stream
       * or into the void.
       */
      private void processStandardError()
      {
          final InputStream input = m_process.getInputStream();
          copy( input, m_error );
      }
  
      /**
       * Copy data from specified input stream to output stream if
       * output stream exists. The size of data that should be attempted
       * to read is determined by calling available() on input stream.
       */
      private void copy( final InputStream input,
                         final OutputStream output )
      {
          try
          {
              final int available = input.available();
              if( 0 >= available ) return;
  
              final byte[] data = new byte[ available ];
              final int read = input.read( data );
  
              if( null != output )
              {
                  output.write( data, 0, read );
              }
          }
          catch( final IOException ioe )
          {
              final String message = "Error processing streams";
              getLogger().error( message, ioe );
          }
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/launchers/DefaultCommandLauncher.java
  
  Index: DefaultCommandLauncher.java
  ===================================================================
  /*
   * 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.aut.nativelib.launchers;
  
  import java.io.File;
  import java.io.IOException;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.Properties;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.aut.nativelib.CommandLauncher;
  import org.apache.aut.nativelib.Environment;
  import org.apache.aut.nativelib.ExecException;
  import org.apache.aut.nativelib.ExecMetaData;
  
  /**
   * A command launcher for a particular JVM/OS platform. This class is a
   * general purpose command launcher which can only launch commands in the
   * current working directory.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:thomas.haas@softwired-inc.com">Thomas Haas</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:08 $
   */
  public class DefaultCommandLauncher
      implements CommandLauncher
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( DefaultCommandLauncher.class );
  
      private static final Method c_execWithCWD;
  
      static
      {
          // Locate method Runtime.exec(String[] cmdarray, String[] envp, File dir)
          Method method = null;
          try
          {
              final Class[] types =
                  new Class[]{String[].class, String[].class, File.class};
              method = Runtime.class.getMethod( "exec", types );
          }
          catch( final NoSuchMethodException nsme )
          {
              //ignore
          }
  
          c_execWithCWD = method;
      }
  
      /**
       * Execute the specified native command.
       *
       * @param metaData the native command to execute
       * @return the Process launched by the CommandLauncher
       * @exception IOException is thrown when the native code can not
       *            launch the application for some reason. Usually due
       *            to the command not being fully specified and not in
       *            the PATH env var.
       * @exception ExecException if the command launcher detects that
       *            it can not execute the native command for some reason.
       */
      public Process exec( final ExecMetaData metaData )
          throws IOException, ExecException
      {
          if( ExecUtil.isCwd( metaData.getWorkingDirectory() ) )
          {
              final String[] env = ExecUtil.getEnvironmentSpec( metaData );
              return Runtime.getRuntime().exec( metaData.getCommand(), env );
          }
          else if( null == c_execWithCWD )
          {
              final String message = REZ.getString( "default.bad-dir.error" );
              throw new ExecException( message );
          }
          else
          {
              return execJava13( metaData );
          }
      }
  
      /**
       * Execute the Java1.3 Runtime.exec() 3 parame method that sets working
       * directory. This needs to be done via reflection so that it can compile
       * under 1.2.
       */
      private Process execJava13( final ExecMetaData metaData )
          throws IOException, ExecException
      {
          final String[] env = ExecUtil.getEnvironmentSpec( metaData );
          final Object[] args =
              {metaData.getCommand(),
               env,
               metaData.getWorkingDirectory()};
          try
          {
              return (Process)c_execWithCWD.invoke( Runtime.getRuntime(), args );
          }
          catch( final IllegalAccessException iae )
          {
              throw new ExecException( iae.getMessage(), iae );
          }
          catch( final IllegalArgumentException iae )
          {
              throw new ExecException( iae.getMessage(), iae );
          }
          catch( final InvocationTargetException ite )
          {
              final Throwable t = ite.getTargetException();
              if( t instanceof IOException )
              {
                  t.fillInStackTrace();
                  throw (IOException)t;
              }
              else
              {
                  throw new ExecException( t.getMessage(), t );
              }
          }
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/launchers/ExecUtil.java
  
  Index: ExecUtil.java
  ===================================================================
  /*
   * 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.aut.nativelib.launchers;
  
  import java.io.File;
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.Properties;
  import org.apache.aut.nativelib.Environment;
  import org.apache.aut.nativelib.ExecException;
  import org.apache.aut.nativelib.ExecMetaData;
  
  /**
   * A set of utility functions useful when writing CommandLaunchers.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:08 $
   */
  class ExecUtil
  {
      /**
       * The file representing the current working directory.
       */
      private static final File c_cwd;
  
      static
      {
          try
          {
              c_cwd = ( new File( "." ) ).getCanonicalFile();
          }
          catch( final IOException ioe )
          {
              //Should never happen
              throw new IllegalStateException();
          }
      }
  
      /**
       * Private constructor to block instantiation.
       */
      private ExecUtil()
      {
      }
  
      /**
       * Create a new ExecMetaData representing the same command with the specified
       * prefix. This is useful when you are launching the native executable via a
       * script of some sort.
       */
      protected static ExecMetaData prepend( final ExecMetaData metaData,
                                             final String[] prefix )
      {
          final String[] original = metaData.getCommand();
          final String[] command = new String[ original.length + prefix.length ];
  
          System.arraycopy( prefix, 0, command, 0, prefix.length );
          System.arraycopy( original, 0, command, prefix.length, original.length );
  
          return new ExecMetaData( command,
                                   metaData.getEnvironment(),
                                   metaData.getWorkingDirectory(),
                                   metaData.isEnvironmentAdditive() );
      }
  
      /**
       * Utility method to check if specified file is equal
       * to the current working directory.
       */
      protected static boolean isCwd( final File file )
          throws IOException
      {
          return file.getCanonicalFile().equals( getCwd() );
      }
  
      private static String[] toNativeEnvironment( final Properties environment )
          throws ExecException
      {
          if( null == environment )
          {
              return null;
          }
          else
          {
              final ArrayList newEnvironment = new ArrayList();
  
              final Iterator keys = environment.keySet().iterator();
              while( keys.hasNext() )
              {
                  final String key = (String)keys.next();
                  final String value = environment.getProperty( key );
                  newEnvironment.add( key + '=' + value );
              }
  
              return (String[])newEnvironment.toArray( new String[ newEnvironment.size() ] );
          }
      }
  
      /**
       * Return the current working directory of the JVM.
       * This value is initialized when this class is first loaded.
       */
      protected static File getCwd()
      {
          return c_cwd;
      }
  
      /**
       * Get the native environment according to proper rules.
       * Return null if no environment specified, return environment combined
       * with native environment if environment data is additive else just return
       * converted environment data.
       */
      protected static String[] getEnvironmentSpec( final ExecMetaData metaData )
          throws ExecException, IOException
      {
          final Properties environment = metaData.getEnvironment();
          if( 0 == environment.size() )
          {
              return null;
          }
          else
          {
              if( metaData.isEnvironmentAdditive() )
              {
                  final Properties newEnvironment = new Properties();
                  newEnvironment.putAll( Environment.getNativeEnvironment() );
                  newEnvironment.putAll( environment );
                  return toNativeEnvironment( newEnvironment );
              }
              else
              {
                  return toNativeEnvironment( environment );
              }
          }
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/launchers/MacCommandLauncher.java
  
  Index: MacCommandLauncher.java
  ===================================================================
  /*
   * 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.aut.nativelib.launchers;
  
  import java.io.File;
  import java.io.IOException;
  import org.apache.aut.nativelib.CommandLauncher;
  import org.apache.aut.nativelib.ExecException;
  import org.apache.aut.nativelib.ExecMetaData;
  
  /**
   * A command launcher for Mac that uses a dodgy mechanism to change working
   * directory before launching commands. This class changes the value of the
   * System property "user.dir" before the command is executed and then resets
   * it after the command is executed. This can have really unhealthy side-effects
   * if there are multiple threads in JVM and should be used with extreme caution.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:thomas.haas@softwired-inc.com">Thomas Haas</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:08 $
   */
  public class MacCommandLauncher
      implements CommandLauncher
  {
      /**
       * Execute the specified native command.
       */
      public Process exec( final ExecMetaData metaData )
          throws IOException, ExecException
      {
          final File directory = metaData.getWorkingDirectory().getCanonicalFile();
          if( ExecUtil.isCwd( directory ) )
          {
              final String[] env = ExecUtil.getEnvironmentSpec( metaData );
              return Runtime.getRuntime().exec( metaData.getCommand(), env );
          }
  
          //WARNING: This is an ugly hack and not thread safe in the slightest way
          //It can have really really undersirable side-effects if multiple threads
          //are running in the JVM
          try
          {
              System.setProperty( "user.dir", directory.toString() );
              final String[] env = ExecUtil.getEnvironmentSpec( metaData );
              return Runtime.getRuntime().exec( metaData.getCommand(), env );
          }
          finally
          {
              System.setProperty( "user.dir", ExecUtil.getCwd().toString() );
          }
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/launchers/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  default.bad-dir.error=Unable to launch native command in a working directory other than "." on Java 1.2 JVMs.
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/launchers/ScriptCommandLauncher.java
  
  Index: ScriptCommandLauncher.java
  ===================================================================
  /*
   * 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.aut.nativelib.launchers;
  
  import java.io.IOException;
  import org.apache.aut.nativelib.CommandLauncher;
  import org.apache.aut.nativelib.ExecException;
  import org.apache.aut.nativelib.ExecMetaData;
  
  /**
   * A command launcher that uses an auxiliary script to launch commands in
   * directories other than the current working directory. The script specified
   * in the constructor is invoked with the directory passed as second argument
   * and the actual command as subsequent arguments.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:thomas.haas@softwired-inc.com">Thomas Haas</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:08 $
   */
  public class ScriptCommandLauncher
      implements CommandLauncher
  {
      private String[] m_script;
  
      /**
       * Create a command launcher whos script is a single
       * command. An example would be "bin/antRun.bat".
       */
      public ScriptCommandLauncher( final String script )
      {
          this( new String[]{script} );
      }
  
      /**
       * Create a command launcher whos script takes multiple
       * commands. Examples would be "perl bin/antRun.pl",
       * "python bin/antRun.py", ""tcl8 bin/antRun.tcl" etc
       */
      public ScriptCommandLauncher( final String[] script )
      {
          m_script = script;
          if( null == m_script )
          {
              throw new NullPointerException( "script" );
          }
          if( 0 == m_script.length )
          {
              throw new IllegalArgumentException( "script" );
          }
      }
  
      /**
       * Launches the given command in a new process using cmd.exe to
       * set the working directory.
       */
      public Process exec( final ExecMetaData metaData )
          throws IOException, ExecException
      {
          // Build the command
          final String[] prefix = new String[ m_script.length + 1 ];
          for( int i = 0; i < m_script.length; i++ )
          {
              prefix[ i ] = m_script[ i ];
          }
          prefix[ m_script.length ] = metaData.getWorkingDirectory().getCanonicalPath();
  
          final ExecMetaData newMetaData = ExecUtil.prepend( metaData, prefix );
          final String[] env = ExecUtil.getEnvironmentSpec( metaData );
          return Runtime.getRuntime().exec( newMetaData.getCommand(), env );
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/nativelib/launchers/WinNTCommandLauncher.java
  
  Index: WinNTCommandLauncher.java
  ===================================================================
  /*
   * 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.aut.nativelib.launchers;
  
  import java.io.IOException;
  import org.apache.aut.nativelib.CommandLauncher;
  import org.apache.aut.nativelib.ExecException;
  import org.apache.aut.nativelib.ExecMetaData;
  
  /**
   * A command launcher for Windows 2000/NT that uses 'cmd.exe' when launching
   * commands in directories other than the current working directory.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:thomas.haas@softwired-inc.com">Thomas Haas</a>
   * @version $Revision: 1.1 $ $Date: 2002/01/12 04:51:08 $
   */
  public class WinNTCommandLauncher
      implements CommandLauncher
  {
      /**
       * Launches the given command in a new process using cmd.exe to
       * set the working directory.
       */
      public Process exec( final ExecMetaData metaData )
          throws IOException, ExecException
      {
          // Use cmd.exe to change to the specified directory before running
          // the command
          final String[] prefix = new String[ 6 ];
          prefix[ 0 ] = "cmd";
          prefix[ 1 ] = "/c";
          prefix[ 2 ] = "cd";
          prefix[ 3 ] = "/d";
          prefix[ 4 ] = metaData.getWorkingDirectory().getCanonicalPath();
          prefix[ 5 ] = "&&";
  
          final ExecMetaData newMetaData = ExecUtil.prepend( metaData, prefix );
          final String[] env = ExecUtil.getEnvironmentSpec( metaData );
          return Runtime.getRuntime().exec( newMetaData.getCommand(), env );
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message