Browse Source

A new resource collection multirootfileset, PR 48621

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@1578003 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 11 years ago
parent
commit
42beec8e1d
8 changed files with 684 additions and 0 deletions
  1. +5
    -0
      WHATSNEW
  2. +173
    -0
      manual/Types/multirootfileset.html
  3. +1
    -0
      manual/Types/resources.html
  4. +1
    -0
      manual/conceptstypeslist.html
  5. +1
    -0
      src/main/org/apache/tools/ant/types/defaults.properties
  6. +232
    -0
      src/main/org/apache/tools/ant/types/resources/MultiRootFileSet.java
  7. +144
    -0
      src/tests/antunit/types/resources/multirootfileset-test.xml
  8. +127
    -0
      src/tests/junit/org/apache/tools/ant/types/resources/MultiRootFileSetTest.java

+ 5
- 0
WHATSNEW View File

@@ -135,6 +135,11 @@ Other changes:
* The <get> task now explicitly accepts and supports the gzip content encoding.
Bugzilla Report 49453

* A new resourcecollection type <multirootfileset> acts like a union
of <fileset>s and <dirset>s that share the same configuration but
have different base directories.
Bugzilla Report 48621

Changes from Ant 1.9.2 TO Ant 1.9.3
===================================



+ 173
- 0
manual/Types/multirootfileset.html View File

@@ -0,0 +1,173 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
<title>MultiRooFileSet Type</title>
</head>

<body>

<h2><a name="multirootfileset">MultiRootFileSet</a></h2>

<p><em>Since Ant 1.9.4</em></p>

<p>A MultiRootFileSet is a group of files or directories. These files
or drectories can be found in a directory forrest starting with a set
of base directories and are matched by patterns taken from a number of
<a href="patternset.html">PatternSets</a> and <a
href="selectors.html">Selectors</a>.</p>

<p>MultiRootFileSet acts as a union of <a
href="fileset.html">FileSets</a> and <a href="dirset.html">DirSets</a>
that share the same patterns and selectors.</p>

<p>MultiRootFileSet supports all attributes and nested elements of
FileSet and DirSet except for the "dir" attribute.</p>

<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">basedirs</td>
<td valign="top">Comma separated list of directories that build
the roots of the MultiRootFileSet.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">cache</td>
<td valign="top">Whether to cache results; disabling
may seriously impact performance</td>
<td valign="top" align="center">No, default <i>true</i></td>
</tr>
<tr>
<td valign="top">type</td>
<td valign="top">The type of file system entities which will be
included in this set.
Acceptable values are:
<ul>
<li>file - regular files</li>
<li>dir - directories</li>
<li>both - regular files and directories</li>
</ul>
</td>
<td valign="top" align="center">No, defaults to <i>file</i></td>
</tr>
<tr>
<td valign="top">includes</td>
<td valign="top">A comma- or space-separated list of patterns of directories that
must be included; all directories are included when omitted.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">includesfile</td>
<td valign="top">The name of a file; each line of this file is
taken to be an include pattern.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">excludes</td>
<td valign="top">A comma- or space-separated list of patterns of directories that
must be excluded; no directories are excluded when omitted.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">excludesfile</td>
<td valign="top">The name of a file; each line of this file is
taken to be an exclude pattern.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">casesensitive</td>
<td valign="top">Specifies whether case-sensitivity should be applied
(<code>true</code>|<code>yes</code>|<code>on</code> or
<code>false</code>|<code>no</code>|<code>off</code>).</td>
<td valign="top" align="center">No; defaults to true.</td>
</tr>
<tr>
<td valign="top">followsymlinks</td>
<td valign="top">Shall symbolic links be followed? Defaults to
true. See <a href="fileset.html#symlink">fileset's documentation</a>.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">erroronmissingdir</td>
<td valign="top">
Specify what happens if one of the base directories does not exist.
If true a build error will happen, if false, the subtree
will be ignored/empty.
Defaults to true.
</td>
<td valign="top" align="center">No</td>
</tr>
</table>

<h3>Parameters specified as nested elements</h3>

<p>PatternSets can be specified as nested
<code>&lt;patternset&gt;</code> elements. In addition, MultiRootFileSet holds
an implicit PatternSet and supports the nested
<code>&lt;include&gt;</code>, <code>&lt;includesfile&gt;</code>,
<code>&lt;exclude&gt;</code> and <code>&lt;excludesfile&gt;</code>
elements of <code>&lt;patternset&gt;</code> directly, as well as
<code>&lt;patternset&gt;</code>'s attributes.</p>

<p>Selectors are available as nested elements within the
MultiRootFileSet. If any of the selectors within the MultiRootFileSet
do not select the file or directory, it is not considered part of the
MultiRootFileSet. This makes a MultiRootFileSet equivalent to
an <code>&lt;and&gt;</code> selector container.</p>

<p>In addition basedirs for the MultiRootFileSet can be specified as
nested <code>basedir</code> elements that have a
single <code>file</code> attribute.</p>


<h4>Examples</h4>

<blockquote><pre>
&lt;multirootfileset basedirs=&quot;${build.dir},${other.project.dir}&quot;&gt;
&lt;include name=&quot;apps/**/classes&quot;/&gt;
&lt;exclude name=&quot;apps/**/*Test*&quot;/&gt;
&lt;/multirootfileset&gt;
</pre></blockquote>
<p>Groups all files inside <code>classes</code> found under the
<code>apps</code> subdirectory of <code>${build.dir}</code> or
<code>${other.project.dir}</code>, except those that have the text
<code>Test</code> in their name.</p>

<blockquote><pre>
&lt;multirootfileset&gt;
&lt;basedir file=&quot;${build.dir}&quot;/&gt;
&lt;basedir file=&quot;${other.project.dir}&quot;
&lt;include name=&quot;apps/**/classes&quot;/&gt;
&lt;exclude name=&quot;apps/**/*Test*&quot;/&gt;
&lt;/multirootfileset&gt;
</pre></blockquote>
<p>Is equivalent to the first example but used
nested <code>basedir</code> elements. The nested elements and
the <code>basedirs</code> attribute can be used at the same time and
the will be merged.</p>

</body>
</html>


+ 1
- 0
manual/Types/resources.html View File

@@ -320,6 +320,7 @@ Ant's "legacy" datatypes have been modified to behave as Resource Collections:
<ul>
<li><a href="fileset.html">fileset</a>,
<a href="dirset.html">dirset</a>,
<a href="multirootfileset.html">multirootfileset</a>,
<a href="filelist.html">filelist</a>, and
<a href="../using.html#path">path</a>
(and derivative types) expose <a href="#file">file</a> resources


+ 1
- 0
manual/conceptstypeslist.html View File

@@ -51,6 +51,7 @@
<li><a href="Types/mapper.html">File Mappers</a></li>
<li><a href="Types/filterchain.html">FilterChains and FilterReaders</a></li>
<li><a href="Types/filterset.html">FilterSet</a></li>
<li><a href="Types/multirootfileset.html">MultiRootFileSet</a></li>
<li><a href="Types/patternset.html">PatternSet</a></li>
<li><a href="using.html#path">Path-like Structures</a></li>
<li><a href="Types/permissions.html">Permissions</a></li>


+ 1
- 0
src/main/org/apache/tools/ant/types/defaults.properties View File

@@ -90,6 +90,7 @@ tarentry=org.apache.tools.ant.types.resources.TarResource
gzipresource=org.apache.tools.ant.types.resources.GZipResource
bzip2resource=org.apache.tools.ant.types.resources.BZip2Resource
javaresource=org.apache.tools.ant.types.resources.JavaResource
multirootfileset=org.apache.tools.ant.types.resources.MultiRootFileSet

#tokenizer implementations
linetokenizer=org.apache.tools.ant.util.LineTokenizer


+ 232
- 0
src/main/org/apache/tools/ant/types/resources/MultiRootFileSet.java View File

@@ -0,0 +1,232 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.types.resources;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.AbstractFileSet;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;

/**
* Union of file/dirsets that share the same patterns and selectors
* but have different roots.
* @since Ant 1.9.4
*/
public class MultiRootFileSet extends AbstractFileSet
implements ResourceCollection {

private SetType type = SetType.file;
private boolean cache = true;
private List<File> baseDirs = new ArrayList<File>();
private Union union;

public void setDir(File dir) {
throw new BuildException(getDataTypeName()
+ " doesn't support the dir attribute");
}

/**
* Determines the types of resources to return.
* @param type the types of resources to return
*/
public void setType(SetType type) {
if (isReference()) {
throw tooManyAttributes();
}
this.type = type;
}

/**
* Set whether to cache collections.
* @param b boolean cache flag.
*/
public synchronized void setCache(boolean b) {
if (isReference()) {
throw tooManyAttributes();
}
cache = b;
}

/**
* Adds basedirs as a comman separated list.
* @param b boolean cache flag.
*/
public void setBaseDirs(String dirs) {
if (isReference()) {
throw tooManyAttributes();
}
if (dirs != null && dirs.length() > 0) {
String[] ds = dirs.split(",");
for (String d : ds) {
baseDirs.add(getProject().resolveFile(d));
}
}
}

/**
* Adds a basedir as nested element.
*/
public void addConfiguredBaseDir(FileResource r) {
if (isReference()) {
throw noChildrenAllowed();
}
baseDirs.add(r.getFile());
}

public void setRefid(Reference r) {
if (!baseDirs.isEmpty()) {
throw tooManyAttributes();
}
super.setRefid(r);
}

/**
* Return a MultiRootFileSet that has the same basedirs and same patternsets
* as this one.
* @return the cloned MultiRootFileSet.
*/
public Object clone() {
if (isReference()) {
return ((MultiRootFileSet) getRef(getProject())).clone();
} else {
MultiRootFileSet fs = (MultiRootFileSet) super.clone();
fs.baseDirs = new ArrayList<File>(baseDirs);
fs.union = null;
return fs;
}
}

/**
* Fulfill the ResourceCollection contract.
* @return an Iterator of Resources.
*/
public Iterator<Resource> iterator() {
if (isReference()) {
return ((MultiRootFileSet) getRef(getProject())).iterator();
}
return merge().iterator();
}

/**
* Fulfill the ResourceCollection contract.
* @return number of elements as int.
*/
public int size() {
if (isReference()) {
return ((MultiRootFileSet) getRef(getProject())).size();
}
return merge().size();
}

/**
* Always returns true.
* @return true indicating that all elements will be FileResources.
*/
public boolean isFilesystemOnly() {
return true;
}

/**
* Returns included directories as a list of semicolon-separated paths.
*
* @return a <code>String</code> of included directories.
*/
public String toString() {
if (isReference()) {
return ((MultiRootFileSet) getRef(getProject())).toString();
}
return merge().toString();
}

private synchronized Union merge() {
if (cache && union != null) {
return union;
}
Union u = new Union();
setup(u);
if (cache) {
union = u;
}
return u;
}

private void setup(Union u) {
for (File d : baseDirs) {
u.add(new Worker(this, type, d));
}
}

/**
* What to return from the set: files, directories or both.
*/
public static enum SetType {
file, dir, both
}

private static class Worker extends AbstractFileSet
implements ResourceCollection {

private final SetType type;
private Worker(MultiRootFileSet fs, SetType type, File dir) {
super(fs);
this.type = type;
setDir(dir);
}

public boolean isFilesystemOnly() {
return true;
}

public Iterator<Resource> iterator() {
DirectoryScanner ds = getDirectoryScanner(getProject());
String[] names = type == SetType.file
? ds.getIncludedFiles()
: ds.getIncludedDirectories();
if (type == SetType.both) {
String[] files = ds.getIncludedFiles();
String[] merged = new String[names.length + files.length];
System.arraycopy(names, 0, merged, 0, names.length);
System.arraycopy(files, 0, merged, names.length, files.length);
names = merged;
}
return new FileResourceIterator(getProject(), getDir(getProject()),
names);
}

public int size() {
DirectoryScanner ds = getDirectoryScanner(getProject());
int count = type == SetType.file
? ds.getIncludedFilesCount()
: ds.getIncludedDirs Count();
if (type == SetType.both) {
count += ds.getIncludedFilesCount();
}
return count;
}
}

}

+ 144
- 0
src/tests/antunit/types/resources/multirootfileset-test.xml View File

@@ -0,0 +1,144 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns:au="antlib:org.apache.ant.antunit" default="antunit">

<import file="../../antunit-base.xml"/>

<target name="setUp">
<touch mkdirs="true" file="${input}/a/1/1.txt"/>
<touch mkdirs="true" file="${input}/a/1/2.txt"/>
<touch mkdirs="true" file="${input}/a/1/3.txt"/>
<touch mkdirs="true" file="${input}/b/2/3.txt"/>
<touch mkdirs="true" file="${input}/b/2/4.txt"/>
<mkdir dir="${output}"/>
</target>

<target name="test-count-in-simple-configuration" depends="setUp">
<resourcecount property="files">
<multirootfileset basedirs="${input}/a,${input}/b"/>
</resourcecount>
<resourcecount property="dirs">
<multirootfileset basedirs="${input}/a,${input}/b" type="dir"/>
</resourcecount>
<resourcecount property="files-and-dirs">
<multirootfileset basedirs="${input}/a,${input}/b" type="both"/>
</resourcecount>
<au:assertPropertyEquals value="5" name="files"/>
<au:assertPropertyEquals value="4" name="dirs"/>
<au:assertPropertyEquals value="9" name="files-and-dirs"/>
</target>

<target name="test-count-nested-basedir-elements" depends="setUp">
<resourcecount property="files">
<multirootfileset>
<basedir file="${input}/a"/>
<basedir file="${input}/b"/>
</multirootfileset>
</resourcecount>
<resourcecount property="dirs">
<multirootfileset type="dir">
<basedir file="${input}/a"/>
<basedir file="${input}/b"/>
</multirootfileset>
</resourcecount>
<resourcecount property="files-and-dirs">
<multirootfileset type="both">
<basedir file="${input}/a"/>
<basedir file="${input}/b"/>
</multirootfileset>
</resourcecount>
<au:assertPropertyEquals value="5" name="files"/>
<au:assertPropertyEquals value="4" name="dirs"/>
<au:assertPropertyEquals value="9" name="files-and-dirs"/>
</target>

<target name="test-copying" depends="setUp">
<copy todir="${output}">
<multirootfileset basedirs="${input}/a,${input}/b"/>
</copy>
<au:assertFileExists file="${output}/1/1.txt"/>
<au:assertFileExists file="${output}/1/2.txt"/>
<au:assertFileExists file="${output}/1/3.txt"/>
<au:assertFileExists file="${output}/2/3.txt"/>
<au:assertFileExists file="${output}/2/4.txt"/>
</target>

<target name="test-dirs" depends="setUp">
<pathconvert property="dirs" pathsep=":">
<multirootfileset basedirs="${input}/a,${input}/b" type="dir"/>
</pathconvert>
<au:assertPropertyEquals value="${input}/a:${input}/a/1:${input}/b:${input}/b/2"
name="dirs"/>
</target>

<target name="test-include-pattern" depends="setUp">
<copy todir="${output}">
<multirootfileset basedirs="${input}/a,${input}/b">
<include name="**/3.txt"/>
</multirootfileset>
</copy>
<au:assertFileDoesntExist file="${output}/1/1.txt"/>
<au:assertFileExists file="${output}/1/3.txt"/>
<au:assertFileExists file="${output}/2/3.txt"/>
<au:assertFileDoesntExist file="${output}/2/4.txt"/>
<pathconvert property="dirs" pathsep=":">
<multirootfileset basedirs="${input}/a,${input}/b" type="dir">
<include name="1/"/>
</multirootfileset>
</pathconvert>
<au:assertPropertyEquals value="${input}/a/1" name="dirs"/>
</target>

<target name="test-exclude-pattern" depends="setUp">
<copy todir="${output}">
<multirootfileset basedirs="${input}/a,${input}/b">
<exclude name="**/3.txt"/>
</multirootfileset>
</copy>
<au:assertFileExists file="${output}/1/1.txt"/>
<au:assertFileDoesntExist file="${output}/1/3.txt"/>
<au:assertFileDoesntExist file="${output}/2/3.txt"/>
<au:assertFileExists file="${output}/2/4.txt"/>
<pathconvert property="dirs" pathsep=":">
<multirootfileset basedirs="${input}/a,${input}/b" type="dir">
<exclude name="1/"/>
</multirootfileset>
</pathconvert>
<au:assertPropertyEquals value="${input}/a:${input}/b:${input}/b/2"
name="dirs"/>
</target>

<target name="test-selectors" depends="setUp">
<copy todir="${output}">
<multirootfileset basedirs="${input}/a,${input}/b">
<filename regex=".*3\.txt"/>
</multirootfileset>
</copy>
<au:assertFileDoesntExist file="${output}/1/1.txt"/>
<au:assertFileExists file="${output}/1/3.txt"/>
<au:assertFileExists file="${output}/2/3.txt"/>
<au:assertFileDoesntExist file="${output}/2/4.txt"/>
<pathconvert property="dirs" pathsep=":">
<multirootfileset basedirs="${input}/a,${input}/b" type="dir">
<filename regex="1"/>
</multirootfileset>
</pathconvert>
<au:assertPropertyEquals value="${input}/a/1" name="dirs"/>
</target>

</project>

+ 127
- 0
src/tests/junit/org/apache/tools/ant/types/resources/MultiRootFileSetTest.java View File

@@ -0,0 +1,127 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.types.resources;

import java.io.File;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.AbstractFileSet;
import org.apache.tools.ant.types.AbstractFileSetTest;
import org.apache.tools.ant.types.Reference;

/**
* This doesn't actually test much, mainly reference handling.
*/
public class MultiRootFileSetTest extends AbstractFileSetTest {

public MultiRootFileSetTest(String name) {
super(name);
}

protected AbstractFileSet getInstance() {
return new MultiRootFileSet() {
// overriding so set/getDir works as expected by the base test class
private File dir;
public void setDir(File dir) {
if (isReference()) {
throw tooManyAttributes();
}
this.dir = dir;
}

public synchronized File getDir(Project p) {
if (isReference()) {
return getRef(p).getDir(p);
}
dieOnCircularReference();
return dir;
}
};
}

public void testEmptyElementIfIsReferenceAdditionalAttributes() {
MultiRootFileSet f = new MultiRootFileSet();
f.setProject(getProject());
f.setBaseDirs("a");
try {
f.setRefid(new Reference(getProject(), "dummyref"));
fail("Can add reference to multirootfileset "
+ " with elements from setBasedirs");
} catch (BuildException be) {
assertEquals("You must not specify more than one attribute "
+ "when using refid", be.getMessage());
}
f = new MultiRootFileSet();
f.addConfiguredBaseDir(new FileResource(new File(".")));
try {
f.setRefid(new Reference(getProject(), "dummyref"));
fail("Can add reference to multirootfileset"
+ " with elements from addConfiguredBaseDir");
} catch (BuildException be) {
assertEquals("You must not specify more than one attribute "
+ "when using refid", be.getMessage());
}

f = new MultiRootFileSet();
f.setRefid(new Reference(getProject(), "dummyref"));
try {
f.setBaseDirs("a");
fail("Can set basedirs in multirootfileset"
+ " that is a reference.");
} catch (BuildException be) {
assertEquals("You must not specify more than one attribute "
+ "when using refid", be.getMessage());
}
try {
f.setCache(true);
fail("Can set cache in multirootfileset"
+ " that is a reference.");
} catch (BuildException be) {
assertEquals("You must not specify more than one attribute "
+ "when using refid", be.getMessage());
}
try {
f.setType(MultiRootFileSet.SetType.file);
fail("Can set type in multirootfileset"
+ " that is a reference.");
} catch (BuildException be) {
assertEquals("You must not specify more than one attribute "
+ "when using refid", be.getMessage());
}
try {
f.addConfiguredBaseDir(new FileResource(new File(".")));
fail("Can add nested basedir in multirootfileset "
+ " that is a reference.");
} catch (BuildException be) {
assertEquals("You must not specify nested elements when using "
+ "refid", be.getMessage());
}
}

public void testDirCannotBeSet() {
try {
new MultiRootFileSet().setDir(new File("."));
fail("Can set dir in a multirootfileset");
} catch (BuildException e) {
assertTrue(e.getMessage()
.endsWith(" doesn't support the dir attribute"));
}
}
}

Loading…
Cancel
Save