donaldp     01/12/17 01:49:30

  Added:       proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec
                        ExecTask.java Execute.java
                        ExecuteStreamHandler.java ExecuteWatchdog.java
                        LogOutputStream.java LogStreamHandler.java
                        ProcessDestroyer.java PumpStreamHandler.java
                        StreamPumper.java
  Log:
  Move the execute related classes into a new package.
  
  Revision  Changes    Path
  1.1                  
jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/ExecTask.java
  
  Index: ExecTask.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 file.
   */
  package org.apache.tools.ant.taskdefs.exec;
  
  import java.io.BufferedReader;
  import java.io.ByteArrayOutputStream;
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.StringReader;
  import org.apache.myrmidon.api.TaskException;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.Task;
  import org.apache.tools.ant.types.Commandline;
  import org.apache.tools.ant.types.Environment;
  
  /**
   * Executes a given command if the os platform is appropriate.
   *
   * @author [EMAIL PROTECTED]
   * @author [EMAIL PROTECTED]
   * @author [EMAIL PROTECTED]
   * @author <a href="mailto:[EMAIL PROTECTED]">Stefan Bodewig</a>
   * @author <a href="mailto:[EMAIL PROTECTED]">Mariusz Nowostawski</a>
   */
  public class ExecTask extends Task
  {
      private static String lSep = System.getProperty( "line.separator" );
      protected boolean failOnError = false;
      protected boolean newEnvironment = false;
      private Integer timeout = null;
      private Environment env = new Environment();
      protected Commandline cmdl = new Commandline();
      private FileOutputStream fos = null;
      private ByteArrayOutputStream baos = null;
      private boolean failIfExecFails = true;
  
      /**
       * Controls whether the VM (1.3 and above) is used to execute the command
       */
      private boolean vmLauncher = true;
      private File dir;
  
      private String os;
      private File out;
      private String outputprop;
      private String resultProperty;
  
      /**
       * The working directory of the process
       *
       * @param d The new Dir value
       */
      public void setDir( File d )
          throws TaskException
      {
          this.dir = d;
      }
  
      /**
       * The command to execute.
       *
       * @param value The new Executable value
       */
      public void setExecutable( String value )
          throws TaskException
      {
          cmdl.setExecutable( value );
      }
  
      /**
       * ant attribute
       *
       * @param flag The new FailIfExecutionFails value
       */
      public void setFailIfExecutionFails( boolean flag )
      {
          failIfExecFails = flag;
      }
  
      /**
       * Throw a TaskException if process returns non 0.
       *
       * @param fail The new Failonerror value
       */
      public void setFailonerror( boolean fail )
      {
          failOnError = fail;
      }
  
      /**
       * Use a completely new environment
       *
       * @param newenv The new Newenvironment value
       */
      public void setNewenvironment( boolean newenv )
      {
          newEnvironment = newenv;
      }
  
      /**
       * Only execute the process if <code>os.name</code> is included in this
       * string.
       *
       * @param os The new Os value
       */
      public void setOs( String os )
      {
          this.os = os;
      }
  
      /**
       * File the output of the process is redirected to.
       *
       * @param out The new Output value
       */
      public void setOutput( File out )
      {
          this.out = out;
      }
  
      /**
       * Property name whose value should be set to the output of the process
       *
       * @param outputprop The new Outputproperty value
       */
      public void setOutputproperty( String outputprop )
      {
          this.outputprop = outputprop;
      }
  
      /**
       * fill a property in with a result. when no property is defined: failure 
to
       * execute
       *
       * @param resultProperty The new ResultProperty value
       * @since 1.5
       */
      public void setResultProperty( String resultProperty )
      {
          this.resultProperty = resultProperty;
      }
  
      /**
       * Timeout in milliseconds after which the process will be killed.
       *
       * @param value The new Timeout value
       */
      public void setTimeout( Integer value )
      {
          timeout = value;
      }
  
      /**
       * Control whether the VM is used to launch the new process or whether the
       * OS's shell is used.
       *
       * @param vmLauncher The new VMLauncher value
       */
      public void setVMLauncher( boolean vmLauncher )
      {
          this.vmLauncher = vmLauncher;
      }
  
      /**
       * Add a nested env element - an environment variable.
       *
       * @param var The feature to be added to the Env attribute
       */
      public void addEnv( Environment.Variable var )
      {
          env.addVariable( var );
      }
  
      /**
       * Add a nested arg element - a command line argument.
       *
       * @return Description of the Returned Value
       */
      public Commandline.Argument createArg()
      {
          return cmdl.createArgument();
      }
  
      /**
       * Do the work.
       *
       * @exception TaskException Description of Exception
       */
      public void execute()
          throws TaskException
      {
          checkConfiguration();
          if( isValidOs() )
          {
              runExec( prepareExec() );
          }
      }
  
      /**
       * Is this the OS the user wanted?
       *
       * @return The ValidOs value
       */
      protected boolean isValidOs()
      {
          // test if os match
          String myos = System.getProperty( "os.name" );
          log( "Current OS is " + myos, Project.MSG_VERBOSE );
          if( ( os != null ) && ( os.indexOf( myos ) < 0 ) )
          {
              // this command will be executed only on the specified OS
              log( "This OS, " + myos + " was not found in the specified list 
of valid OSes: " + os, Project.MSG_VERBOSE );
              return false;
          }
          return true;
      }
  
      /**
       * A Utility method for this classes and subclasses to run an Execute
       * instance (an external command).
       *
       * @param exe Description of Parameter
       * @exception IOException Description of Exception
       */
      protected final void runExecute( Execute exe )
          throws IOException, TaskException
      {
          int err = -1;// assume the worst
  
          err = exe.execute();
          //test for and handle a forced process death
          if( exe.killedProcess() )
          {
              log( "Timeout: killed the sub-process", Project.MSG_WARN );
          }
          maybeSetResultPropertyValue( err );
          if( err != 0 )
          {
              if( failOnError )
              {
                  throw new TaskException( getName() + " returned: " + err );
              }
              else
              {
                  log( "Result: " + err, Project.MSG_ERR );
              }
          }
          if( baos != null )
          {
              BufferedReader in =
                  new BufferedReader( new StringReader( baos.toString() ) );
              String line = null;
              StringBuffer val = new StringBuffer();
              while( ( line = in.readLine() ) != null )
              {
                  if( val.length() != 0 )
                  {
                      val.append( lSep );
                  }
                  val.append( line );
              }
              setProperty( outputprop, val.toString() );
          }
      }
  
      /**
       * Has the user set all necessary attributes?
       *
       * @exception TaskException Description of Exception
       */
      protected void checkConfiguration()
          throws TaskException
      {
          if( cmdl.getExecutable() == null )
          {
              throw new TaskException( "no executable specified" );
          }
          if( dir != null && !dir.exists() )
          {
              throw new TaskException( "The directory you specified does not 
exist" );
          }
          if( dir != null && !dir.isDirectory() )
          {
              throw new TaskException( "The directory you specified is not a 
directory" );
          }
      }
  
      /**
       * Create the StreamHandler to use with our Execute instance.
       *
       * @return Description of the Returned Value
       * @exception TaskException Description of Exception
       */
      protected ExecuteStreamHandler createHandler()
          throws TaskException
      {
          if( out != null )
          {
              try
              {
                  fos = new FileOutputStream( out );
                  log( "Output redirected to " + out, Project.MSG_VERBOSE );
                  return new PumpStreamHandler( fos );
              }
              catch( FileNotFoundException fne )
              {
                  throw new TaskException( "Cannot write to " + out, fne );
              }
              catch( IOException ioe )
              {
                  throw new TaskException( "Cannot write to " + out, ioe );
              }
          }
          else if( outputprop != null )
          {
              baos = new ByteArrayOutputStream();
              log( "Output redirected to ByteArray", Project.MSG_VERBOSE );
              return new PumpStreamHandler( baos );
          }
          else
          {
              return new LogStreamHandler( this,
                                           Project.MSG_INFO, Project.MSG_WARN );
          }
      }
  
      /**
       * Create the Watchdog to kill a runaway process.
       *
       * @return Description of the Returned Value
       * @exception TaskException Description of Exception
       */
      protected ExecuteWatchdog createWatchdog()
          throws TaskException
      {
          if( timeout == null )
              return null;
          return new ExecuteWatchdog( timeout.intValue() );
      }
  
      /**
       * Flush the output stream - if there is one.
       */
      protected void logFlush()
      {
          try
          {
              if( fos != null )
                  fos.close();
              if( baos != null )
                  baos.close();
          }
          catch( IOException io )
          {
          }
      }
  
      /**
       * helper method to set result property to the passed in value if
       * appropriate
       *
       * @param result Description of Parameter
       */
      protected void maybeSetResultPropertyValue( int result )
          throws TaskException
      {
          String res = Integer.toString( result );
          if( resultProperty != null )
          {
              setProperty( resultProperty, res );
          }
      }
  
      /**
       * Create an Execute instance with the correct working directory set.
       *
       * @return Description of the Returned Value
       * @exception TaskException Description of Exception
       */
      protected Execute prepareExec()
          throws TaskException
      {
          // default directory to the project's base directory
          if( dir == null ) dir = getBaseDirectory();
          // show the command
          log( cmdl.toString(), Project.MSG_VERBOSE );
  
          Execute exe = new Execute( createHandler(), createWatchdog() );
          exe.setAntRun( project );
          exe.setWorkingDirectory( dir );
          exe.setVMLauncher( vmLauncher );
          String[] environment = env.getVariables();
          if( environment != null )
          {
              for( int i = 0; i < environment.length; i++ )
              {
                  log( "Setting environment variable: " + environment[ i ],
                       Project.MSG_VERBOSE );
              }
          }
          exe.setNewenvironment( newEnvironment );
          exe.setEnvironment( environment );
          return exe;
      }
  
      /**
       * Run the command using the given Execute instance. This may be overidden
       * by subclasses
       *
       * @param exe Description of Parameter
       * @exception TaskException Description of Exception
       */
      protected void runExec( Execute exe )
          throws TaskException
      {
          exe.setCommandline( cmdl.getCommandline() );
          try
          {
              runExecute( exe );
          }
          catch( IOException e )
          {
              if( failIfExecFails )
              {
                  throw new TaskException( "Execute failed: " + e.toString(), e 
);
              }
              else
              {
                  log( "Execute failed: " + e.toString(), Project.MSG_ERR );
              }
          }
          finally
          {
              // close the output file if required
              logFlush();
          }
      }
  
  }
  
  
  
  1.1                  
jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/Execute.java
  
  Index: Execute.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 file.
   */
  package org.apache.tools.ant.taskdefs.exec;
  
  import java.io.BufferedReader;
  import java.io.ByteArrayOutputStream;
  import java.io.File;
  import java.io.IOException;
  import java.io.StringReader;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.Locale;
  import java.util.Vector;
  import org.apache.myrmidon.api.TaskException;
  import org.apache.myrmidon.framework.Os;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.Task;
  import org.apache.tools.ant.types.Commandline;
  import org.apache.tools.ant.util.FileUtils;
  
  /**
   * Runs an external program.
   *
   * @author [EMAIL PROTECTED]
   */
  public class Execute
  {
      /**
       * Invalid exit code.
       */
      public final static int INVALID = Integer.MAX_VALUE;
  
      private static String antWorkingDirectory = System.getProperty( 
"user.dir" );
      private static CommandLauncher vmLauncher;
      private static CommandLauncher shellLauncher;
      private static Vector procEnvironment;
  
      /**
       * Used to destroy processes when the VM exits.
       */
      private static ProcessDestroyer processDestroyer = new ProcessDestroyer();
  
      private String[] cmdl = null;
      private String[] env = null;
      private int exitValue = INVALID;
      private File workingDirectory = null;
      private Project project = null;
      private boolean newEnvironment = false;
  
      /**
       * Controls whether the VM is used to launch commands, where possible
       */
      private boolean useVMLauncher = true;
      private ExecuteStreamHandler streamHandler;
      private ExecuteWatchdog watchdog;
  
      /**
       * Builds a command launcher for the OS and JVM we are running under
       */
      static
      {
  
          try
          {
              // Try using a JDK 1.3 launcher
              try
              {
                  vmLauncher = new Java13CommandLauncher();
              }
              catch( NoSuchMethodException exc )
              {
                  // Ignore and keep try
              }
  
              if( Os.isFamily( "mac" ) )
              {
                  // Mac
                  shellLauncher = new MacCommandLauncher( new CommandLauncher() 
);
              }
              else if( Os.isFamily( "os/2" ) )
              {
                  // OS/2 - use same mechanism as Windows 2000
                  shellLauncher = new WinNTCommandLauncher( new 
CommandLauncher() );
              }
              else if( Os.isFamily( "windows" ) )
              {
                  // Windows.  Need to determine which JDK we're running in
  
                  CommandLauncher baseLauncher;
                  if( System.getProperty( "java.version" ).startsWith( "1.1" ) )
                  {
                      // JDK 1.1
                      baseLauncher = new Java11CommandLauncher();
                  }
                  else
                  {
                      // JDK 1.2
                      baseLauncher = new CommandLauncher();
                  }
  
                  // Determine if we're running under 2000/NT or 98/95
                  String osname =
                      System.getProperty( "os.name" ).toLowerCase( Locale.US );
  
                  if( osname.indexOf( "nt" ) >= 0 || osname.indexOf( "2000" ) 
>= 0 )
                  {
                      // Windows 2000/NT
                      shellLauncher = new WinNTCommandLauncher( baseLauncher );
                  }
                  else
                  {
                      // Windows 98/95 - need to use an auxiliary script
                      shellLauncher = new ScriptCommandLauncher( 
"bin/antRun.bat", baseLauncher );
                  }
              }
              else if( ( new Os( "netware" ) ).eval() )
              {
                  // NetWare.  Need to determine which JDK we're running in
                  CommandLauncher baseLauncher;
                  if( System.getProperty( "java.version" ).startsWith( "1.1" ) )
                  {
                      // JDK 1.1
                      baseLauncher = new Java11CommandLauncher();
                  }
                  else
                  {
                      // JDK 1.2
                      baseLauncher = new CommandLauncher();
                  }
  
                  shellLauncher = new PerlScriptCommandLauncher( 
"bin/antRun.pl", baseLauncher );
              }
              else
              {
                  // Generic
                  shellLauncher = new ScriptCommandLauncher( "bin/antRun", new 
CommandLauncher() );
              }
          }
          catch( TaskException e )
          {
              e.printStackTrace();
          }
      }
  
      /**
       * Creates a new execute object using <code>PumpStreamHandler</code> for
       * stream handling.
       */
      public Execute()
      {
          this( new PumpStreamHandler(), null );
      }
  
      /**
       * Creates a new execute object.
       *
       * @param streamHandler the stream handler used to handle the input and
       *      output streams of the subprocess.
       */
      public Execute( ExecuteStreamHandler streamHandler )
      {
          this( streamHandler, null );
      }
  
      /**
       * Creates a new execute object.
       *
       * @param streamHandler the stream handler used to handle the input and
       *      output streams of the subprocess.
       * @param watchdog a watchdog for the subprocess or <code>null</code> to 
to
       *      disable a timeout for the subprocess.
       */
      public Execute( ExecuteStreamHandler streamHandler, ExecuteWatchdog 
watchdog )
      {
          this.streamHandler = streamHandler;
          this.watchdog = watchdog;
      }
  
      /**
       * Find the list of environment variables for this process.
       *
       * @return The ProcEnvironment value
       */
      public static synchronized Vector getProcEnvironment()
          throws TaskException
      {
          if( procEnvironment != null )
              return procEnvironment;
  
          procEnvironment = new Vector();
          try
          {
              ByteArrayOutputStream out = new ByteArrayOutputStream();
              Execute exe = new Execute( new PumpStreamHandler( out ) );
              exe.setCommandline( getProcEnvCommand() );
              // Make sure we do not recurse forever
              exe.setNewenvironment( true );
              int retval = exe.execute();
              if( retval != 0 )
              {
                  // Just try to use what we got
              }
  
              BufferedReader in =
                  new BufferedReader( new StringReader( out.toString() ) );
              String var = null;
              String line;
              String lineSep = System.getProperty( "line.separator" );
              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 = lineSep + line;
                      }
                      else
                      {
                          var += lineSep + line;
                      }
                  }
                  else
                  {
                      // New env var...append the previous one if we have it.
                      if( var != null )
                      {
                          procEnvironment.addElement( var );
                      }
                      var = line;
                  }
              }
              // Since we "look ahead" before adding, there's one last env var.
              procEnvironment.addElement( var );
          }
          catch( IOException exc )
          {
              exc.printStackTrace();
              // Just try to see how much we got
          }
          return procEnvironment;
      }
  
      /**
       * A utility method that runs an external command. Writes the output and
       * error streams of the command to the project log.
       *
       * @param task The task that the command is part of. Used for logging
       * @param cmdline The command to execute.
       * @throws TaskException if the command does not return 0.
       */
      public static void runCommand( Task task, String[] cmdline )
          throws TaskException
      {
          try
          {
              task.log( Commandline.toString( cmdline ), Project.MSG_VERBOSE );
              Execute exe = new Execute( new LogStreamHandler( task,
                                                               Project.MSG_INFO,
                                                               Project.MSG_ERR 
) );
              exe.setAntRun( task.getProject() );
              exe.setCommandline( cmdline );
              int retval = exe.execute();
              if( retval != 0 )
              {
                  throw new TaskException( cmdline[ 0 ] + " failed with return 
code " + retval );
              }
          }
          catch( IOException exc )
          {
              throw new TaskException( "Could not launch " + cmdline[ 0 ] + ": 
" + exc );
          }
      }
  
      private static String[] getProcEnvCommand()
      {
          if( Os.isFamily( "os/2" ) )
          {
              // OS/2 - use same mechanism as Windows 2000
              // Not sure
              String[] cmd = {"cmd", "/c", "set"};
              return cmd;
          }
          else if( Os.isFamily( "windows" ) )
          {
              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
                  String[] cmd = {"cmd", "/c", "set"};
                  return cmd;
              }
              else
              {
                  // Windows 98/95 - need to use an auxiliary script
                  String[] cmd = {"command.com", "/c", "set"};
                  return cmd;
              }
          }
          else if( Os.isFamily( "unix" ) )
          {
              // Generic UNIX
              // Alternatively one could use: /bin/sh -c env
              String[] cmd = {"/usr/bin/env"};
              return cmd;
          }
          else if( Os.isFamily( "netware" ) )
          {
              String[] cmd = {"env"};
              return cmd;
          }
          else
          {
              // MAC OS 9 and previous
              // TODO: I have no idea how to get it, someone must fix it
              String[] cmd = null;
              return cmd;
          }
      }
  
      /**
       * Set the name of the antRun script using the project's value.
       *
       * @param project the current project.
       * @exception TaskException Description of Exception
       */
      public void setAntRun( Project project )
          throws TaskException
      {
          this.project = project;
      }
  
      /**
       * Sets the commandline of the subprocess to launch.
       *
       * @param commandline the commandline of the subprocess to launch
       */
      public void setCommandline( String[] commandline )
      {
          cmdl = commandline;
      }
  
      /**
       * Sets the environment variables for the subprocess to launch.
       *
       * @param env The new Environment value
       */
      public void setEnvironment( String[] env )
      {
          this.env = env;
      }
  
      /**
       * Set whether to propagate the default environment or not.
       *
       * @param newenv whether to propagate the process environment.
       */
      public void setNewenvironment( boolean newenv )
      {
          newEnvironment = newenv;
      }
  
      /**
       * Launch this execution through the VM, where possible, rather than 
through
       * the OS's shell. In some cases and operating systems using the shell 
will
       * allow the shell to perform additional processing such as associating an
       * executable with a script, etc
       *
       * @param useVMLauncher The new VMLauncher value
       */
      public void setVMLauncher( boolean useVMLauncher )
      {
          this.useVMLauncher = useVMLauncher;
      }
  
      /**
       * Sets the working directory of the process to execute. <p>
       *
       * This is emulated using the antRun scripts unless the OS is Windows NT 
in
       * which case a cmd.exe is spawned, or MRJ and setting user.dir works, or
       * JDK 1.3 and there is official support in java.lang.Runtime.
       *
       * @param wd the working directory of the process.
       */
      public void setWorkingDirectory( File wd )
      {
          if( wd == null || wd.getAbsolutePath().equals( antWorkingDirectory ) )
              workingDirectory = null;
          else
              workingDirectory = wd;
      }
  
      /**
       * Returns the commandline used to create a subprocess.
       *
       * @return the commandline used to create a subprocess
       */
      public String[] getCommandline()
      {
          return cmdl;
      }
  
      /**
       * Returns the environment used to create a subprocess.
       *
       * @return the environment used to create a subprocess
       */
      public String[] getEnvironment()
          throws TaskException
      {
          if( env == null || newEnvironment )
              return env;
          return patchEnvironment();
      }
  
      /**
       * query the exit value of the process.
       *
       * @return the exit value, 1 if the process was killed, or Project.INVALID
       *      if no exit value has been received
       */
      public int getExitValue()
      {
          return exitValue;
      }
  
      /**
       * Runs a process defined by the command line and returns its exit status.
       *
       * @return the exit status of the subprocess or <code>INVALID</code>
       * @exception IOException Description of Exception
       */
      public int execute()
          throws IOException, TaskException
      {
          CommandLauncher launcher = vmLauncher != null ? vmLauncher : 
shellLauncher;
          if( !useVMLauncher )
          {
              launcher = shellLauncher;
          }
  
          final Process process = launcher.exec( project, getCommandline(), 
getEnvironment(), workingDirectory );
          try
          {
              streamHandler.setProcessInputStream( process.getOutputStream() );
              streamHandler.setProcessOutputStream( process.getInputStream() );
              streamHandler.setProcessErrorStream( process.getErrorStream() );
          }
          catch( IOException e )
          {
              process.destroy();
              throw e;
          }
          streamHandler.start();
  
          // add the process to the list of those to destroy if the VM exits
          //
          processDestroyer.add( process );
  
          if( watchdog != null )
              watchdog.start( process );
          waitFor( process );
  
          // remove the process to the list of those to destroy if the VM exits
          //
          processDestroyer.remove( process );
  
          if( watchdog != null )
              watchdog.stop();
          streamHandler.stop();
          if( watchdog != null )
              watchdog.checkException();
          return getExitValue();
      }
  
      /**
       * test for an untimely death of the process
       *
       * @return true iff a watchdog had to kill the process
       * @since 1.5
       */
      public boolean killedProcess()
      {
          return watchdog != null && watchdog.killedProcess();
      }
  
      protected void setExitValue( int value )
      {
          exitValue = value;
      }
  
      protected void waitFor( Process process )
      {
          try
          {
              process.waitFor();
              setExitValue( process.exitValue() );
          }
          catch( InterruptedException e )
          {
          }
      }
  
      /**
       * Patch the current environment with the new values from the user.
       *
       * @return the patched environment
       */
      private String[] patchEnvironment()
          throws TaskException
      {
          Vector osEnv = (Vector)getProcEnvironment().clone();
          for( int i = 0; i < env.length; i++ )
          {
              int pos = env[ i ].indexOf( '=' );
              // Get key including "="
              String key = env[ i ].substring( 0, pos + 1 );
              int size = osEnv.size();
              for( int j = 0; j < size; j++ )
              {
                  if( ( (String)osEnv.elementAt( j ) ).startsWith( key ) )
                  {
                      osEnv.removeElementAt( j );
                      break;
                  }
              }
              osEnv.addElement( env[ i ] );
          }
          String[] result = new String[ osEnv.size() ];
          osEnv.copyInto( result );
          return result;
      }
  
      /**
       * 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 RT
       */
      private static class CommandLauncher
      {
          /**
           * Launches the given command in a new process.
           *
           * @param project The project that the command is part of
           * @param cmd The command to execute
           * @param env The environment for the new process. If null, the
           *      environment of the current proccess is used.
           * @return Description of the Returned Value
           * @exception IOException Description of Exception
           */
          public Process exec( Project project, String[] cmd, String[] env )
              throws IOException, TaskException
          {
              if( project != null )
              {
                  project.log( "Execute:CommandLauncher: " +
                               Commandline.toString( cmd ), Project.MSG_DEBUG );
              }
              return Runtime.getRuntime().exec( cmd, env );
          }
  
          /**
           * Launches the given command in a new process, in the given working
           * directory.
           *
           * @param project The project that the command is part of
           * @param cmd The command to execute
           * @param env The environment for the new process. If null, the
           *      environment of the current proccess is used.
           * @param workingDir The directory to start the command in. If null, 
the
           *      current directory is used
           * @return Description of the Returned Value
           * @exception IOException Description of Exception
           */
          public Process exec( Project project, String[] cmd, String[] env, 
File workingDir )
              throws IOException, TaskException
          {
              if( workingDir == null )
              {
                  return exec( project, cmd, env );
              }
              throw new IOException( "Cannot execute a process in different 
directory under this JVM" );
          }
      }
  
      /**
       * A command launcher that proxies another command launcher. Sub-classes
       * override exec(args, env, workdir)
       *
       * @author RT
       */
      private static class CommandLauncherProxy extends CommandLauncher
      {
  
          private CommandLauncher _launcher;
  
          CommandLauncherProxy( CommandLauncher launcher )
          {
              _launcher = launcher;
          }
  
          /**
           * Launches the given command in a new process. Delegates this method 
to
           * the proxied launcher
           *
           * @param project Description of Parameter
           * @param cmd Description of Parameter
           * @param env Description of Parameter
           * @return Description of the Returned Value
           * @exception IOException Description of Exception
           */
          public Process exec( Project project, String[] cmd, String[] env )
              throws IOException, TaskException
          {
              return _launcher.exec( project, cmd, env );
          }
      }
  
      /**
       * A command launcher for JDK/JRE 1.1 under Windows. Fixes quoting 
problems
       * in Runtime.exec(). Can only launch commands in the current working
       * directory
       *
       * @author RT
       */
      private static class Java11CommandLauncher extends CommandLauncher
      {
          /**
           * Launches the given command in a new process. Needs to quote 
arguments
           *
           * @param project Description of Parameter
           * @param cmd Description of Parameter
           * @param env Description of Parameter
           * @return Description of the Returned Value
           * @exception IOException Description of Exception
           */
          public Process exec( Project project, String[] cmd, String[] env )
              throws IOException, TaskException
          {
              // Need to quote arguments with spaces, and to escape quote 
characters
              String[] newcmd = new String[ cmd.length ];
              for( int i = 0; i < cmd.length; i++ )
              {
                  newcmd[ i ] = Commandline.quoteArgument( cmd[ i ] );
              }
              if( project != null )
              {
                  project.log( "Execute:Java11CommandLauncher: " +
                               Commandline.toString( newcmd ), 
Project.MSG_DEBUG );
              }
              return Runtime.getRuntime().exec( newcmd, env );
          }
      }
  
      /**
       * A command launcher for JDK/JRE 1.3 (and higher). Uses the built-in
       * Runtime.exec() command
       *
       * @author RT
       */
      private static class Java13CommandLauncher extends CommandLauncher
      {
  
          private Method _execWithCWD;
  
          public Java13CommandLauncher()
              throws NoSuchMethodException
          {
              // Locate method Runtime.exec(String[] cmdarray, String[] envp, 
File dir)
              _execWithCWD = Runtime.class.getMethod( "exec", new 
Class[]{String[].class, String[].class, File.class} );
          }
  
          /**
           * Launches the given command in a new process, in the given working
           * directory
           *
           * @param project Description of Parameter
           * @param cmd Description of Parameter
           * @param env Description of Parameter
           * @param workingDir Description of Parameter
           * @return Description of the Returned Value
           * @exception IOException Description of Exception
           */
          public Process exec( Project project, String[] cmd, String[] env, 
File workingDir )
              throws IOException, TaskException
          {
              try
              {
                  if( project != null )
                  {
                      project.log( "Execute:Java13CommandLauncher: " +
                                   Commandline.toString( cmd ), 
Project.MSG_DEBUG );
                  }
                  Object[] arguments = {cmd, env, workingDir};
                  return (Process)_execWithCWD.invoke( Runtime.getRuntime(), 
arguments );
              }
              catch( InvocationTargetException exc )
              {
                  Throwable realexc = exc.getTargetException();
                  if( realexc instanceof ThreadDeath )
                  {
                      throw (ThreadDeath)realexc;
                  }
                  else if( realexc instanceof IOException )
                  {
                      throw (IOException)realexc;
                  }
                  else
                  {
                      throw new TaskException( "Unable to execute command", 
realexc );
                  }
              }
              catch( Exception exc )
              {
                  // IllegalAccess, IllegalArgument, ClassCast
                  throw new TaskException( "Unable to execute command", exc );
              }
          }
      }
  
      /**
       * A command launcher for Mac that uses a dodgy mechanism to change 
working
       * directory before launching commands.
       *
       * @author RT
       */
      private static class MacCommandLauncher extends CommandLauncherProxy
      {
          MacCommandLauncher( CommandLauncher launcher )
          {
              super( launcher );
          }
  
          /**
           * Launches the given command in a new process, in the given working
           * directory
           *
           * @param project Description of Parameter
           * @param cmd Description of Parameter
           * @param env Description of Parameter
           * @param workingDir Description of Parameter
           * @return Description of the Returned Value
           * @exception IOException Description of Exception
           */
          public Process exec( Project project, String[] cmd, String[] env, 
File workingDir )
              throws IOException, TaskException
          {
              if( workingDir == null )
              {
                  return exec( project, cmd, env );
              }
  
              System.getProperties().put( "user.dir", 
workingDir.getAbsolutePath() );
              try
              {
                  return exec( project, cmd, env );
              }
              finally
              {
                  System.getProperties().put( "user.dir", antWorkingDirectory );
              }
          }
      }
  
      /**
       * A command launcher that uses an auxiliary perl script to launch 
commands
       * in directories other than the current working directory.
       *
       * @author RT
       */
      private static class PerlScriptCommandLauncher extends 
CommandLauncherProxy
      {
          private String _script;
  
          PerlScriptCommandLauncher( String script, CommandLauncher launcher )
          {
              super( launcher );
              _script = script;
          }
  
          /**
           * Launches the given command in a new process, in the given working
           * directory
           *
           * @param project Description of Parameter
           * @param cmd Description of Parameter
           * @param env Description of Parameter
           * @param workingDir Description of Parameter
           * @return Description of the Returned Value
           * @exception IOException Description of Exception
           */
          public Process exec( Project project, String[] cmd, String[] env, 
File workingDir )
              throws IOException, TaskException
          {
              if( project == null )
              {
                  if( workingDir == null )
                  {
                      return exec( project, cmd, env );
                  }
                  throw new IOException( "Cannot locate antRun script: No 
project provided" );
              }
  
              // Locate the auxiliary script
              String antHome = project.getProperty( "ant.home" );
              if( antHome == null )
              {
                  throw new IOException( "Cannot locate antRun script: Property 
'ant.home' not found" );
              }
              String antRun = FileUtils.newFileUtils().
                  resolveFile( project.getBaseDir(), antHome + File.separator + 
_script ).toString();
  
              // Build the command
              File commandDir = workingDir;
              if( workingDir == null && project != null )
              {
                  commandDir = project.getBaseDir();
              }
  
              String[] newcmd = new String[ cmd.length + 3 ];
              newcmd[ 0 ] = "perl";
              newcmd[ 1 ] = antRun;
              newcmd[ 2 ] = commandDir.getAbsolutePath();
              System.arraycopy( cmd, 0, newcmd, 3, cmd.length );
  
              return exec( project, newcmd, env );
          }
      }
  
      /**
       * A command launcher that uses an auxiliary script to launch commands in
       * directories other than the current working directory.
       *
       * @author RT
       */
      private static class ScriptCommandLauncher extends CommandLauncherProxy
      {
  
          private String _script;
  
          ScriptCommandLauncher( String script, CommandLauncher launcher )
          {
              super( launcher );
              _script = script;
          }
  
          /**
           * Launches the given command in a new process, in the given working
           * directory
           *
           * @param project Description of Parameter
           * @param cmd Description of Parameter
           * @param env Description of Parameter
           * @param workingDir Description of Parameter
           * @return Description of the Returned Value
           * @exception IOException Description of Exception
           */
          public Process exec( Project project, String[] cmd, String[] env, 
File workingDir )
              throws IOException, TaskException
          {
              if( project == null )
              {
                  if( workingDir == null )
                  {
                      return exec( project, cmd, env );
                  }
                  throw new IOException( "Cannot locate antRun script: No 
project provided" );
              }
  
              // Locate the auxiliary script
              String antHome = project.getProperty( "ant.home" );
              if( antHome == null )
              {
                  throw new IOException( "Cannot locate antRun script: Property 
'ant.home' not found" );
              }
              String antRun = FileUtils.newFileUtils().
                  resolveFile( project.getBaseDir(), antHome + File.separator + 
_script ).toString();
  
              // Build the command
              File commandDir = workingDir;
              if( workingDir == null && project != null )
              {
                  commandDir = project.getBaseDir();
              }
  
              String[] newcmd = new String[ cmd.length + 2 ];
              newcmd[ 0 ] = antRun;
              newcmd[ 1 ] = commandDir.getAbsolutePath();
              System.arraycopy( cmd, 0, newcmd, 2, cmd.length );
  
              return exec( project, newcmd, env );
          }
      }
  
      /**
       * A command launcher for Windows 2000/NT that uses 'cmd.exe' when 
launching
       * commands in directories other than the current working directory.
       *
       * @author RT
       */
      private static class WinNTCommandLauncher extends CommandLauncherProxy
      {
          WinNTCommandLauncher( CommandLauncher launcher )
          {
              super( launcher );
          }
  
          /**
           * Launches the given command in a new process, in the given working
           * directory.
           *
           * @param project Description of Parameter
           * @param cmd Description of Parameter
           * @param env Description of Parameter
           * @param workingDir Description of Parameter
           * @return Description of the Returned Value
           * @exception IOException Description of Exception
           */
          public Process exec( Project project, String[] cmd, String[] env, 
File workingDir )
              throws IOException, TaskException
          {
              File commandDir = workingDir;
              if( workingDir == null )
              {
                  if( project != null )
                  {
                      commandDir = project.getBaseDir();
                  }
                  else
                  {
                      return exec( project, cmd, env );
                  }
              }
  
              // Use cmd.exe to change to the specified directory before running
              // the command
              final int preCmdLength = 6;
              String[] newcmd = new String[ cmd.length + preCmdLength ];
              newcmd[ 0 ] = "cmd";
              newcmd[ 1 ] = "/c";
              newcmd[ 2 ] = "cd";
              newcmd[ 3 ] = "/d";
              newcmd[ 4 ] = commandDir.getAbsolutePath();
              newcmd[ 5 ] = "&&";
              System.arraycopy( cmd, 0, newcmd, preCmdLength, cmd.length );
  
              return exec( project, newcmd, env );
          }
      }
  }
  
  
  
  1.1                  
jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/ExecuteStreamHandler.java
  
  Index: ExecuteStreamHandler.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 file.
   */
  package org.apache.tools.ant.taskdefs.exec;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import org.apache.myrmidon.api.TaskException;
  
  /**
   * Used by <code>Execute</code> to handle input and output stream of
   * subprocesses.
   *
   * @author [EMAIL PROTECTED]
   */
  public interface ExecuteStreamHandler
  {
      /**
       * Install a handler for the input stream of the subprocess.
       *
       * @param os output stream to write to the standard input stream of the
       *      subprocess
       * @exception IOException Description of Exception
       */
      void setProcessInputStream( OutputStream os )
          throws IOException;
  
      /**
       * Install a handler for the error stream of the subprocess.
       *
       * @param is input stream to read from the error stream from the 
subprocess
       * @exception IOException Description of Exception
       */
      void setProcessErrorStream( InputStream is )
          throws IOException;
  
      /**
       * Install a handler for the output stream of the subprocess.
       *
       * @param is input stream to read from the error stream from the 
subprocess
       * @exception IOException Description of Exception
       */
      void setProcessOutputStream( InputStream is )
          throws TaskException, IOException;
  
      /**
       * Start handling of the streams.
       *
       * @exception IOException Description of Exception
       */
      void start()
          throws IOException;
  
      /**
       * Stop handling of the streams - will not be restarted.
       */
      void stop()
          throws TaskException;
  }
  
  
  
  1.1                  
jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/ExecuteWatchdog.java
  
  Index: ExecuteWatchdog.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 file.
   */
  package org.apache.tools.ant.taskdefs.exec;
  
  import org.apache.myrmidon.api.TaskException;
  
  /**
   * Destroys a process running for too long. For example: <pre>
   * ExecuteWatchdog watchdog = new ExecuteWatchdog(30000);
   * Execute exec = new Execute(myloghandler, watchdog);
   * exec.setCommandLine(mycmdline);
   * int exitvalue = exec.execute();
   * if (exitvalue != SUCCESS && watchdog.killedProcess()){
   *              // it was killed on purpose by the watchdog
   * }
   * </pre>
   *
   * @author [EMAIL PROTECTED]
   * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Bailliez</a>
   * @see Execute
   */
  public class ExecuteWatchdog implements Runnable
  {
  
      /**
       * say whether or not the watchog is currently monitoring a process
       */
      private boolean watch = false;
  
      /**
       * exception that might be thrown during the process execution
       */
      private Exception caught = null;
  
      /**
       * say whether or not the process was killed due to running overtime
       */
      private boolean killedProcess = false;
  
      /**
       * the process to execute and watch for duration
       */
      private Process process;
  
      /**
       * timeout duration. Once the process running time exceeds this it should 
be
       * killed
       */
      private int timeout;
  
      /**
       * Creates a new watchdog with a given timeout.
       *
       * @param timeout the timeout for the process in milliseconds. It must be
       *      greather than 0.
       */
      public ExecuteWatchdog( int timeout )
      {
          if( timeout < 1 )
          {
              throw new IllegalArgumentException( "timeout lesser than 1." );
          }
          this.timeout = timeout;
      }
  
      /**
       * Indicates whether or not the watchdog is still monitoring the process.
       *
       * @return <tt>true</tt> if the process is still running, otherwise <tt>
       *      false</tt> .
       */
      public boolean isWatching()
      {
          return watch;
      }
  
      /**
       * This method will rethrow the exception that was possibly caught during
       * the run of the process. It will only remains valid once the process has
       * been terminated either by 'error', timeout or manual intervention.
       * Information will be discarded once a new process is ran.
       *
       * @throws TaskException a wrapped exception over the one that was 
silently
       *      swallowed and stored during the process run.
       */
      public void checkException()
          throws TaskException
      {
          if( caught != null )
          {
              throw new TaskException( "Exception in ExecuteWatchdog.run: "
                                       + caught.getMessage(), caught );
          }
      }
  
      /**
       * Indicates whether the last process run was killed on timeout or not.
       *
       * @return <tt>true</tt> if the process was killed otherwise 
<tt>false</tt>
       *      .
       */
      public boolean killedProcess()
      {
          return killedProcess;
      }
  
      /**
       * Watches the process and terminates it, if it runs for to long.
       */
      public synchronized void run()
      {
          try
          {
              // This isn't a Task, don't have a Project object to log.
              // project.log("ExecuteWatchdog: timeout = "+timeout+" msec",  
Project.MSG_VERBOSE);
              final long until = System.currentTimeMillis() + timeout;
              long now;
              while( watch && until > ( now = System.currentTimeMillis() ) )
              {
                  try
                  {
                      wait( until - now );
                  }
                  catch( InterruptedException e )
                  {
                  }
              }
  
              // if we are here, either someone stopped the watchdog,
              // we are on timeout and the process must be killed, or
              // we are on timeout and the process has already stopped.
              try
              {
                  // We must check if the process was not stopped
                  // before being here
                  process.exitValue();
              }
              catch( IllegalThreadStateException e )
              {
                  // the process is not terminated, if this is really
                  // a timeout and not a manual stop then kill it.
                  if( watch )
                  {
                      killedProcess = true;
                      process.destroy();
                  }
              }
          }
          catch( Exception e )
          {
              caught = e;
          }
          finally
          {
              cleanUp();
          }
      }
  
      /**
       * Watches the given process and terminates it, if it runs for too long. 
All
       * information from the previous run are reset.
       *
       * @param process the process to monitor. It cannot be <tt>null</tt>
       * @throws IllegalStateException thrown if a process is still being
       *      monitored.
       */
      public synchronized void start( Process process )
      {
          if( process == null )
          {
              throw new NullPointerException( "process is null." );
          }
          if( this.process != null )
          {
              throw new IllegalStateException( "Already running." );
          }
          this.caught = null;
          this.killedProcess = false;
          this.watch = true;
          this.process = process;
          final Thread thread = new Thread( this, "WATCHDOG" );
          thread.setDaemon( true );
          thread.start();
      }
  
      /**
       * Stops the watcher. It will notify all threads possibly waiting on this
       * object.
       */
      public synchronized void stop()
      {
          watch = false;
          notifyAll();
      }
  
      /**
       * reset the monitor flag and the process.
       */
      protected void cleanUp()
      {
          watch = false;
          process = null;
      }
  }
  
  
  
  
  1.1                  
jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/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 file.
   */
  package org.apache.tools.ant.taskdefs.exec;
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.Task;
  
  /**
   * Logs each line written to this stream to the log system of ant. Tries to be
   * smart about line separators.<br>
   * TODO: This class can be split to implement other line based processing of
   * data written to the stream.
   *
   * @author [EMAIL PROTECTED]
   */
  public class LogOutputStream extends OutputStream
  {
  
      private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
      private boolean skip = false;
      private int level = Project.MSG_INFO;
  
      private Task task;
  
      /**
       * Creates a new instance of this class.
       *
       * @param task the task for whom to log
       * @param level loglevel used to log data written to this stream.
       */
      public LogOutputStream( Task task, int level )
      {
          this.task = task;
          this.level = level;
      }
  
      public int getMessageLevel()
      {
          return level;
      }
  
      /**
       * Writes all remaining
       *
       * @exception IOException Description of Exception
       */
      public void close()
          throws IOException
      {
          if( buffer.size() > 0 )
              processBuffer();
          super.close();
      }
  
      /**
       * Write the data to the buffer and flush the buffer, if a line separator 
is
       * detected.
       *
       * @param cc data to log (byte).
       * @exception IOException Description of Exception
       */
      public void write( int cc )
          throws IOException
      {
          final byte c = (byte)cc;
          if( ( c == '\n' ) || ( c == '\r' ) )
          {
              if( !skip )
                  processBuffer();
          }
          else
              buffer.write( cc );
          skip = ( c == '\r' );
      }
  
      /**
       * Converts the buffer to a string and sends it to 
<code>processLine</code>
       */
      protected void processBuffer()
      {
          processLine( buffer.toString() );
          buffer.reset();
      }
  
      /**
       * Logs a line to the log system of ant.
       *
       * @param line the line to log.
       */
      protected void processLine( String line )
      {
          processLine( line, level );
      }
  
      /**
       * Logs a line to the log system of ant.
       *
       * @param line the line to log.
       * @param level Description of Parameter
       */
      protected void processLine( String line, int level )
      {
          task.log( line, level );
      }
  }
  
  
  
  1.1                  
jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/LogStreamHandler.java
  
  Index: LogStreamHandler.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 file.
   */
  package org.apache.tools.ant.taskdefs.exec;
  
  import java.io.IOException;
  import org.apache.myrmidon.api.TaskException;
  import org.apache.tools.ant.Task;
  
  /**
   * Logs standard output and error of a subprocess to the log system of ant.
   *
   * @author [EMAIL PROTECTED]
   */
  public class LogStreamHandler
      extends PumpStreamHandler
  {
      /**
       * Creates a new instance of this class.
       *
       * @param task the task for whom to log
       * @param outlevel the loglevel used to log standard output
       * @param errlevel the loglevel used to log standard error
       */
      public LogStreamHandler( Task task, int outlevel, int errlevel )
      {
          super( new LogOutputStream( task, outlevel ),
                 new LogOutputStream( task, errlevel ) );
      }
  
      public void stop()
          throws TaskException
      {
          super.stop();
          try
          {
              getErr().close();
              getOut().close();
          }
          catch( IOException e )
          {
              // plain impossible
              throw new TaskException( "Error", e );
          }
      }
  }
  
  
  
  1.1                  
jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/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 file.
   */
  package org.apache.tools.ant.taskdefs.exec;
  
  import java.lang.reflect.Method;
  import java.util.Enumeration;
  import java.util.Vector;
  
  /**
   * Destroys all registered <code>Process</code>es when the VM exits.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]">Michael Newcomb</a>
   */
  class ProcessDestroyer
      extends Thread
  {
  
      private Vector processes = new Vector();
  
      /**
       * 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)
              //
              Class[] paramTypes = {Thread.class};
              Method addShutdownHook =
                  Runtime.class.getMethod( "addShutdownHook", paramTypes );
  
              // add the hook
              //
              Object[] args = {this};
              addShutdownHook.invoke( Runtime.getRuntime(), args );
          }
          catch( Exception e )
          {
              // it just won't be added as a shutdown hook... :(
          }
      }
  
      /**
       * Returns <code>true</code> if the specified <code>Process</code> was
       * successfully added to the list of processes to destroy upon VM exit.
       *
       * @param process the process to add
       * @return <code>true</code> if the specified <code>Process</code> was
       *      successfully added
       */
      public boolean add( Process process )
      {
          processes.addElement( process );
          return processes.contains( process );
      }
  
      /**
       * Returns <code>true</code> if the specified <code>Process</code> was
       * successfully removed from the list of processes to destroy upon VM 
exit.
       *
       * @param process the process to remove
       * @return <code>true</code> if the specified <code>Process</code> was
       *      successfully removed
       */
      public boolean remove( Process process )
      {
          return processes.removeElement( process );
      }
  
      /**
       * Invoked by the VM when it is exiting.
       */
      public void run()
      {
          synchronized( processes )
          {
              Enumeration e = processes.elements();
              while( e.hasMoreElements() )
              {
                  ( (Process)e.nextElement() ).destroy();
              }
          }
      }
  }
  
  
  
  1.1                  
jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/PumpStreamHandler.java
  
  Index: PumpStreamHandler.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 file.
   */
  package org.apache.tools.ant.taskdefs.exec;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import org.apache.myrmidon.api.TaskException;
  
  /**
   * Copies standard output and error of subprocesses to standard output and 
error
   * of the parent process. TODO: standard input of the subprocess is not
   * implemented.
   *
   * @author [EMAIL PROTECTED]
   */
  public class PumpStreamHandler implements ExecuteStreamHandler
  {
      private Thread errorThread;
  
      private Thread inputThread;
  
      private OutputStream out, err;
  
      public PumpStreamHandler( OutputStream out, OutputStream err )
      {
          this.out = out;
          this.err = err;
      }
  
      public PumpStreamHandler( OutputStream outAndErr )
      {
          this( outAndErr, outAndErr );
      }
  
      public PumpStreamHandler()
      {
          this( System.out, System.err );
      }
  
      public void setProcessErrorStream( InputStream is )
      {
          createProcessErrorPump( is, err );
      }
  
      public void setProcessInputStream( OutputStream os )
      {
      }
  
      public void setProcessOutputStream( InputStream is )
      {
          createProcessOutputPump( is, out );
      }
  
      public void start()
      {
          inputThread.start();
          errorThread.start();
      }
  
      public void stop()
          throws TaskException
      {
          try
          {
              inputThread.join();
          }
          catch( InterruptedException e )
          {
          }
          try
          {
              errorThread.join();
          }
          catch( InterruptedException e )
          {
          }
          try
          {
              err.flush();
          }
          catch( IOException e )
          {
          }
          try
          {
              out.flush();
          }
          catch( IOException e )
          {
          }
      }
  
      protected OutputStream getErr()
      {
          return err;
      }
  
      protected OutputStream getOut()
      {
          return out;
      }
  
      protected void createProcessErrorPump( InputStream is, OutputStream os )
      {
          errorThread = createPump( is, os );
      }
  
      protected void createProcessOutputPump( InputStream is, OutputStream os )
      {
          inputThread = createPump( is, os );
      }
  
      /**
       * Creates a stream pumper to copy the given input stream to the given
       * output stream.
       *
       * @param is Description of Parameter
       * @param os Description of Parameter
       * @return Description of the Returned Value
       */
      protected Thread createPump( InputStream is, OutputStream os )
      {
          final Thread result = new Thread( new StreamPumper( is, os ) );
          result.setDaemon( true );
          return result;
      }
  
  }
  
  
  
  1.1                  
jakarta-ant/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/StreamPumper.java
  
  Index: StreamPumper.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 file.
   */
  package org.apache.tools.ant.taskdefs.exec;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  
  /**
   * Copies all data from an input stream to an output stream.
   *
   * @author [EMAIL PROTECTED]
   */
  public class StreamPumper implements Runnable
  {
  
      // TODO: make SIZE and SLEEP instance variables.
      // TODO: add a status flag to note if an error occured in run.
  
      private final static int SLEEP = 5;
      private final static int SIZE = 128;
      private InputStream is;
      private OutputStream os;
  
      /**
       * Create a new stream pumper.
       *
       * @param is input stream to read data from
       * @param os output stream to write data to.
       */
      public StreamPumper( InputStream is, OutputStream os )
      {
          this.is = is;
          this.os = os;
      }
  
      /**
       * Copies data from the input stream to the output stream. Terminates as
       * soon as the input stream is closed or an error occurs.
       */
      public void run()
      {
          final byte[] buf = new byte[ SIZE ];
  
          int length;
          try
          {
              while( ( length = is.read( buf ) ) > 0 )
              {
                  os.write( buf, 0, length );
                  try
                  {
                      Thread.sleep( SLEEP );
                  }
                  catch( InterruptedException e )
                  {
                  }
              }
          }
          catch( IOException e )
          {
          }
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to