FileDocCategorySizeDatePackage
ExecuteOn.javaAPI DocApache Ant 1.7027712Wed Dec 13 06:16:20 GMT 2006org.apache.tools.ant.taskdefs

ExecuteOn

public class ExecuteOn extends ExecTask
Executes a given command, supplying a set of files as arguments.
since
Ant 1.2
ant.task
category="control" name="apply"

Fields Summary
protected Vector
filesets
private org.apache.tools.ant.types.resources.Union
resources
private boolean
relative
private boolean
parallel
private boolean
forwardSlash
protected String
type
protected Commandline.Marker
srcFilePos
private boolean
skipEmpty
protected Commandline.Marker
targetFilePos
protected org.apache.tools.ant.types.Mapper
mapperElement
protected org.apache.tools.ant.util.FileNameMapper
mapper
protected File
destDir
private int
maxParallel
private boolean
addSourceFile
private boolean
verbose
private boolean
ignoreMissing
private boolean
force
protected boolean
srcIsFirst
Has <srcfile> been specified before <targetfile>
Constructors Summary
Methods Summary
public voidadd(org.apache.tools.ant.util.FileNameMapper fileNameMapper)
Add a nested FileNameMapper.

param
fileNameMapper the mapper to add.
since
Ant 1.6.3

        createMapper().add(fileNameMapper);
    
public voidadd(org.apache.tools.ant.types.ResourceCollection rc)
Add a collection of resources upon which to operate.

param
rc resource collection to add.
since
Ant 1.7

        if (resources == null) {
            resources = new Union();
        }
        resources.add(rc);
    
public voidaddDirset(org.apache.tools.ant.types.DirSet set)
Add a set of directories upon which to operate.

param
set the DirSet to add.
since
Ant 1.6

        filesets.addElement(set);
    
public voidaddFilelist(org.apache.tools.ant.types.FileList list)
Add a list of source files upon which to operate.

param
list the FileList to add.

        add(list);
    
public voidaddFileset(org.apache.tools.ant.types.FileSet set)
Add a set of files upon which to operate.

param
set the FileSet to add.


    // CheckStyle:VisibilityModifier ON
                        
        
        filesets.addElement(set);
    
protected voidcheckConfiguration()
Check the configuration of this ExecuteOn instance.

//     * @TODO using taskName here is brittle, as a user could override it.
//     *       this should probably be modified to use the classname instead.
        if ("execon".equals(getTaskName())) {
            log("!! execon is deprecated. Use apply instead. !!");
        }
        super.checkConfiguration();
        if (filesets.size() == 0 && resources == null) {
            throw new BuildException("no resources specified",
                                     getLocation());
        }
        if (targetFilePos != null && mapperElement == null) {
            throw new BuildException("targetfile specified without mapper",
                                     getLocation());
        }
        if (destDir != null && mapperElement == null) {
            throw new BuildException("dest specified without mapper",
                                     getLocation());
        }
        if (mapperElement != null) {
            mapper = mapperElement.getImplementation();
        }
    
protected ExecuteStreamHandlercreateHandler()
Create the ExecuteStreamHandler instance that will be used during execution.

return
ExecuteStreamHandler.
throws
BuildException on error.

        //if we have a RedirectorElement, return a decoy
        return (redirectorElement == null)
            ? super.createHandler() : new PumpStreamHandler();
    
public org.apache.tools.ant.types.MappercreateMapper()
Create a nested Mapper element to use for mapping source files to target files.

return
Mapper.
throws
BuildException if more than one mapper is defined.

        if (mapperElement != null) {
            throw new BuildException("Cannot define more than one mapper",
                                     getLocation());
        }
        mapperElement = new Mapper(getProject());
        return mapperElement;
    
public Commandline.MarkercreateSrcfile()
Create a placeholder indicating where on the command line the name of the source file should be inserted.

return
Commandline.Marker.

        if (srcFilePos != null) {
            throw new BuildException(getTaskType() + " doesn\'t support multiple "
                                     + "srcfile elements.", getLocation());
        }
        srcFilePos = cmdl.createMarker();
        return srcFilePos;
    
public Commandline.MarkercreateTargetfile()
Create a placeholder indicating where on the command line the name of the target file should be inserted.

return
Commandline.Marker.

        if (targetFilePos != null) {
            throw new BuildException(getTaskType() + " doesn\'t support multiple "
                                     + "targetfile elements.", getLocation());
        }
        targetFilePos = cmdl.createMarker();
        srcIsFirst = (srcFilePos != null);
        return targetFilePos;
    
protected java.lang.String[]getCommandline(java.lang.String[] srcFiles, java.io.File[] baseDirs)
Construct the command line for parallel execution.

param
srcFiles The filenames to add to the commandline.
param
baseDirs filenames are relative to this dir.
return
the command line in the form of a String[].

        final char fileSeparator = File.separatorChar;
        Vector targets = new Vector();
        if (targetFilePos != null) {
            Hashtable addedFiles = new Hashtable();
            for (int i = 0; i < srcFiles.length; i++) {
                String[] subTargets = mapper.mapFileName(srcFiles[i]);
                if (subTargets != null) {
                    for (int j = 0; j < subTargets.length; j++) {
                        String name = null;
                        if (!relative) {
                            name = (new File(destDir, subTargets[j])).getAbsolutePath();
                        } else {
                            name = subTargets[j];
                        }
                        if (forwardSlash && fileSeparator != '/") {
                            name = name.replace(fileSeparator, '/");
                        }
                        if (!addedFiles.contains(name)) {
                            targets.addElement(name);
                            addedFiles.put(name, name);
                        }
                    }
                }
            }
        }
        String[] targetFiles = new String[targets.size()];
        targets.copyInto(targetFiles);

        if (!addSourceFile) {
            srcFiles = new String[0];
        }
        String[] orig = cmdl.getCommandline();
        String[] result
            = new String[orig.length + srcFiles.length + targetFiles.length];

        int srcIndex = orig.length;
        if (srcFilePos != null) {
            srcIndex = srcFilePos.getPosition();
        }
        if (targetFilePos != null) {
            int targetIndex = targetFilePos.getPosition();

            if (srcIndex < targetIndex
                || (srcIndex == targetIndex && 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 (!relative) {
                result[srcIndex + i] =
                    (new File(baseDirs[i], srcFiles[i])).getAbsolutePath();
            } else {
                result[srcIndex + i] = srcFiles[i];
            }
            if (forwardSlash && fileSeparator != '/") {
                result[srcIndex + i] =
                    result[srcIndex + i].replace(fileSeparator, '/");
            }
        }
        return result;
    
protected java.lang.String[]getCommandline(java.lang.String srcFile, java.io.File baseDir)
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 command line in the form of a String[].

        return getCommandline(new String[] {srcFile}, new File[] {baseDir});
    
protected java.lang.String[]getDirs(java.io.File baseDir, org.apache.tools.ant.DirectoryScanner ds)
Return the list of Directories from this DirectoryScanner that should be included on the command line.

param
baseDir the File base directory.
param
ds the DirectoryScanner to use for file scanning.
return
a String[] containing the directory names.

        return restrict(ds.getIncludedDirectories(), baseDir);
    
protected java.lang.String[]getFiles(java.io.File baseDir, org.apache.tools.ant.DirectoryScanner ds)
Return the list of files from this DirectoryScanner that should be included on the command line.

param
baseDir the File base directory.
param
ds the DirectoryScanner to use for file scanning.
return
a String[] containing the filenames.

        return restrict(ds.getIncludedFiles(), baseDir);
    
protected java.lang.String[]getFilesAndDirs(org.apache.tools.ant.types.FileList list)
Return the list of files or directories from this FileList that should be included on the command line.

param
list the FileList to check.
return
a String[] containing the directory names.
since
Ant 1.6.2

        return restrict(list.getFiles(getProject()), list.getDir(getProject()));
    
private java.lang.String[]restrict(java.lang.String[] s, java.io.File baseDir)

        return (mapper == null || force) ? s
            : new SourceFileScanner(this).restrict(s, baseDir, destDir, mapper);
    
protected voidrunExec(Execute exe)
Run the specified Execute object.

param
exe the Execute instance representing the external process.
throws
BuildException on error

        int totalFiles = 0;
        int totalDirs = 0;
        boolean haveExecuted = false;
        try {
            Vector fileNames = new Vector();
            Vector baseDirs = new Vector();
            for (int i = 0; i < filesets.size(); i++) {
                String currentType = type;
                AbstractFileSet fs = (AbstractFileSet) filesets.elementAt(i);
                if (fs instanceof DirSet) {
                    if (!FileDirBoth.DIR.equals(type)) {
                        log("Found a nested dirset but type is " + type + ". "
                            + "Temporarily switching to type=\"dir\" on the"
                            + " assumption that you really did mean"
                            + " <dirset> not <fileset>.", Project.MSG_DEBUG);
                        currentType = FileDirBoth.DIR;
                    }
                }
                File base = fs.getDir(getProject());

                DirectoryScanner ds = fs.getDirectoryScanner(getProject());

                if (!FileDirBoth.DIR.equals(currentType)) {
                    String[] s = getFiles(base, ds);
                    for (int j = 0; j < s.length; j++) {
                        totalFiles++;
                        fileNames.addElement(s[j]);
                        baseDirs.addElement(base);
                    }
                }
                if (!FileDirBoth.FILE.equals(currentType)) {
                    String[] s = getDirs(base, ds);
                    for (int j = 0; j < s.length; j++) {
                        totalDirs++;
                        fileNames.addElement(s[j]);
                        baseDirs.addElement(base);
                    }
                }
                if (fileNames.size() == 0 && skipEmpty) {
                    int includedCount
                        = ((!FileDirBoth.DIR.equals(currentType))
                        ? ds.getIncludedFilesCount() : 0)
                        + ((!FileDirBoth.FILE.equals(currentType))
                        ? ds.getIncludedDirsCount() : 0);

                    log("Skipping fileset for directory " + base + ". It is "
                        + ((includedCount > 0) ? "up to date." : "empty."),
                        Project.MSG_INFO);
                    continue;
                }
                if (!parallel) {
                    String[] s = new String[fileNames.size()];
                    fileNames.copyInto(s);
                    for (int j = 0; j < s.length; j++) {
                        String[] command = getCommandline(s[j], base);
                        log(Commandline.describeCommand(command),
                            Project.MSG_VERBOSE);
                        exe.setCommandline(command);

                        if (redirectorElement != null) {
                            setupRedirector();
                            redirectorElement.configure(redirector, s[j]);
                        }
                        if (redirectorElement != null || haveExecuted) {
                            // need to reset the stream handler to restart
                            // reading of pipes;
                            // go ahead and do it always w/ nested redirectors
                            exe.setStreamHandler(redirector.createHandler());
                        }
                        runExecute(exe);
                        haveExecuted = true;
                    }
                    fileNames.removeAllElements();
                    baseDirs.removeAllElements();
                }
            }

            if (resources != null) {
                Iterator iter = resources.iterator();
                while (iter.hasNext()) {
                    Resource res = (Resource) iter.next();

                    if (!res.isExists() && ignoreMissing) {
                        continue;
                    }

                    File base = null;
                    String name = res.getName();
                    if (res instanceof FileResource) {
                        FileResource fr = (FileResource) res;
                        base = fr.getBaseDir();
                        if (base == null) {
                            name = fr.getFile().getAbsolutePath();
                        }
                    }

                    if (restrict(new String[] {name}, base).length == 0) {
                        continue;
                    }

                    if ((!res.isDirectory() || !res.isExists())
                        && !FileDirBoth.DIR.equals(type)) {
                        totalFiles++;
                    } else if (res.isDirectory()
                               && !FileDirBoth.FILE.equals(type)) {
                        totalDirs++;
                    } else {
                        continue;
                    }

                    baseDirs.add(base);
                    fileNames.add(name);

                    if (!parallel) {
                        String[] command = getCommandline(name, base);
                        log(Commandline.describeCommand(command),
                            Project.MSG_VERBOSE);
                        exe.setCommandline(command);

                        if (redirectorElement != null) {
                            setupRedirector();
                            redirectorElement.configure(redirector, name);
                        }
                        if (redirectorElement != null || haveExecuted) {
                            // need to reset the stream handler to restart
                            // reading of pipes;
                            // go ahead and do it always w/ nested redirectors
                            exe.setStreamHandler(redirector.createHandler());
                        }
                        runExecute(exe);
                        haveExecuted = true;
                        fileNames.removeAllElements();
                        baseDirs.removeAllElements();
                    }
                }
            }
            if (parallel && (fileNames.size() > 0 || !skipEmpty)) {
                runParallel(exe, fileNames, baseDirs);
                haveExecuted = true;
            }
            if (haveExecuted) {
                log("Applied " + cmdl.getExecutable() + " to "
                    + totalFiles + " file"
                    + (totalFiles != 1 ? "s" : "") + " and "
                    + totalDirs + " director"
                    + (totalDirs != 1 ? "ies" : "y") + ".",
                    verbose ? Project.MSG_INFO : Project.MSG_VERBOSE);
            }
        } catch (IOException e) {
            throw new BuildException("Execute failed: " + e, e, getLocation());
        } finally {
            // close the output file if required
            logFlush();
            redirector.setAppendProperties(false);
            redirector.setProperties();
        }
    
protected voidrunParallel(Execute exe, java.util.Vector fileNames, java.util.Vector baseDirs)
Run the command in "parallel" mode, making sure that at most maxParallel sourcefiles get passed on the command line.

param
exe the Executable to use.
param
fileNames the Vector of filenames.
param
baseDirs the Vector of base directories corresponding to fileNames.
throws
IOException on I/O errors.
throws
BuildException on other errors.
since
Ant 1.6

        String[] s = new String[fileNames.size()];
        fileNames.copyInto(s);
        File[] b = new File[baseDirs.size()];
        baseDirs.copyInto(b);

        if (maxParallel <= 0
            || s.length == 0 /* this is skipEmpty == false */) {
            String[] command = getCommandline(s, b);
            log(Commandline.describeCommand(command), Project.MSG_VERBOSE);
            exe.setCommandline(command);
            runExecute(exe);
        } else {
            int stillToDo = fileNames.size();
            int currentOffset = 0;
            while (stillToDo > 0) {
                int currentAmount = Math.min(stillToDo, maxParallel);
                String[] cs = new String[currentAmount];
                System.arraycopy(s, currentOffset, cs, 0, currentAmount);
                File[] cb = new File[currentAmount];
                System.arraycopy(b, currentOffset, cb, 0, currentAmount);
                String[] command = getCommandline(cs, cb);
                log(Commandline.describeCommand(command), Project.MSG_VERBOSE);
                exe.setCommandline(command);
                if (redirectorElement != null) {
                    setupRedirector();
                    redirectorElement.configure(redirector, null);
                }
                if (redirectorElement != null || currentOffset > 0) {
                    // need to reset the stream handler to restart
                    // reading of pipes;
                    // go ahead and do it always w/ nested redirectors
                    exe.setStreamHandler(redirector.createHandler());
                }
                runExecute(exe);

                stillToDo -= currentAmount;
                currentOffset += currentAmount;
            }
        }
    
public voidsetAddsourcefile(boolean b)
Set whether to send the source file name on the command line.

Defaults to true.

param
b whether to add the source file to the command line.
since
Ant 1.6

        addSourceFile = b;
    
public voidsetDest(java.io.File destDir)
Specify the directory where target files are to be placed.

param
destDir the File object representing the destination directory.

        this.destDir = destDir;
    
public voidsetForce(boolean b)
Set whether to bypass timestamp comparisons for target files.

param
b whether to bypass timestamp comparisons.
since
Ant 1.6.3

        force = b;
    
public voidsetForwardslash(boolean forwardSlash)
Set whether the source and target file names on Windows and OS/2 must use the forward slash as file separator.

param
forwardSlash whether the forward slash will be forced.

        this.forwardSlash = forwardSlash;
    
public voidsetIgnoremissing(boolean b)
Set whether to ignore nonexistent files from filelists.

param
b whether to ignore missing files.
since
Ant 1.6.2

        ignoreMissing = b;
    
public voidsetMaxParallel(int max)
Limit the command line length by passing at maximum this many sourcefiles at once to the command.

Set to <= 0 for unlimited - this is the default.

param
max int maximum number of sourcefiles passed to the executable.
since
Ant 1.6

        maxParallel = max;
    
public voidsetParallel(boolean parallel)
Set whether to execute in parallel mode. If true, run the command only once, appending all files as arguments. If false, command will be executed once for every file. Defaults to false.

param
parallel whether to run in parallel.

        this.parallel = parallel;
    
public voidsetRelative(boolean relative)
Set whether the filenames should be passed on the command line as absolute or relative pathnames. Paths are relative to the base directory of the corresponding fileset for source files or the dest attribute for target files.

param
relative whether to pass relative pathnames.

        this.relative = relative;
    
public voidsetSkipEmptyFilesets(boolean skip)
Set whether empty filesets will be skipped. If true and no source files have been found or are newer than their corresponding target files, the command will not be run.

param
skip whether to skip empty filesets.

        skipEmpty = skip;
    
public voidsetType(org.apache.tools.ant.taskdefs.ExecuteOn$FileDirBoth type)
Set whether the command works only on files, directories or both.

param
type a FileDirBoth EnumeratedAttribute.

        this.type = type.getValue();
    
public voidsetVerbose(boolean b)
Set whether to operate in verbose mode. If true, a verbose summary will be printed after execution.

param
b whether to operate in verbose mode.
since
Ant 1.6

        verbose = b;
    
protected voidsetupRedirector()
Set up the I/O Redirector.

        super.setupRedirector();
        redirector.setAppendProperties(true);