git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271341 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -1,414 +0,0 @@ | |||
| /* | |||
| * 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.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 java.util.Iterator; | |||
| import java.util.Properties; | |||
| import org.apache.avalon.excalibur.util.StringUtil; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.types.Argument; | |||
| import org.apache.tools.ant.types.Commandline; | |||
| import org.apache.tools.ant.types.EnvironmentData; | |||
| import org.apache.tools.ant.types.EnvironmentVariable; | |||
| /** | |||
| * Executes a given command if the os platform is appropriate. | |||
| * | |||
| * @author duncan@x180.com | |||
| * @author rubys@us.ibm.com | |||
| * @author thomas.haas@softwired-inc.com | |||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
| * @author <a href="mailto:mariusz@rakiura.org">Mariusz Nowostawski</a> | |||
| */ | |||
| public class ExecTask | |||
| extends Task | |||
| { | |||
| private boolean m_newEnvironment; | |||
| private Integer m_timeout; | |||
| private EnvironmentData m_env = new EnvironmentData(); | |||
| private Commandline m_command = new Commandline(); | |||
| private FileOutputStream m_ouput; | |||
| private ByteArrayOutputStream m_byteArrayOutput; | |||
| /** | |||
| * Controls whether the VM (1.3 and above) is used to execute the command | |||
| */ | |||
| private boolean m_useVMLauncher = true; | |||
| private File m_workingDirectory; | |||
| private String m_os; | |||
| private File m_outputFile; | |||
| private String m_outputProperty; | |||
| private String m_resultProperty; | |||
| /** | |||
| * The working directory of the process | |||
| * | |||
| * @param d The new Dir value | |||
| */ | |||
| public void setDir( final File dir ) | |||
| throws TaskException | |||
| { | |||
| m_workingDirectory = dir; | |||
| } | |||
| /** | |||
| * The command to execute. | |||
| */ | |||
| public void setExecutable( final String value ) | |||
| throws TaskException | |||
| { | |||
| m_command.setExecutable( value ); | |||
| } | |||
| /** | |||
| * Use a completely new environment | |||
| */ | |||
| public void setNewenvironment( final boolean newEnvironment ) | |||
| { | |||
| m_newEnvironment = newEnvironment; | |||
| } | |||
| /** | |||
| * Only execute the process if <code>os.name</code> is included in this | |||
| * string. | |||
| * | |||
| * @param os The new Os value | |||
| */ | |||
| public void setOs( final String os ) | |||
| { | |||
| m_os = os; | |||
| } | |||
| /** | |||
| * File the output of the process is redirected to. | |||
| * | |||
| * @param out The new Output value | |||
| */ | |||
| public void setOutput( final File outputFile ) | |||
| { | |||
| m_outputFile = outputFile; | |||
| } | |||
| /** | |||
| * Property name whose value should be set to the output of the process | |||
| * | |||
| * @param outputprop The new Outputproperty value | |||
| */ | |||
| public void setOutputproperty( final String outputprop ) | |||
| { | |||
| m_outputProperty = 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( final String resultProperty ) | |||
| { | |||
| m_resultProperty = resultProperty; | |||
| } | |||
| /** | |||
| * Timeout in milliseconds after which the process will be killed. | |||
| * | |||
| * @param value The new Timeout value | |||
| */ | |||
| public void setTimeout( final Integer timeout ) | |||
| { | |||
| m_timeout = timeout; | |||
| } | |||
| /** | |||
| * 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( final boolean vmLauncher ) | |||
| { | |||
| m_useVMLauncher = vmLauncher; | |||
| } | |||
| /** | |||
| * Add a nested env element - an environment variable. | |||
| * | |||
| * @param var The feature to be added to the Env attribute | |||
| */ | |||
| public void addEnv( final EnvironmentVariable var ) | |||
| { | |||
| m_env.addVariable( var ); | |||
| } | |||
| /** | |||
| * Add a nested arg element - a command line argument. | |||
| */ | |||
| public void addArg( final Argument argument ) | |||
| { | |||
| m_command.addArgument( argument ); | |||
| } | |||
| /** | |||
| * Do the work. | |||
| * | |||
| * @exception TaskException Description of Exception | |||
| */ | |||
| public void execute() | |||
| throws TaskException | |||
| { | |||
| validate(); | |||
| if( isValidOs() ) | |||
| { | |||
| runExec( prepareExec() ); | |||
| } | |||
| } | |||
| /** | |||
| * Is this the OS the user wanted? | |||
| * | |||
| * @return The ValidOs value | |||
| */ | |||
| protected boolean isValidOs() | |||
| { | |||
| // test if os match | |||
| final String os = System.getProperty( "os.name" ); | |||
| getLogger().debug( "Current OS is " + os ); | |||
| if( ( m_os != null ) && ( m_os.indexOf( os ) < 0 ) ) | |||
| { | |||
| // this command will be executed only on the specified OS | |||
| getLogger().debug( "This OS, " + os + " was not found in the specified list of valid OSes: " + m_os ); | |||
| 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( final Execute exe ) | |||
| throws IOException, TaskException | |||
| { | |||
| final int err = exe.execute(); | |||
| //test for and handle a forced process death | |||
| maybeSetResultPropertyValue( err ); | |||
| if( 0 != err ) | |||
| { | |||
| throw new TaskException( getContext().getName() + " returned: " + err ); | |||
| } | |||
| if( null != m_byteArrayOutput ) | |||
| { | |||
| writeResultToProperty(); | |||
| } | |||
| } | |||
| private void writeResultToProperty() throws IOException, TaskException | |||
| { | |||
| final BufferedReader input = | |||
| new BufferedReader( new StringReader( m_byteArrayOutput.toString() ) ); | |||
| String line = null; | |||
| StringBuffer val = new StringBuffer(); | |||
| while( ( line = input.readLine() ) != null ) | |||
| { | |||
| if( val.length() != 0 ) | |||
| { | |||
| val.append( StringUtil.LINE_SEPARATOR ); | |||
| } | |||
| val.append( line ); | |||
| } | |||
| final String name = m_outputProperty; | |||
| final Object value = val.toString(); | |||
| getContext().setProperty( name, value ); | |||
| } | |||
| /** | |||
| * Has the user set all necessary attributes? | |||
| * | |||
| * @exception TaskException Description of Exception | |||
| */ | |||
| protected void validate() | |||
| throws TaskException | |||
| { | |||
| if( m_command.getExecutable() == null ) | |||
| { | |||
| throw new TaskException( "no executable specified" ); | |||
| } | |||
| if( m_workingDirectory != null && !m_workingDirectory.exists() ) | |||
| { | |||
| throw new TaskException( "The directory you specified does not exist" ); | |||
| } | |||
| if( m_workingDirectory != null && !m_workingDirectory.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 | |||
| */ | |||
| private void setupOutput( final Execute exe ) | |||
| throws TaskException | |||
| { | |||
| if( m_outputFile != null ) | |||
| { | |||
| try | |||
| { | |||
| m_ouput = new FileOutputStream( m_outputFile ); | |||
| getLogger().debug( "Output redirected to " + m_outputFile ); | |||
| exe.setOutput( m_ouput ); | |||
| exe.setError( m_ouput ); | |||
| } | |||
| catch( FileNotFoundException fne ) | |||
| { | |||
| throw new TaskException( "Cannot write to " + m_outputFile, fne ); | |||
| } | |||
| catch( IOException ioe ) | |||
| { | |||
| throw new TaskException( "Cannot write to " + m_outputFile, ioe ); | |||
| } | |||
| } | |||
| else if( m_outputProperty != null ) | |||
| { | |||
| m_byteArrayOutput = new ByteArrayOutputStream(); | |||
| getLogger().debug( "Output redirected to ByteArray" ); | |||
| exe.setOutput( m_byteArrayOutput ); | |||
| exe.setError( m_byteArrayOutput ); | |||
| } | |||
| else | |||
| { | |||
| exe.setOutput( new LogOutputStream( getLogger(), false ) ); | |||
| exe.setError( new LogOutputStream( getLogger(), true ) ); | |||
| } | |||
| } | |||
| /** | |||
| * Flush the output stream - if there is one. | |||
| */ | |||
| protected void logFlush() | |||
| { | |||
| try | |||
| { | |||
| if( m_ouput != null ) | |||
| { | |||
| m_ouput.close(); | |||
| } | |||
| if( m_byteArrayOutput != null ) | |||
| { | |||
| m_byteArrayOutput.close(); | |||
| } | |||
| } | |||
| catch( IOException io ) | |||
| { | |||
| } | |||
| } | |||
| /** | |||
| * helper method to set result property to the passed in value if | |||
| * appropriate | |||
| */ | |||
| protected void maybeSetResultPropertyValue( int result ) | |||
| throws TaskException | |||
| { | |||
| final String res = Integer.toString( result ); | |||
| if( m_resultProperty != null ) | |||
| { | |||
| final String name = m_resultProperty; | |||
| getContext().setProperty( name, res ); | |||
| } | |||
| } | |||
| /** | |||
| * Create an Execute instance with the correct working directory set. | |||
| */ | |||
| protected Execute prepareExec() | |||
| throws TaskException | |||
| { | |||
| // default directory to the project's base directory | |||
| if( m_workingDirectory == null ) | |||
| { | |||
| m_workingDirectory = getBaseDirectory(); | |||
| } | |||
| // show the command | |||
| getLogger().debug( m_command.toString() ); | |||
| final Execute exe = new Execute(); | |||
| setupOutput( exe ); | |||
| if( null != m_timeout ) | |||
| { | |||
| exe.setTimeout( m_timeout.intValue() ); | |||
| } | |||
| exe.setWorkingDirectory( m_workingDirectory ); | |||
| exe.setVMLauncher( m_useVMLauncher ); | |||
| exe.setNewenvironment( m_newEnvironment ); | |||
| final Properties environment = m_env.getVariables(); | |||
| final Iterator keys = environment.keySet().iterator(); | |||
| while( keys.hasNext() ) | |||
| { | |||
| final String key = (String)keys.next(); | |||
| final String value = environment.getProperty( key ); | |||
| getLogger().debug( "Setting environment variable: " + key + "=" + value ); | |||
| } | |||
| 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( final Execute exe ) | |||
| throws TaskException | |||
| { | |||
| exe.setCommandline( m_command.getCommandline() ); | |||
| try | |||
| { | |||
| runExecute( exe ); | |||
| } | |||
| catch( IOException e ) | |||
| { | |||
| throw new TaskException( "Execute failed: " + e.toString(), e ); | |||
| } | |||
| finally | |||
| { | |||
| // close the output file if required | |||
| logFlush(); | |||
| } | |||
| } | |||
| protected final Commandline getCommand() | |||
| { | |||
| return m_command; | |||
| } | |||
| } | |||
| @@ -1,142 +0,0 @@ | |||
| /* | |||
| * 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.tools.ant.taskdefs.exec; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.OutputStream; | |||
| import java.util.Properties; | |||
| import org.apache.aut.nativelib.ExecException; | |||
| import org.apache.aut.nativelib.ExecManager; | |||
| import org.apache.aut.nativelib.ExecMetaData; | |||
| import org.apache.avalon.excalibur.io.IOUtil; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| import org.apache.myrmidon.framework.factorys.ExecManagerFactory; | |||
| import org.apache.myrmidon.interfaces.service.ServiceException; | |||
| /** | |||
| * Runs an external program. | |||
| * | |||
| * @author thomas.haas@softwired-inc.com | |||
| */ | |||
| public class Execute | |||
| { | |||
| private String[] m_command; | |||
| private Properties m_environment = new Properties(); | |||
| private File m_workingDirectory = new File( "." ); | |||
| private boolean m_newEnvironment; | |||
| private OutputStream m_output; | |||
| private OutputStream m_error; | |||
| private long m_timeout; | |||
| /** | |||
| * Controls whether the VM is used to launch commands, where possible | |||
| */ | |||
| private boolean m_useVMLauncher = true; | |||
| public void setTimeout( final long timeout ) | |||
| { | |||
| m_timeout = timeout; | |||
| } | |||
| public void setOutput( final OutputStream output ) | |||
| { | |||
| m_output = output; | |||
| } | |||
| public void setError( final OutputStream error ) | |||
| { | |||
| m_error = error; | |||
| } | |||
| /** | |||
| * Sets the commandline of the subprocess to launch. | |||
| * | |||
| * @param commandline the commandline of the subprocess to launch | |||
| */ | |||
| public void setCommandline( String[] commandline ) | |||
| { | |||
| m_command = commandline; | |||
| } | |||
| public void setEnvironment( final Properties environment ) | |||
| { | |||
| if( null == environment ) | |||
| { | |||
| throw new NullPointerException( "environment" ); | |||
| } | |||
| m_environment = environment; | |||
| } | |||
| /** | |||
| * Set whether to propagate the default environment or not. | |||
| * | |||
| * @param newenv whether to propagate the process environment. | |||
| */ | |||
| public void setNewenvironment( boolean newEnvironment ) | |||
| { | |||
| m_newEnvironment = newEnvironment; | |||
| } | |||
| /** | |||
| * 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 ) | |||
| { | |||
| m_useVMLauncher = useVMLauncher; | |||
| } | |||
| /** | |||
| * Sets the working directory of the process to execute. <p> | |||
| * | |||
| * @param workingDirectory the working directory of the process. | |||
| */ | |||
| public void setWorkingDirectory( final File workingDirectory ) | |||
| { | |||
| m_workingDirectory = workingDirectory; | |||
| } | |||
| /** | |||
| * 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 | |||
| { | |||
| try | |||
| { | |||
| final ExecManagerFactory factory = new ExecManagerFactory(); | |||
| final ExecManager manager = (ExecManager)factory.createService(); | |||
| final ExecMetaData metaData = | |||
| new ExecMetaData( m_command, m_environment, | |||
| m_workingDirectory, m_newEnvironment ); | |||
| return manager.execute( metaData, null, m_output, m_error, m_timeout ); | |||
| } | |||
| catch( final ExecException ee ) | |||
| { | |||
| throw new TaskException( ee.getMessage(), ee ); | |||
| } | |||
| catch( final ServiceException se ) | |||
| { | |||
| throw new TaskException( se.getMessage(), se ); | |||
| } | |||
| finally | |||
| { | |||
| IOUtil.shutdownStream( m_output ); | |||
| IOUtil.shutdownStream( m_error ); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,440 +0,0 @@ | |||
| /* | |||
| * 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.tools.ant.taskdefs.exec; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.util.ArrayList; | |||
| import java.util.Hashtable; | |||
| import org.apache.avalon.excalibur.util.StringUtil; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| import org.apache.tools.ant.types.DirectoryScanner; | |||
| import org.apache.tools.ant.types.FileSet; | |||
| import org.apache.tools.ant.types.Marker; | |||
| import org.apache.tools.ant.types.ScannerUtil; | |||
| import org.apache.tools.ant.types.SourceFileScanner; | |||
| import org.apache.tools.ant.util.mappers.FileNameMapper; | |||
| import org.apache.tools.ant.util.mappers.Mapper; | |||
| /** | |||
| * Executes a given command, supplying a set of files as arguments. | |||
| * | |||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
| * @author <a href="mailto:mariusz@rakiura.org">Mariusz Nowostawski</a> | |||
| */ | |||
| public class ExecuteOn | |||
| extends ExecTask | |||
| { | |||
| private ArrayList m_filesets = new ArrayList(); | |||
| private boolean m_relative; | |||
| private boolean m_parallel; | |||
| private String m_type = "file"; | |||
| private Marker m_srcFilePos; | |||
| private boolean m_skipEmpty; | |||
| private Marker m_targetFilePos; | |||
| private Mapper m_mapperElement; | |||
| private FileNameMapper m_mapper; | |||
| private File m_destDir; | |||
| /** | |||
| * Has <srcfile> been specified before <targetfile> | |||
| */ | |||
| private boolean m_srcIsFirst = true; | |||
| /** | |||
| * Set the destination directory. | |||
| */ | |||
| public void setDest( final File destDir ) | |||
| { | |||
| m_destDir = destDir; | |||
| } | |||
| /** | |||
| * Shall the command work on all specified files in parallel? | |||
| */ | |||
| public void setParallel( final boolean parallel ) | |||
| { | |||
| m_parallel = parallel; | |||
| } | |||
| /** | |||
| * Should filenames be returned as relative path names? | |||
| */ | |||
| public void setRelative( final boolean relative ) | |||
| { | |||
| m_relative = relative; | |||
| } | |||
| /** | |||
| * Should empty filesets be ignored? | |||
| */ | |||
| public void setSkipEmptyFilesets( final boolean skip ) | |||
| { | |||
| m_skipEmpty = skip; | |||
| } | |||
| /** | |||
| * Shall the command work only on files, directories or both? | |||
| */ | |||
| public void setType( final FileDirBoth type ) | |||
| { | |||
| m_type = type.getValue(); | |||
| } | |||
| /** | |||
| * Adds a set of files (nested fileset attribute). | |||
| */ | |||
| public void addFileset( final FileSet set ) | |||
| { | |||
| m_filesets.add( set ); | |||
| } | |||
| /** | |||
| * Defines the FileNameMapper to use (nested mapper element). | |||
| */ | |||
| public Mapper createMapper() | |||
| throws TaskException | |||
| { | |||
| if( m_mapperElement != null ) | |||
| { | |||
| throw new TaskException( "Cannot define more than one mapper" ); | |||
| } | |||
| m_mapperElement = new Mapper(); | |||
| return m_mapperElement; | |||
| } | |||
| /** | |||
| * Marker that indicates where the name of the source file should be put on | |||
| * the command line. | |||
| */ | |||
| public Marker createSrcfile() | |||
| throws TaskException | |||
| { | |||
| if( m_srcFilePos != null ) | |||
| { | |||
| throw new TaskException( getContext().getName() + " doesn\'t support multiple srcfile elements." ); | |||
| } | |||
| m_srcFilePos = getCommand().createMarker(); | |||
| return m_srcFilePos; | |||
| } | |||
| /** | |||
| * Marker that indicates where the name of the target file should be put on | |||
| * the command line. | |||
| */ | |||
| public Marker createTargetfile() | |||
| throws TaskException | |||
| { | |||
| if( m_targetFilePos != null ) | |||
| { | |||
| throw new TaskException( getContext().getName() + " doesn\'t support multiple targetfile elements." ); | |||
| } | |||
| m_targetFilePos = getCommand().createMarker(); | |||
| m_srcIsFirst = ( m_srcFilePos != null ); | |||
| return m_targetFilePos; | |||
| } | |||
| /** | |||
| * Construct the command line for parallel execution. | |||
| * | |||
| * @param srcFiles The filenames to add to the commandline | |||
| */ | |||
| protected String[] getCommandline( final String[] srcFiles, | |||
| final File[] baseDirs ) | |||
| throws TaskException | |||
| { | |||
| final ArrayList targets = new ArrayList(); | |||
| if( m_targetFilePos != null ) | |||
| { | |||
| Hashtable addedFiles = new Hashtable(); | |||
| for( int i = 0; i < srcFiles.length; i++ ) | |||
| { | |||
| String[] subTargets = m_mapper.mapFileName( srcFiles[ i ] ); | |||
| if( subTargets != null ) | |||
| { | |||
| for( int j = 0; j < subTargets.length; j++ ) | |||
| { | |||
| String name = null; | |||
| if( !m_relative ) | |||
| { | |||
| name = | |||
| ( new File( m_destDir, subTargets[ j ] ) ).getAbsolutePath(); | |||
| } | |||
| else | |||
| { | |||
| name = subTargets[ j ]; | |||
| } | |||
| if( !addedFiles.contains( name ) ) | |||
| { | |||
| targets.add( name ); | |||
| addedFiles.put( name, name ); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| String[] targetFiles = new String[ targets.size() ]; | |||
| targetFiles = (String[])targets.toArray( targetFiles ); | |||
| String[] orig = getCommand().getCommandline(); | |||
| String[] result = new String[ orig.length + srcFiles.length + targetFiles.length ]; | |||
| int srcIndex = orig.length; | |||
| if( m_srcFilePos != null ) | |||
| { | |||
| srcIndex = m_srcFilePos.getPosition(); | |||
| } | |||
| if( m_targetFilePos != null ) | |||
| { | |||
| int targetIndex = m_targetFilePos.getPosition(); | |||
| if( srcIndex < targetIndex | |||
| || ( srcIndex == targetIndex && m_srcIsFirst ) ) | |||
| { | |||
| // 0 --> srcIndex | |||
| System.arraycopy( orig, 0, result, 0, srcIndex ); | |||
| // srcIndex --> targetIndex | |||
| System.arraycopy( orig, srcIndex, result, | |||
| srcIndex + srcFiles.length, | |||
| targetIndex - srcIndex ); | |||
| // targets are already absolute file names | |||
| System.arraycopy( targetFiles, 0, result, | |||
| targetIndex + srcFiles.length, | |||
| targetFiles.length ); | |||
| // targetIndex --> end | |||
| System.arraycopy( orig, targetIndex, result, | |||
| targetIndex + srcFiles.length + targetFiles.length, | |||
| orig.length - targetIndex ); | |||
| } | |||
| else | |||
| { | |||
| // 0 --> targetIndex | |||
| System.arraycopy( orig, 0, result, 0, targetIndex ); | |||
| // targets are already absolute file names | |||
| System.arraycopy( targetFiles, 0, result, | |||
| targetIndex, | |||
| targetFiles.length ); | |||
| // targetIndex --> srcIndex | |||
| System.arraycopy( orig, targetIndex, result, | |||
| targetIndex + targetFiles.length, | |||
| srcIndex - targetIndex ); | |||
| // srcIndex --> end | |||
| System.arraycopy( orig, srcIndex, result, | |||
| srcIndex + srcFiles.length + targetFiles.length, | |||
| orig.length - srcIndex ); | |||
| srcIndex += targetFiles.length; | |||
| } | |||
| } | |||
| else | |||
| {// no targetFilePos | |||
| // 0 --> srcIndex | |||
| System.arraycopy( orig, 0, result, 0, srcIndex ); | |||
| // srcIndex --> end | |||
| System.arraycopy( orig, srcIndex, result, | |||
| srcIndex + srcFiles.length, | |||
| orig.length - srcIndex ); | |||
| } | |||
| // fill in source file names | |||
| for( int i = 0; i < srcFiles.length; i++ ) | |||
| { | |||
| if( !m_relative ) | |||
| { | |||
| result[ srcIndex + i ] = | |||
| ( new File( baseDirs[ i ], srcFiles[ i ] ) ).getAbsolutePath(); | |||
| } | |||
| else | |||
| { | |||
| result[ srcIndex + i ] = srcFiles[ i ]; | |||
| } | |||
| } | |||
| return result; | |||
| } | |||
| /** | |||
| * Construct the command line for serial execution. | |||
| * | |||
| * @param srcFile The filename to add to the commandline | |||
| * @param baseDir filename is relative to this dir | |||
| * @return The Commandline value | |||
| */ | |||
| protected String[] getCommandline( final String srcFile, | |||
| final File baseDir ) | |||
| throws TaskException | |||
| { | |||
| return getCommandline( new String[]{srcFile}, new File[]{baseDir} ); | |||
| } | |||
| /** | |||
| * Return the list of Directories from this DirectoryScanner that should be | |||
| * included on the command line. | |||
| * | |||
| * @param baseDir Description of Parameter | |||
| * @param ds Description of Parameter | |||
| * @return The Dirs value | |||
| */ | |||
| protected String[] getDirs( final File baseDir, | |||
| final DirectoryScanner ds ) | |||
| throws TaskException | |||
| { | |||
| if( m_mapper != null ) | |||
| { | |||
| final SourceFileScanner scanner = new SourceFileScanner(); | |||
| setupLogger( scanner ); | |||
| return scanner.restrict( ds.getIncludedDirectories(), baseDir, m_destDir, | |||
| m_mapper ); | |||
| } | |||
| else | |||
| { | |||
| return ds.getIncludedDirectories(); | |||
| } | |||
| } | |||
| /** | |||
| * Return the list of files from this DirectoryScanner that should be | |||
| * included on the command line. | |||
| * | |||
| * @param baseDir Description of Parameter | |||
| * @param ds Description of Parameter | |||
| * @return The Files value | |||
| */ | |||
| protected String[] getFiles( final File baseDir, | |||
| final DirectoryScanner ds ) | |||
| throws TaskException | |||
| { | |||
| if( m_mapper != null ) | |||
| { | |||
| final SourceFileScanner scanner = new SourceFileScanner(); | |||
| setupLogger( scanner ); | |||
| return scanner.restrict( ds.getIncludedFiles(), baseDir, m_destDir, | |||
| m_mapper ); | |||
| } | |||
| else | |||
| { | |||
| return ds.getIncludedFiles(); | |||
| } | |||
| } | |||
| protected void validate() | |||
| throws TaskException | |||
| { | |||
| super.validate(); | |||
| if( m_filesets.size() == 0 ) | |||
| { | |||
| final String message = "no filesets specified"; | |||
| throw new TaskException( message ); | |||
| } | |||
| if( m_targetFilePos != null || | |||
| m_mapperElement != null || | |||
| m_destDir != null ) | |||
| { | |||
| if( m_mapperElement == null ) | |||
| { | |||
| final String message = "no mapper specified"; | |||
| throw new TaskException( message ); | |||
| } | |||
| if( m_mapperElement == null ) | |||
| { | |||
| final String message = "no dest attribute specified"; | |||
| throw new TaskException( message ); | |||
| } | |||
| m_mapper = m_mapperElement.getImplementation(); | |||
| } | |||
| } | |||
| protected void runExec( final Execute exe ) | |||
| throws TaskException | |||
| { | |||
| try | |||
| { | |||
| final ArrayList fileNames = new ArrayList(); | |||
| final ArrayList baseDirs = new ArrayList(); | |||
| for( int i = 0; i < m_filesets.size(); i++ ) | |||
| { | |||
| final FileSet fs = (FileSet)m_filesets.get( i ); | |||
| final File base = fs.getDir(); | |||
| final DirectoryScanner ds = ScannerUtil.getDirectoryScanner( fs ); | |||
| if( !"dir".equals( m_type ) ) | |||
| { | |||
| final String[] s = getFiles( base, ds ); | |||
| for( int j = 0; j < s.length; j++ ) | |||
| { | |||
| fileNames.add( s[ j ] ); | |||
| baseDirs.add( base ); | |||
| } | |||
| } | |||
| if( !"file".equals( m_type ) ) | |||
| { | |||
| final String[] s = getDirs( base, ds ); | |||
| for( int j = 0; j < s.length; j++ ) | |||
| { | |||
| fileNames.add( s[ j ] ); | |||
| baseDirs.add( base ); | |||
| } | |||
| } | |||
| if( fileNames.size() == 0 && m_skipEmpty ) | |||
| { | |||
| getLogger().info( "Skipping fileset for directory " + base + ". It is empty." ); | |||
| continue; | |||
| } | |||
| if( !m_parallel ) | |||
| { | |||
| String[] s = new String[ fileNames.size() ]; | |||
| s = (String[])fileNames.toArray( s ); | |||
| for( int j = 0; j < s.length; j++ ) | |||
| { | |||
| String[] command = getCommandline( s[ j ], base ); | |||
| getLogger().debug( "Executing " + StringUtil.join( command, " " ) ); | |||
| exe.setCommandline( command ); | |||
| runExecute( exe ); | |||
| } | |||
| fileNames.clear(); | |||
| baseDirs.clear(); | |||
| } | |||
| } | |||
| if( m_parallel && ( fileNames.size() > 0 || !m_skipEmpty ) ) | |||
| { | |||
| String[] s = new String[ fileNames.size() ]; | |||
| s = (String[])fileNames.toArray( s ); | |||
| File[] b = new File[ baseDirs.size() ]; | |||
| b = (File[])baseDirs.toArray( b ); | |||
| String[] command = getCommandline( s, b ); | |||
| getLogger().debug( "Executing " + StringUtil.join( command, " " ) ); | |||
| exe.setCommandline( command ); | |||
| runExecute( exe ); | |||
| } | |||
| } | |||
| catch( IOException e ) | |||
| { | |||
| throw new TaskException( "Execute failed: " + e, e ); | |||
| } | |||
| finally | |||
| { | |||
| // close the output file if required | |||
| logFlush(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,23 +0,0 @@ | |||
| /* | |||
| * 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.tools.ant.taskdefs.exec; | |||
| import org.apache.tools.ant.types.EnumeratedAttribute; | |||
| /** | |||
| * Enumerated attribute with the values "file", "dir" and "both" for the | |||
| * type attribute. | |||
| */ | |||
| public class FileDirBoth | |||
| extends EnumeratedAttribute | |||
| { | |||
| public String[] getValues() | |||
| { | |||
| return new String[]{"file", "dir", "both"}; | |||
| } | |||
| } | |||
| @@ -1,114 +0,0 @@ | |||
| /* | |||
| * 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.tools.ant.taskdefs.exec; | |||
| import java.io.ByteArrayOutputStream; | |||
| import java.io.IOException; | |||
| import java.io.OutputStream; | |||
| import org.apache.avalon.framework.logger.Logger; | |||
| /** | |||
| * 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 thomas.haas@softwired-inc.com | |||
| */ | |||
| public class LogOutputStream | |||
| extends OutputStream | |||
| { | |||
| private final boolean m_isError; | |||
| private final Logger m_logger; | |||
| private ByteArrayOutputStream m_buffer = new ByteArrayOutputStream(); | |||
| private boolean m_skip; | |||
| public LogOutputStream( final Logger logger, final boolean isError ) | |||
| { | |||
| m_logger = logger; | |||
| m_isError = isError; | |||
| } | |||
| protected final Logger getLogger() | |||
| { | |||
| return m_logger; | |||
| } | |||
| /** | |||
| * Writes all remaining | |||
| * | |||
| * @exception IOException Description of Exception | |||
| */ | |||
| 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 cc data to log (byte). | |||
| * @exception IOException Description of Exception | |||
| */ | |||
| 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>processLine</code> | |||
| */ | |||
| private void processBuffer() | |||
| { | |||
| processLine( m_buffer.toString() ); | |||
| m_buffer.reset(); | |||
| } | |||
| /** | |||
| * Logs a line to the log system of ant. | |||
| * | |||
| * @param line the line to log. | |||
| * @param level Description of Parameter | |||
| */ | |||
| protected void processLine( final String line ) | |||
| { | |||
| if( m_isError ) | |||
| { | |||
| getLogger().warn( line ); | |||
| } | |||
| else | |||
| { | |||
| getLogger().info( line ); | |||
| } | |||
| } | |||
| public boolean isError() | |||
| { | |||
| return m_isError; | |||
| } | |||
| } | |||
| @@ -1,414 +0,0 @@ | |||
| /* | |||
| * 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.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 java.util.Iterator; | |||
| import java.util.Properties; | |||
| import org.apache.avalon.excalibur.util.StringUtil; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.types.Argument; | |||
| import org.apache.tools.ant.types.Commandline; | |||
| import org.apache.tools.ant.types.EnvironmentData; | |||
| import org.apache.tools.ant.types.EnvironmentVariable; | |||
| /** | |||
| * Executes a given command if the os platform is appropriate. | |||
| * | |||
| * @author duncan@x180.com | |||
| * @author rubys@us.ibm.com | |||
| * @author thomas.haas@softwired-inc.com | |||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
| * @author <a href="mailto:mariusz@rakiura.org">Mariusz Nowostawski</a> | |||
| */ | |||
| public class ExecTask | |||
| extends Task | |||
| { | |||
| private boolean m_newEnvironment; | |||
| private Integer m_timeout; | |||
| private EnvironmentData m_env = new EnvironmentData(); | |||
| private Commandline m_command = new Commandline(); | |||
| private FileOutputStream m_ouput; | |||
| private ByteArrayOutputStream m_byteArrayOutput; | |||
| /** | |||
| * Controls whether the VM (1.3 and above) is used to execute the command | |||
| */ | |||
| private boolean m_useVMLauncher = true; | |||
| private File m_workingDirectory; | |||
| private String m_os; | |||
| private File m_outputFile; | |||
| private String m_outputProperty; | |||
| private String m_resultProperty; | |||
| /** | |||
| * The working directory of the process | |||
| * | |||
| * @param d The new Dir value | |||
| */ | |||
| public void setDir( final File dir ) | |||
| throws TaskException | |||
| { | |||
| m_workingDirectory = dir; | |||
| } | |||
| /** | |||
| * The command to execute. | |||
| */ | |||
| public void setExecutable( final String value ) | |||
| throws TaskException | |||
| { | |||
| m_command.setExecutable( value ); | |||
| } | |||
| /** | |||
| * Use a completely new environment | |||
| */ | |||
| public void setNewenvironment( final boolean newEnvironment ) | |||
| { | |||
| m_newEnvironment = newEnvironment; | |||
| } | |||
| /** | |||
| * Only execute the process if <code>os.name</code> is included in this | |||
| * string. | |||
| * | |||
| * @param os The new Os value | |||
| */ | |||
| public void setOs( final String os ) | |||
| { | |||
| m_os = os; | |||
| } | |||
| /** | |||
| * File the output of the process is redirected to. | |||
| * | |||
| * @param out The new Output value | |||
| */ | |||
| public void setOutput( final File outputFile ) | |||
| { | |||
| m_outputFile = outputFile; | |||
| } | |||
| /** | |||
| * Property name whose value should be set to the output of the process | |||
| * | |||
| * @param outputprop The new Outputproperty value | |||
| */ | |||
| public void setOutputproperty( final String outputprop ) | |||
| { | |||
| m_outputProperty = 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( final String resultProperty ) | |||
| { | |||
| m_resultProperty = resultProperty; | |||
| } | |||
| /** | |||
| * Timeout in milliseconds after which the process will be killed. | |||
| * | |||
| * @param value The new Timeout value | |||
| */ | |||
| public void setTimeout( final Integer timeout ) | |||
| { | |||
| m_timeout = timeout; | |||
| } | |||
| /** | |||
| * 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( final boolean vmLauncher ) | |||
| { | |||
| m_useVMLauncher = vmLauncher; | |||
| } | |||
| /** | |||
| * Add a nested env element - an environment variable. | |||
| * | |||
| * @param var The feature to be added to the Env attribute | |||
| */ | |||
| public void addEnv( final EnvironmentVariable var ) | |||
| { | |||
| m_env.addVariable( var ); | |||
| } | |||
| /** | |||
| * Add a nested arg element - a command line argument. | |||
| */ | |||
| public void addArg( final Argument argument ) | |||
| { | |||
| m_command.addArgument( argument ); | |||
| } | |||
| /** | |||
| * Do the work. | |||
| * | |||
| * @exception TaskException Description of Exception | |||
| */ | |||
| public void execute() | |||
| throws TaskException | |||
| { | |||
| validate(); | |||
| if( isValidOs() ) | |||
| { | |||
| runExec( prepareExec() ); | |||
| } | |||
| } | |||
| /** | |||
| * Is this the OS the user wanted? | |||
| * | |||
| * @return The ValidOs value | |||
| */ | |||
| protected boolean isValidOs() | |||
| { | |||
| // test if os match | |||
| final String os = System.getProperty( "os.name" ); | |||
| getLogger().debug( "Current OS is " + os ); | |||
| if( ( m_os != null ) && ( m_os.indexOf( os ) < 0 ) ) | |||
| { | |||
| // this command will be executed only on the specified OS | |||
| getLogger().debug( "This OS, " + os + " was not found in the specified list of valid OSes: " + m_os ); | |||
| 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( final Execute exe ) | |||
| throws IOException, TaskException | |||
| { | |||
| final int err = exe.execute(); | |||
| //test for and handle a forced process death | |||
| maybeSetResultPropertyValue( err ); | |||
| if( 0 != err ) | |||
| { | |||
| throw new TaskException( getContext().getName() + " returned: " + err ); | |||
| } | |||
| if( null != m_byteArrayOutput ) | |||
| { | |||
| writeResultToProperty(); | |||
| } | |||
| } | |||
| private void writeResultToProperty() throws IOException, TaskException | |||
| { | |||
| final BufferedReader input = | |||
| new BufferedReader( new StringReader( m_byteArrayOutput.toString() ) ); | |||
| String line = null; | |||
| StringBuffer val = new StringBuffer(); | |||
| while( ( line = input.readLine() ) != null ) | |||
| { | |||
| if( val.length() != 0 ) | |||
| { | |||
| val.append( StringUtil.LINE_SEPARATOR ); | |||
| } | |||
| val.append( line ); | |||
| } | |||
| final String name = m_outputProperty; | |||
| final Object value = val.toString(); | |||
| getContext().setProperty( name, value ); | |||
| } | |||
| /** | |||
| * Has the user set all necessary attributes? | |||
| * | |||
| * @exception TaskException Description of Exception | |||
| */ | |||
| protected void validate() | |||
| throws TaskException | |||
| { | |||
| if( m_command.getExecutable() == null ) | |||
| { | |||
| throw new TaskException( "no executable specified" ); | |||
| } | |||
| if( m_workingDirectory != null && !m_workingDirectory.exists() ) | |||
| { | |||
| throw new TaskException( "The directory you specified does not exist" ); | |||
| } | |||
| if( m_workingDirectory != null && !m_workingDirectory.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 | |||
| */ | |||
| private void setupOutput( final Execute exe ) | |||
| throws TaskException | |||
| { | |||
| if( m_outputFile != null ) | |||
| { | |||
| try | |||
| { | |||
| m_ouput = new FileOutputStream( m_outputFile ); | |||
| getLogger().debug( "Output redirected to " + m_outputFile ); | |||
| exe.setOutput( m_ouput ); | |||
| exe.setError( m_ouput ); | |||
| } | |||
| catch( FileNotFoundException fne ) | |||
| { | |||
| throw new TaskException( "Cannot write to " + m_outputFile, fne ); | |||
| } | |||
| catch( IOException ioe ) | |||
| { | |||
| throw new TaskException( "Cannot write to " + m_outputFile, ioe ); | |||
| } | |||
| } | |||
| else if( m_outputProperty != null ) | |||
| { | |||
| m_byteArrayOutput = new ByteArrayOutputStream(); | |||
| getLogger().debug( "Output redirected to ByteArray" ); | |||
| exe.setOutput( m_byteArrayOutput ); | |||
| exe.setError( m_byteArrayOutput ); | |||
| } | |||
| else | |||
| { | |||
| exe.setOutput( new LogOutputStream( getLogger(), false ) ); | |||
| exe.setError( new LogOutputStream( getLogger(), true ) ); | |||
| } | |||
| } | |||
| /** | |||
| * Flush the output stream - if there is one. | |||
| */ | |||
| protected void logFlush() | |||
| { | |||
| try | |||
| { | |||
| if( m_ouput != null ) | |||
| { | |||
| m_ouput.close(); | |||
| } | |||
| if( m_byteArrayOutput != null ) | |||
| { | |||
| m_byteArrayOutput.close(); | |||
| } | |||
| } | |||
| catch( IOException io ) | |||
| { | |||
| } | |||
| } | |||
| /** | |||
| * helper method to set result property to the passed in value if | |||
| * appropriate | |||
| */ | |||
| protected void maybeSetResultPropertyValue( int result ) | |||
| throws TaskException | |||
| { | |||
| final String res = Integer.toString( result ); | |||
| if( m_resultProperty != null ) | |||
| { | |||
| final String name = m_resultProperty; | |||
| getContext().setProperty( name, res ); | |||
| } | |||
| } | |||
| /** | |||
| * Create an Execute instance with the correct working directory set. | |||
| */ | |||
| protected Execute prepareExec() | |||
| throws TaskException | |||
| { | |||
| // default directory to the project's base directory | |||
| if( m_workingDirectory == null ) | |||
| { | |||
| m_workingDirectory = getBaseDirectory(); | |||
| } | |||
| // show the command | |||
| getLogger().debug( m_command.toString() ); | |||
| final Execute exe = new Execute(); | |||
| setupOutput( exe ); | |||
| if( null != m_timeout ) | |||
| { | |||
| exe.setTimeout( m_timeout.intValue() ); | |||
| } | |||
| exe.setWorkingDirectory( m_workingDirectory ); | |||
| exe.setVMLauncher( m_useVMLauncher ); | |||
| exe.setNewenvironment( m_newEnvironment ); | |||
| final Properties environment = m_env.getVariables(); | |||
| final Iterator keys = environment.keySet().iterator(); | |||
| while( keys.hasNext() ) | |||
| { | |||
| final String key = (String)keys.next(); | |||
| final String value = environment.getProperty( key ); | |||
| getLogger().debug( "Setting environment variable: " + key + "=" + value ); | |||
| } | |||
| 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( final Execute exe ) | |||
| throws TaskException | |||
| { | |||
| exe.setCommandline( m_command.getCommandline() ); | |||
| try | |||
| { | |||
| runExecute( exe ); | |||
| } | |||
| catch( IOException e ) | |||
| { | |||
| throw new TaskException( "Execute failed: " + e.toString(), e ); | |||
| } | |||
| finally | |||
| { | |||
| // close the output file if required | |||
| logFlush(); | |||
| } | |||
| } | |||
| protected final Commandline getCommand() | |||
| { | |||
| return m_command; | |||
| } | |||
| } | |||
| @@ -1,142 +0,0 @@ | |||
| /* | |||
| * 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.tools.ant.taskdefs.exec; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.OutputStream; | |||
| import java.util.Properties; | |||
| import org.apache.aut.nativelib.ExecException; | |||
| import org.apache.aut.nativelib.ExecManager; | |||
| import org.apache.aut.nativelib.ExecMetaData; | |||
| import org.apache.avalon.excalibur.io.IOUtil; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| import org.apache.myrmidon.framework.factorys.ExecManagerFactory; | |||
| import org.apache.myrmidon.interfaces.service.ServiceException; | |||
| /** | |||
| * Runs an external program. | |||
| * | |||
| * @author thomas.haas@softwired-inc.com | |||
| */ | |||
| public class Execute | |||
| { | |||
| private String[] m_command; | |||
| private Properties m_environment = new Properties(); | |||
| private File m_workingDirectory = new File( "." ); | |||
| private boolean m_newEnvironment; | |||
| private OutputStream m_output; | |||
| private OutputStream m_error; | |||
| private long m_timeout; | |||
| /** | |||
| * Controls whether the VM is used to launch commands, where possible | |||
| */ | |||
| private boolean m_useVMLauncher = true; | |||
| public void setTimeout( final long timeout ) | |||
| { | |||
| m_timeout = timeout; | |||
| } | |||
| public void setOutput( final OutputStream output ) | |||
| { | |||
| m_output = output; | |||
| } | |||
| public void setError( final OutputStream error ) | |||
| { | |||
| m_error = error; | |||
| } | |||
| /** | |||
| * Sets the commandline of the subprocess to launch. | |||
| * | |||
| * @param commandline the commandline of the subprocess to launch | |||
| */ | |||
| public void setCommandline( String[] commandline ) | |||
| { | |||
| m_command = commandline; | |||
| } | |||
| public void setEnvironment( final Properties environment ) | |||
| { | |||
| if( null == environment ) | |||
| { | |||
| throw new NullPointerException( "environment" ); | |||
| } | |||
| m_environment = environment; | |||
| } | |||
| /** | |||
| * Set whether to propagate the default environment or not. | |||
| * | |||
| * @param newenv whether to propagate the process environment. | |||
| */ | |||
| public void setNewenvironment( boolean newEnvironment ) | |||
| { | |||
| m_newEnvironment = newEnvironment; | |||
| } | |||
| /** | |||
| * 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 ) | |||
| { | |||
| m_useVMLauncher = useVMLauncher; | |||
| } | |||
| /** | |||
| * Sets the working directory of the process to execute. <p> | |||
| * | |||
| * @param workingDirectory the working directory of the process. | |||
| */ | |||
| public void setWorkingDirectory( final File workingDirectory ) | |||
| { | |||
| m_workingDirectory = workingDirectory; | |||
| } | |||
| /** | |||
| * 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 | |||
| { | |||
| try | |||
| { | |||
| final ExecManagerFactory factory = new ExecManagerFactory(); | |||
| final ExecManager manager = (ExecManager)factory.createService(); | |||
| final ExecMetaData metaData = | |||
| new ExecMetaData( m_command, m_environment, | |||
| m_workingDirectory, m_newEnvironment ); | |||
| return manager.execute( metaData, null, m_output, m_error, m_timeout ); | |||
| } | |||
| catch( final ExecException ee ) | |||
| { | |||
| throw new TaskException( ee.getMessage(), ee ); | |||
| } | |||
| catch( final ServiceException se ) | |||
| { | |||
| throw new TaskException( se.getMessage(), se ); | |||
| } | |||
| finally | |||
| { | |||
| IOUtil.shutdownStream( m_output ); | |||
| IOUtil.shutdownStream( m_error ); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,440 +0,0 @@ | |||
| /* | |||
| * 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.tools.ant.taskdefs.exec; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.util.ArrayList; | |||
| import java.util.Hashtable; | |||
| import org.apache.avalon.excalibur.util.StringUtil; | |||
| import org.apache.myrmidon.api.TaskException; | |||
| import org.apache.tools.ant.types.DirectoryScanner; | |||
| import org.apache.tools.ant.types.FileSet; | |||
| import org.apache.tools.ant.types.Marker; | |||
| import org.apache.tools.ant.types.ScannerUtil; | |||
| import org.apache.tools.ant.types.SourceFileScanner; | |||
| import org.apache.tools.ant.util.mappers.FileNameMapper; | |||
| import org.apache.tools.ant.util.mappers.Mapper; | |||
| /** | |||
| * Executes a given command, supplying a set of files as arguments. | |||
| * | |||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
| * @author <a href="mailto:mariusz@rakiura.org">Mariusz Nowostawski</a> | |||
| */ | |||
| public class ExecuteOn | |||
| extends ExecTask | |||
| { | |||
| private ArrayList m_filesets = new ArrayList(); | |||
| private boolean m_relative; | |||
| private boolean m_parallel; | |||
| private String m_type = "file"; | |||
| private Marker m_srcFilePos; | |||
| private boolean m_skipEmpty; | |||
| private Marker m_targetFilePos; | |||
| private Mapper m_mapperElement; | |||
| private FileNameMapper m_mapper; | |||
| private File m_destDir; | |||
| /** | |||
| * Has <srcfile> been specified before <targetfile> | |||
| */ | |||
| private boolean m_srcIsFirst = true; | |||
| /** | |||
| * Set the destination directory. | |||
| */ | |||
| public void setDest( final File destDir ) | |||
| { | |||
| m_destDir = destDir; | |||
| } | |||
| /** | |||
| * Shall the command work on all specified files in parallel? | |||
| */ | |||
| public void setParallel( final boolean parallel ) | |||
| { | |||
| m_parallel = parallel; | |||
| } | |||
| /** | |||
| * Should filenames be returned as relative path names? | |||
| */ | |||
| public void setRelative( final boolean relative ) | |||
| { | |||
| m_relative = relative; | |||
| } | |||
| /** | |||
| * Should empty filesets be ignored? | |||
| */ | |||
| public void setSkipEmptyFilesets( final boolean skip ) | |||
| { | |||
| m_skipEmpty = skip; | |||
| } | |||
| /** | |||
| * Shall the command work only on files, directories or both? | |||
| */ | |||
| public void setType( final FileDirBoth type ) | |||
| { | |||
| m_type = type.getValue(); | |||
| } | |||
| /** | |||
| * Adds a set of files (nested fileset attribute). | |||
| */ | |||
| public void addFileset( final FileSet set ) | |||
| { | |||
| m_filesets.add( set ); | |||
| } | |||
| /** | |||
| * Defines the FileNameMapper to use (nested mapper element). | |||
| */ | |||
| public Mapper createMapper() | |||
| throws TaskException | |||
| { | |||
| if( m_mapperElement != null ) | |||
| { | |||
| throw new TaskException( "Cannot define more than one mapper" ); | |||
| } | |||
| m_mapperElement = new Mapper(); | |||
| return m_mapperElement; | |||
| } | |||
| /** | |||
| * Marker that indicates where the name of the source file should be put on | |||
| * the command line. | |||
| */ | |||
| public Marker createSrcfile() | |||
| throws TaskException | |||
| { | |||
| if( m_srcFilePos != null ) | |||
| { | |||
| throw new TaskException( getContext().getName() + " doesn\'t support multiple srcfile elements." ); | |||
| } | |||
| m_srcFilePos = getCommand().createMarker(); | |||
| return m_srcFilePos; | |||
| } | |||
| /** | |||
| * Marker that indicates where the name of the target file should be put on | |||
| * the command line. | |||
| */ | |||
| public Marker createTargetfile() | |||
| throws TaskException | |||
| { | |||
| if( m_targetFilePos != null ) | |||
| { | |||
| throw new TaskException( getContext().getName() + " doesn\'t support multiple targetfile elements." ); | |||
| } | |||
| m_targetFilePos = getCommand().createMarker(); | |||
| m_srcIsFirst = ( m_srcFilePos != null ); | |||
| return m_targetFilePos; | |||
| } | |||
| /** | |||
| * Construct the command line for parallel execution. | |||
| * | |||
| * @param srcFiles The filenames to add to the commandline | |||
| */ | |||
| protected String[] getCommandline( final String[] srcFiles, | |||
| final File[] baseDirs ) | |||
| throws TaskException | |||
| { | |||
| final ArrayList targets = new ArrayList(); | |||
| if( m_targetFilePos != null ) | |||
| { | |||
| Hashtable addedFiles = new Hashtable(); | |||
| for( int i = 0; i < srcFiles.length; i++ ) | |||
| { | |||
| String[] subTargets = m_mapper.mapFileName( srcFiles[ i ] ); | |||
| if( subTargets != null ) | |||
| { | |||
| for( int j = 0; j < subTargets.length; j++ ) | |||
| { | |||
| String name = null; | |||
| if( !m_relative ) | |||
| { | |||
| name = | |||
| ( new File( m_destDir, subTargets[ j ] ) ).getAbsolutePath(); | |||
| } | |||
| else | |||
| { | |||
| name = subTargets[ j ]; | |||
| } | |||
| if( !addedFiles.contains( name ) ) | |||
| { | |||
| targets.add( name ); | |||
| addedFiles.put( name, name ); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| String[] targetFiles = new String[ targets.size() ]; | |||
| targetFiles = (String[])targets.toArray( targetFiles ); | |||
| String[] orig = getCommand().getCommandline(); | |||
| String[] result = new String[ orig.length + srcFiles.length + targetFiles.length ]; | |||
| int srcIndex = orig.length; | |||
| if( m_srcFilePos != null ) | |||
| { | |||
| srcIndex = m_srcFilePos.getPosition(); | |||
| } | |||
| if( m_targetFilePos != null ) | |||
| { | |||
| int targetIndex = m_targetFilePos.getPosition(); | |||
| if( srcIndex < targetIndex | |||
| || ( srcIndex == targetIndex && m_srcIsFirst ) ) | |||
| { | |||
| // 0 --> srcIndex | |||
| System.arraycopy( orig, 0, result, 0, srcIndex ); | |||
| // srcIndex --> targetIndex | |||
| System.arraycopy( orig, srcIndex, result, | |||
| srcIndex + srcFiles.length, | |||
| targetIndex - srcIndex ); | |||
| // targets are already absolute file names | |||
| System.arraycopy( targetFiles, 0, result, | |||
| targetIndex + srcFiles.length, | |||
| targetFiles.length ); | |||
| // targetIndex --> end | |||
| System.arraycopy( orig, targetIndex, result, | |||
| targetIndex + srcFiles.length + targetFiles.length, | |||
| orig.length - targetIndex ); | |||
| } | |||
| else | |||
| { | |||
| // 0 --> targetIndex | |||
| System.arraycopy( orig, 0, result, 0, targetIndex ); | |||
| // targets are already absolute file names | |||
| System.arraycopy( targetFiles, 0, result, | |||
| targetIndex, | |||
| targetFiles.length ); | |||
| // targetIndex --> srcIndex | |||
| System.arraycopy( orig, targetIndex, result, | |||
| targetIndex + targetFiles.length, | |||
| srcIndex - targetIndex ); | |||
| // srcIndex --> end | |||
| System.arraycopy( orig, srcIndex, result, | |||
| srcIndex + srcFiles.length + targetFiles.length, | |||
| orig.length - srcIndex ); | |||
| srcIndex += targetFiles.length; | |||
| } | |||
| } | |||
| else | |||
| {// no targetFilePos | |||
| // 0 --> srcIndex | |||
| System.arraycopy( orig, 0, result, 0, srcIndex ); | |||
| // srcIndex --> end | |||
| System.arraycopy( orig, srcIndex, result, | |||
| srcIndex + srcFiles.length, | |||
| orig.length - srcIndex ); | |||
| } | |||
| // fill in source file names | |||
| for( int i = 0; i < srcFiles.length; i++ ) | |||
| { | |||
| if( !m_relative ) | |||
| { | |||
| result[ srcIndex + i ] = | |||
| ( new File( baseDirs[ i ], srcFiles[ i ] ) ).getAbsolutePath(); | |||
| } | |||
| else | |||
| { | |||
| result[ srcIndex + i ] = srcFiles[ i ]; | |||
| } | |||
| } | |||
| return result; | |||
| } | |||
| /** | |||
| * Construct the command line for serial execution. | |||
| * | |||
| * @param srcFile The filename to add to the commandline | |||
| * @param baseDir filename is relative to this dir | |||
| * @return The Commandline value | |||
| */ | |||
| protected String[] getCommandline( final String srcFile, | |||
| final File baseDir ) | |||
| throws TaskException | |||
| { | |||
| return getCommandline( new String[]{srcFile}, new File[]{baseDir} ); | |||
| } | |||
| /** | |||
| * Return the list of Directories from this DirectoryScanner that should be | |||
| * included on the command line. | |||
| * | |||
| * @param baseDir Description of Parameter | |||
| * @param ds Description of Parameter | |||
| * @return The Dirs value | |||
| */ | |||
| protected String[] getDirs( final File baseDir, | |||
| final DirectoryScanner ds ) | |||
| throws TaskException | |||
| { | |||
| if( m_mapper != null ) | |||
| { | |||
| final SourceFileScanner scanner = new SourceFileScanner(); | |||
| setupLogger( scanner ); | |||
| return scanner.restrict( ds.getIncludedDirectories(), baseDir, m_destDir, | |||
| m_mapper ); | |||
| } | |||
| else | |||
| { | |||
| return ds.getIncludedDirectories(); | |||
| } | |||
| } | |||
| /** | |||
| * Return the list of files from this DirectoryScanner that should be | |||
| * included on the command line. | |||
| * | |||
| * @param baseDir Description of Parameter | |||
| * @param ds Description of Parameter | |||
| * @return The Files value | |||
| */ | |||
| protected String[] getFiles( final File baseDir, | |||
| final DirectoryScanner ds ) | |||
| throws TaskException | |||
| { | |||
| if( m_mapper != null ) | |||
| { | |||
| final SourceFileScanner scanner = new SourceFileScanner(); | |||
| setupLogger( scanner ); | |||
| return scanner.restrict( ds.getIncludedFiles(), baseDir, m_destDir, | |||
| m_mapper ); | |||
| } | |||
| else | |||
| { | |||
| return ds.getIncludedFiles(); | |||
| } | |||
| } | |||
| protected void validate() | |||
| throws TaskException | |||
| { | |||
| super.validate(); | |||
| if( m_filesets.size() == 0 ) | |||
| { | |||
| final String message = "no filesets specified"; | |||
| throw new TaskException( message ); | |||
| } | |||
| if( m_targetFilePos != null || | |||
| m_mapperElement != null || | |||
| m_destDir != null ) | |||
| { | |||
| if( m_mapperElement == null ) | |||
| { | |||
| final String message = "no mapper specified"; | |||
| throw new TaskException( message ); | |||
| } | |||
| if( m_mapperElement == null ) | |||
| { | |||
| final String message = "no dest attribute specified"; | |||
| throw new TaskException( message ); | |||
| } | |||
| m_mapper = m_mapperElement.getImplementation(); | |||
| } | |||
| } | |||
| protected void runExec( final Execute exe ) | |||
| throws TaskException | |||
| { | |||
| try | |||
| { | |||
| final ArrayList fileNames = new ArrayList(); | |||
| final ArrayList baseDirs = new ArrayList(); | |||
| for( int i = 0; i < m_filesets.size(); i++ ) | |||
| { | |||
| final FileSet fs = (FileSet)m_filesets.get( i ); | |||
| final File base = fs.getDir(); | |||
| final DirectoryScanner ds = ScannerUtil.getDirectoryScanner( fs ); | |||
| if( !"dir".equals( m_type ) ) | |||
| { | |||
| final String[] s = getFiles( base, ds ); | |||
| for( int j = 0; j < s.length; j++ ) | |||
| { | |||
| fileNames.add( s[ j ] ); | |||
| baseDirs.add( base ); | |||
| } | |||
| } | |||
| if( !"file".equals( m_type ) ) | |||
| { | |||
| final String[] s = getDirs( base, ds ); | |||
| for( int j = 0; j < s.length; j++ ) | |||
| { | |||
| fileNames.add( s[ j ] ); | |||
| baseDirs.add( base ); | |||
| } | |||
| } | |||
| if( fileNames.size() == 0 && m_skipEmpty ) | |||
| { | |||
| getLogger().info( "Skipping fileset for directory " + base + ". It is empty." ); | |||
| continue; | |||
| } | |||
| if( !m_parallel ) | |||
| { | |||
| String[] s = new String[ fileNames.size() ]; | |||
| s = (String[])fileNames.toArray( s ); | |||
| for( int j = 0; j < s.length; j++ ) | |||
| { | |||
| String[] command = getCommandline( s[ j ], base ); | |||
| getLogger().debug( "Executing " + StringUtil.join( command, " " ) ); | |||
| exe.setCommandline( command ); | |||
| runExecute( exe ); | |||
| } | |||
| fileNames.clear(); | |||
| baseDirs.clear(); | |||
| } | |||
| } | |||
| if( m_parallel && ( fileNames.size() > 0 || !m_skipEmpty ) ) | |||
| { | |||
| String[] s = new String[ fileNames.size() ]; | |||
| s = (String[])fileNames.toArray( s ); | |||
| File[] b = new File[ baseDirs.size() ]; | |||
| b = (File[])baseDirs.toArray( b ); | |||
| String[] command = getCommandline( s, b ); | |||
| getLogger().debug( "Executing " + StringUtil.join( command, " " ) ); | |||
| exe.setCommandline( command ); | |||
| runExecute( exe ); | |||
| } | |||
| } | |||
| catch( IOException e ) | |||
| { | |||
| throw new TaskException( "Execute failed: " + e, e ); | |||
| } | |||
| finally | |||
| { | |||
| // close the output file if required | |||
| logFlush(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,23 +0,0 @@ | |||
| /* | |||
| * 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.tools.ant.taskdefs.exec; | |||
| import org.apache.tools.ant.types.EnumeratedAttribute; | |||
| /** | |||
| * Enumerated attribute with the values "file", "dir" and "both" for the | |||
| * type attribute. | |||
| */ | |||
| public class FileDirBoth | |||
| extends EnumeratedAttribute | |||
| { | |||
| public String[] getValues() | |||
| { | |||
| return new String[]{"file", "dir", "both"}; | |||
| } | |||
| } | |||
| @@ -1,114 +0,0 @@ | |||
| /* | |||
| * 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.tools.ant.taskdefs.exec; | |||
| import java.io.ByteArrayOutputStream; | |||
| import java.io.IOException; | |||
| import java.io.OutputStream; | |||
| import org.apache.avalon.framework.logger.Logger; | |||
| /** | |||
| * 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 thomas.haas@softwired-inc.com | |||
| */ | |||
| public class LogOutputStream | |||
| extends OutputStream | |||
| { | |||
| private final boolean m_isError; | |||
| private final Logger m_logger; | |||
| private ByteArrayOutputStream m_buffer = new ByteArrayOutputStream(); | |||
| private boolean m_skip; | |||
| public LogOutputStream( final Logger logger, final boolean isError ) | |||
| { | |||
| m_logger = logger; | |||
| m_isError = isError; | |||
| } | |||
| protected final Logger getLogger() | |||
| { | |||
| return m_logger; | |||
| } | |||
| /** | |||
| * Writes all remaining | |||
| * | |||
| * @exception IOException Description of Exception | |||
| */ | |||
| 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 cc data to log (byte). | |||
| * @exception IOException Description of Exception | |||
| */ | |||
| 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>processLine</code> | |||
| */ | |||
| private void processBuffer() | |||
| { | |||
| processLine( m_buffer.toString() ); | |||
| m_buffer.reset(); | |||
| } | |||
| /** | |||
| * Logs a line to the log system of ant. | |||
| * | |||
| * @param line the line to log. | |||
| * @param level Description of Parameter | |||
| */ | |||
| protected void processLine( final String line ) | |||
| { | |||
| if( m_isError ) | |||
| { | |||
| getLogger().warn( line ); | |||
| } | |||
| else | |||
| { | |||
| getLogger().info( line ); | |||
| } | |||
| } | |||
| public boolean isError() | |||
| { | |||
| return m_isError; | |||
| } | |||
| } | |||