Browse Source

resource collection support for apply and friends

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@292251 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 20 years ago
parent
commit
a7d38cf263
8 changed files with 182 additions and 69 deletions
  1. +22
    -1
      docs/manual/CoreTasks/apply.html
  2. +4
    -0
      docs/manual/CoreTasks/chmod.html
  3. +4
    -0
      docs/manual/OptionalTasks/attrib.html
  4. +4
    -0
      docs/manual/OptionalTasks/chgrp.html
  5. +3
    -0
      docs/manual/OptionalTasks/chown.html
  6. +32
    -0
      src/etc/testcases/taskdefs/exec/apply.xml
  7. +92
    -68
      src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java
  8. +21
    -0
      src/testcases/org/apache/tools/ant/taskdefs/ExecuteOnTest.java

+ 22
- 1
docs/manual/CoreTasks/apply.html View File

@@ -16,12 +16,16 @@ compatibility.</i></p>
<p>Executes a system command. When the <i>os</i> attribute is specified, then <p>Executes a system command. When the <i>os</i> attribute is specified, then
the command is only executed when Ant is run on one of the specified operating the command is only executed when Ant is run on one of the specified operating
systems.</p> systems.</p>
<p>The files and/or directories of a number of

<p>The files and/or directories of a number of <a
href="../CoreTypes/resources.html#collection">Resource Collection</a>s
&ndash; including but not restricted to
<a href="../CoreTypes/fileset.html">FileSet</a>s, <a href="../CoreTypes/fileset.html">FileSet</a>s,
<a href="../CoreTypes/dirset.html">DirSet</a>s <a href="../CoreTypes/dirset.html">DirSet</a>s
(<em>since&nbsp;Ant&nbsp;1.6</em>) or (<em>since&nbsp;Ant&nbsp;1.6</em>) or
<a href="../CoreTypes/filelist.html">FileList</a>s <a href="../CoreTypes/filelist.html">FileList</a>s
(<em>since&nbsp;Ant&nbsp;1.6</em>) (<em>since&nbsp;Ant&nbsp;1.6</em>)
&ndash;
are passed as arguments to the system command.</p> are passed as arguments to the system command.</p>
<p>If you specify a nested <a href="../CoreTypes/mapper.html">mapper</a>, <p>If you specify a nested <a href="../CoreTypes/mapper.html">mapper</a>,
the timestamp of each source file is compared to the timestamp of a the timestamp of each source file is compared to the timestamp of a
@@ -283,6 +287,12 @@ elements to define the files for this task and refer to
<p>You can use any number of nested <code>&lt;dirset&gt;</code> <p>You can use any number of nested <code>&lt;dirset&gt;</code>
elements to define the directories for this task and refer to elements to define the directories for this task and refer to
<code>&lt;dirset&gt;</code>s defined elsewhere.</p> <code>&lt;dirset&gt;</code>s defined elsewhere.</p>

<h4>Any other <a href="../CoreTypes/resources.html#collection">Resource
Collection</a></h4>
<p><em>since Ant 1.7</em></p>
<p>You can use any number of nested resource collections.</p>

<h4>mapper</h4> <h4>mapper</h4>
<p>A single <code>&lt;mapper&gt;</code> specifies the target files relative <p>A single <code>&lt;mapper&gt;</code> specifies the target files relative
to the <code>dest</code> attribute for dependency checking. If the to the <code>dest</code> attribute for dependency checking. If the
@@ -385,6 +395,17 @@ task. A reference to <code>out</code> is then used as an
<code>&lt;outputmapper&gt;</code> nested in a <code>&lt;redirector&gt;</code>, which in turn is <code>&lt;outputmapper&gt;</code> nested in a <code>&lt;redirector&gt;</code>, which in turn is
nested beneath this <code>&lt;apply&gt;</code> instance. This allows us to perform nested beneath this <code>&lt;apply&gt;</code> instance. This allows us to perform
dependency checking against output files--the target files in this case. dependency checking against output files--the target files in this case.
<blockquote><pre>
&lt;apply executable="ls" parallel="true"
force="true" dest="${basedir}" append="true" type="both"&gt;
&lt;path&gt;
&lt;pathelement path="${env.PATH}"/&gt;
&lt;/path&gt;
&lt;identitymapper/&gt;
&lt;/apply&gt;
</pre></blockquote>
Applies the "ls" executable to all directories in the PATH, effectively
listing all executables that are available on the PATH.


<hr><p align="center">Copyright &copy; 2000-2005 The Apache Software Foundation. All rights <hr><p align="center">Copyright &copy; 2000-2005 The Apache Software Foundation. All rights
Reserved.</p> Reserved.</p>


+ 4
- 0
docs/manual/CoreTasks/chmod.html View File

@@ -26,6 +26,10 @@ specified using nested <code>&lt;fileset&gt;</code> or
<p>Starting with Ant 1.6, this task also supports nested <a <p>Starting with Ant 1.6, this task also supports nested <a
href="../CoreTypes/filelist.html">filelist</a>s.</p> href="../CoreTypes/filelist.html">filelist</a>s.</p>


<p>Starting with Ant 1.7, this task supports arbitrary <a
href="../CoreTypes/resources.html#collection">Resource Collection</a>s
as nested elements.</p>

<p>By default this task will use a single invocation of the underlying <p>By default this task will use a single invocation of the underlying
chmod command. If you are working on a large number of files this may chmod command. If you are working on a large number of files this may
result in a command line that is too long for your operating system. result in a command line that is too long for your operating system.


+ 4
- 0
docs/manual/OptionalTasks/attrib.html View File

@@ -23,6 +23,10 @@ href="../CoreTypes/filelist.html">FileList</a>s can be specified using
nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and
<code>&lt;filelist&gt;</code> elements.</p> <code>&lt;filelist&gt;</code> elements.</p>


<p>Starting with Ant 1.7, this task supports arbitrary <a
href="../CoreTypes/resources.html#collection">Resource Collection</a>s
as nested elements.</p>

<p>By default this task will use a single invocation of the underlying <p>By default this task will use a single invocation of the underlying
attrib command. If you are working on a large number of files this attrib command. If you are working on a large number of files this
may result in a command line that is too long for your operating may result in a command line that is too long for your operating


+ 4
- 0
docs/manual/OptionalTasks/chgrp.html View File

@@ -23,6 +23,10 @@ href="../CoreTypes/filelist.html">FileList</a>s can be specified using
nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and
<code>&lt;filelist&gt;</code> elements.</p> <code>&lt;filelist&gt;</code> elements.</p>


<p>Starting with Ant 1.7, this task supports arbitrary <a
href="../CoreTypes/resources.html#collection">Resource Collection</a>s
as nested elements.</p>

<p>By default this task will use a single invocation of the underlying <p>By default this task will use a single invocation of the underlying
chgrp command. If you are working on a large number of files this may chgrp command. If you are working on a large number of files this may
result in a command line that is too long for your operating system. result in a command line that is too long for your operating system.


+ 3
- 0
docs/manual/OptionalTasks/chown.html View File

@@ -23,6 +23,9 @@ href="../CoreTypes/filelist.html">FileList</a>s can be specified using
nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and
<code>&lt;filelist&gt;</code> elements.</p> <code>&lt;filelist&gt;</code> elements.</p>


<p>Starting with Ant 1.7, this task supports arbitrary <a
href="../CoreTypes/resources.html#collection">Resource Collection</a>s
as nested elements.</p>


<p>By default this task will use a single invocation of the underlying <p>By default this task will use a single invocation of the underlying
chown command. If you are working on a large number of files this may chown command. If you are working on a large number of files this may


+ 32
- 0
src/etc/testcases/taskdefs/exec/apply.xml View File

@@ -31,6 +31,17 @@
<isset property="echo.exe.executable"/> <isset property="echo.exe.executable"/>
</or> </or>
</condition> </condition>

<!-- UNIX -->
<available file="ls" filepath="${env.PATH}" property="ls.executable"/>
<!-- CYGWIN -->
<available file="ls.exe" filepath="${env.PATH}" property="ls.exe.executable"/>
<condition property="ls.can.run">
<or>
<isset property="ls.executable"/>
<isset property="ls.exe.executable"/>
</or>
</condition>
</target> </target>


<target name="xyz"> <target name="xyz">
@@ -394,6 +405,7 @@


<ekko outputproperty="foo" /> <ekko outputproperty="foo" />
<ekko outputproperty="bar" force="true" /> <ekko outputproperty="bar" force="true" />

<fail> <fail>
<condition> <condition>
<not> <not>
@@ -428,6 +440,26 @@
</fail> </fail>
</target> </target>


<target name="lsPath" depends="init" if="ls.can.run">
<apply executable="ls" parallel="false" outputproperty="foo"
force="true" dest="${basedir}" append="true" type="both">
<path>
<pathelement path="${env.PATH}"/>
</path>
<identitymapper/>
</apply>
</target>

<target name="lsPathParallel" depends="init" if="ls.can.run">
<apply executable="ls" parallel="true" outputproperty="foo"
force="true" dest="${basedir}" append="true" type="both">
<path>
<pathelement path="${env.PATH}"/>
</path>
<identitymapper/>
</apply>
</target>

<target name="cleanup"> <target name="cleanup">
<delete> <delete>
<fileset refid="xyz" /> <fileset refid="xyz" />


+ 92
- 68
src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java View File

@@ -20,6 +20,7 @@ package org.apache.tools.ant.taskdefs;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector; import java.util.Vector;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.DirectoryScanner;
@@ -31,6 +32,10 @@ import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileList; import org.apache.tools.ant.types.FileList;
import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Mapper; import org.apache.tools.ant.types.Mapper;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.Union;
import org.apache.tools.ant.util.FileNameMapper; import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.ant.util.SourceFileScanner; import org.apache.tools.ant.util.SourceFileScanner;


@@ -43,13 +48,20 @@ import org.apache.tools.ant.util.SourceFileScanner;
*/ */
public class ExecuteOn extends ExecTask { public class ExecuteOn extends ExecTask {


// filesets has been protected so we need to keep that even after
// switching to resource collections. In fact, they will still
// get a different treatment form the other resource collections
// even in execute since we have some subtle special features like
// switching type to "dir" when we encounter a DirSet that would
// be more difficult to achieve otherwise.

protected Vector filesets = new Vector(); // contains AbstractFileSet protected Vector filesets = new Vector(); // contains AbstractFileSet
// (both DirSet and FileSet) // (both DirSet and FileSet)
private Vector filelists = new Vector();
private Union resources = new Union();
private boolean relative = false; private boolean relative = false;
private boolean parallel = false; private boolean parallel = false;
private boolean forwardSlash = false; private boolean forwardSlash = false;
protected String type = "file";
protected String type = FileDirBoth.FILE;
protected Commandline.Marker srcFilePos = null; protected Commandline.Marker srcFilePos = null;
private boolean skipEmpty = false; private boolean skipEmpty = false;
protected Commandline.Marker targetFilePos = null; protected Commandline.Marker targetFilePos = null;
@@ -91,7 +103,18 @@ public class ExecuteOn extends ExecTask {
* @param list the FileList to add. * @param list the FileList to add.
*/ */
public void addFilelist(FileList list) { public void addFilelist(FileList list) {
filelists.addElement(list);
add(list);
}

/**
* Add a collection of resources upon which to operate.
* @param rc resource collection to add.
* @since Ant 1.7
*/
public void add(ResourceCollection rc) {
if (rc instanceof FileSet)
throw new BuildException("Huh?");
resources.add(rc);
} }


/** /**
@@ -273,8 +296,8 @@ public class ExecuteOn extends ExecTask {
log("!! execon is deprecated. Use apply instead. !!"); log("!! execon is deprecated. Use apply instead. !!");
} }
super.checkConfiguration(); super.checkConfiguration();
if (filesets.size() == 0 && filelists.size() == 0) {
throw new BuildException("no filesets and no filelists specified",
if (filesets.size() == 0 && resources.size() == 0) {
throw new BuildException("no resources specified",
getLocation()); getLocation());
} }
if (targetFilePos != null && mapperElement == null) { if (targetFilePos != null && mapperElement == null) {
@@ -326,19 +349,19 @@ public class ExecuteOn extends ExecTask {
String currentType = type; String currentType = type;
AbstractFileSet fs = (AbstractFileSet) filesets.elementAt(i); AbstractFileSet fs = (AbstractFileSet) filesets.elementAt(i);
if (fs instanceof DirSet) { if (fs instanceof DirSet) {
if (!"dir".equals(type)) {
if (!FileDirBoth.DIR.equals(type)) {
log("Found a nested dirset but type is " + type + ". " log("Found a nested dirset but type is " + type + ". "
+ "Temporarily switching to type=\"dir\" on the" + "Temporarily switching to type=\"dir\" on the"
+ " assumption that you really did mean" + " assumption that you really did mean"
+ " <dirset> not <fileset>.", Project.MSG_DEBUG); + " <dirset> not <fileset>.", Project.MSG_DEBUG);
currentType = "dir";
currentType = FileDirBoth.DIR;
} }
} }
File base = fs.getDir(getProject()); File base = fs.getDir(getProject());


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


if (!"dir".equals(currentType)) {
if (!FileDirBoth.DIR.equals(currentType)) {
String[] s = getFiles(base, ds); String[] s = getFiles(base, ds);
for (int j = 0; j < s.length; j++) { for (int j = 0; j < s.length; j++) {
totalFiles++; totalFiles++;
@@ -346,7 +369,7 @@ public class ExecuteOn extends ExecTask {
baseDirs.addElement(base); baseDirs.addElement(base);
} }
} }
if (!"file".equals(currentType)) {
if (!FileDirBoth.FILE.equals(currentType)) {
String[] s = getDirs(base, ds); String[] s = getDirs(base, ds);
for (int j = 0; j < s.length; j++) { for (int j = 0; j < s.length; j++) {
totalDirs++; totalDirs++;
@@ -356,9 +379,9 @@ public class ExecuteOn extends ExecTask {
} }
if (fileNames.size() == 0 && skipEmpty) { if (fileNames.size() == 0 && skipEmpty) {
int includedCount int includedCount
= ((!"dir".equals(currentType))
= ((!FileDirBoth.DIR.equals(currentType))
? ds.getIncludedFilesCount() : 0) ? ds.getIncludedFilesCount() : 0)
+ ((!"file".equals(currentType))
+ ((!FileDirBoth.FILE.equals(currentType))
? ds.getIncludedDirsCount() : 0); ? ds.getIncludedDirsCount() : 0);


log("Skipping fileset for directory " + base + ". It is " log("Skipping fileset for directory " + base + ". It is "
@@ -392,68 +415,67 @@ public class ExecuteOn extends ExecTask {
baseDirs.removeAllElements(); baseDirs.removeAllElements();
} }
} }
for (int i = 0; i < filelists.size(); i++) {
FileList list = (FileList) filelists.elementAt(i);
File base = list.getDir(getProject());
String[] names = getFilesAndDirs(list);

for (int j = 0; j < names.length; j++) {
File f = new File(base, names[j]);
if ((!ignoreMissing) || (f.isFile() && !"dir".equals(type))
|| (f.isDirectory() && !"file".equals(type))) {

if (ignoreMissing || f.isFile()) {
totalFiles++;
} else {
totalDirs++;
}
fileNames.addElement(names[j]);
baseDirs.addElement(base);
}
}
if (fileNames.size() == 0 && skipEmpty) {
DirectoryScanner ds = new DirectoryScanner();
ds.setBasedir(base);
ds.setIncludes(list.getFiles(getProject()));
ds.scan();
int includedCount
= ds.getIncludedFilesCount() + ds.getIncludedDirsCount();
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);


log("Skipping filelist for directory " + base + ". It is "
+ ((includedCount > 0) ? "up to date." : "empty."),
Project.MSG_INFO);
continue;
}
if (!parallel) { 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();
}
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)) { if (parallel && (fileNames.size() > 0 || !skipEmpty)) {
runParallel(exe, fileNames, baseDirs); runParallel(exe, fileNames, baseDirs);
haveExecuted = true; haveExecuted = true;
}
}
if (haveExecuted) { if (haveExecuted) {
log("Applied " + cmdl.getExecutable() + " to " log("Applied " + cmdl.getExecutable() + " to "
+ totalFiles + " file" + totalFiles + " file"
@@ -697,11 +719,13 @@ public class ExecuteOn extends ExecTask {
* for the type attribute. * for the type attribute.
*/ */
public static class FileDirBoth extends EnumeratedAttribute { public static class FileDirBoth extends EnumeratedAttribute {
public static final String FILE = "file";
public static final String DIR = "dir";
/** /**
* @see EnumeratedAttribute#getValues * @see EnumeratedAttribute#getValues
*/ */
public String[] getValues() { public String[] getValues() {
return new String[] {"file", "dir", "both"};
return new String[] {FILE, DIR, "both"};
} }
} }
} }

+ 21
- 0
src/testcases/org/apache/tools/ant/taskdefs/ExecuteOnTest.java View File

@@ -31,6 +31,7 @@ import java.io.OutputStream;
public class ExecuteOnTest extends BuildFileTest { public class ExecuteOnTest extends BuildFileTest {
private static final String BUILD_PATH = "src/etc/testcases/taskdefs/exec/"; private static final String BUILD_PATH = "src/etc/testcases/taskdefs/exec/";
private static final String BUILD_FILE = BUILD_PATH + "apply.xml"; private static final String BUILD_FILE = BUILD_PATH + "apply.xml";
private static final String LINE_SEP = System.getProperty("line.separator");
public ExecuteOnTest(String name) { public ExecuteOnTest(String name) {
super(name); super(name);
@@ -562,6 +563,26 @@ public class ExecuteOnTest extends BuildFileTest {
executeTarget("testNoDest"); executeTarget("testNoDest");
} }


public void testLsPath() {
testLsPath("lsPath");
}

public void testLsPathParallel() {
testLsPath("lsPathParallel");
}

private void testLsPath(String target) {
executeTarget(target);
if (getProject().getProperty("ls.can.run") == null) {
return;
}
String foo = getProject().getProperty("foo");
assertNotNull(foo);
int indNoExt = foo.indexOf("ls" + LINE_SEP);
int indExe = foo.indexOf("ls.exe" + LINE_SEP);
assertTrue(indNoExt >= 0 || indExe >= 0);
}

//borrowed from TokenFilterTest //borrowed from TokenFilterTest
private String getFileString(String filename) throws IOException { private String getFileString(String filename) throws IOException {
String result = null; String result = null;


Loading…
Cancel
Save