diff --git a/WHATSNEW b/WHATSNEW index 16bfdf1d2..1e184fa23 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -337,6 +337,8 @@ Other changes: * new resourcesmatch condition. +* added the onmissingfiltersfile attribute to filterset. Bugzilla report 19845. + Changes from Ant 1.6.4 to Ant 1.6.5 =================================== diff --git a/docs/manual/CoreTypes/filterset.html b/docs/manual/CoreTypes/filterset.html index 4ffe817ea..579ca0595 100644 --- a/docs/manual/CoreTypes/filterset.html +++ b/docs/manual/CoreTypes/filterset.html @@ -62,7 +62,7 @@ you should ensure that the set of files being filtered are all text files. filtersfile Specify a single filtersfile. - n/a + none No @@ -72,6 +72,13 @@ you should ensure that the set of files being filtered are all text files. true No + + onmissingfiltersfile + Indicate behavior when a nonexistent filtersfile + is specified. One of "fail", "warn", "ignore". Since Ant 1.7 + "fail" + No +

Filter

diff --git a/src/etc/testcases/types/filterset.xml b/src/etc/testcases/types/filterset.xml index 4fa780af4..210bfe22d 100644 --- a/src/etc/testcases/types/filterset.xml +++ b/src/etc/testcases/types/filterset.xml @@ -48,10 +48,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + diff --git a/src/etc/testcases/types/filtersetd.txt b/src/etc/testcases/types/filtersetd.txt new file mode 100644 index 000000000..45c4849ee --- /dev/null +++ b/src/etc/testcases/types/filtersetd.txt @@ -0,0 +1 @@ +@foo@ @bar@ @baz@ @blah@ diff --git a/src/etc/testcases/types/filtersfile1 b/src/etc/testcases/types/filtersfile1 new file mode 100644 index 000000000..20fe058f2 --- /dev/null +++ b/src/etc/testcases/types/filtersfile1 @@ -0,0 +1,2 @@ +foo=FOO +bar=BAR diff --git a/src/etc/testcases/types/filtersfile2 b/src/etc/testcases/types/filtersfile2 new file mode 100644 index 000000000..43c97f27d --- /dev/null +++ b/src/etc/testcases/types/filtersfile2 @@ -0,0 +1 @@ +baz=BAZ diff --git a/src/main/org/apache/tools/ant/types/FilterSet.java b/src/main/org/apache/tools/ant/types/FilterSet.java index 1ae90c63f..9251c7020 100644 --- a/src/main/org/apache/tools/ant/types/FilterSet.java +++ b/src/main/org/apache/tools/ant/types/FilterSet.java @@ -118,7 +118,44 @@ public class FilterSet extends DataType implements Cloneable { * @param file the file from which filters will be read. */ public void setFile(File file) { - readFiltersFromFile(file); + filtersFiles.add(file); + } + } + + /** + * EnumeratedAttribute to set behavior WRT missing filtersfiles: + * "fail" (default), "warn", "ignore". + * @since Ant 1.7 + */ + public static class OnMissing extends EnumeratedAttribute { + private static final String[] VALUES + = new String[] {"fail", "warn", "ignore"}; + + public static final OnMissing FAIL = new OnMissing("fail"); + public static final OnMissing WARN = new OnMissing("warn"); + public static final OnMissing IGNORE = new OnMissing("ignore"); + + private static final int FAIL_INDEX = 0; + private static final int WARN_INDEX = 1; + private static final int IGNORE_INDEX = 2; + + /** + * Default constructor. + */ + public OnMissing() { + } + + /** + * Convenience constructor. + * @param value the value to set. + */ + public OnMissing(String value) { + setValue(value); + } + + //inherit doc + public String[] getValues() { + return VALUES; } } @@ -138,6 +175,9 @@ public class FilterSet extends DataType implements Cloneable { private boolean recurse = true; private Hashtable filterHash = null; + private Vector filtersFiles = new Vector(); + private OnMissing onMissingFiltersFile = OnMissing.FAIL; + private boolean readingFiles = false; /** * List of ordered filters and filter files. @@ -169,6 +209,15 @@ public class FilterSet extends DataType implements Cloneable { if (isReference()) { return getRef().getFilters(); } + //silly hack to avoid stack overflow... + if (!readingFiles) { + readingFiles = true; + for (int i = 0, sz = filtersFiles.size(); i < sz; i++) { + readFiltersFromFile((File) filtersFiles.get(i)); + } + filtersFiles.clear(); + readingFiles = false; + } return filters; } @@ -202,13 +251,12 @@ public class FilterSet extends DataType implements Cloneable { * * @param filtersFile sets the filter file from which to read filters * for this filter set. - * @exception BuildException if there is a problem reading the filters. */ public void setFiltersfile(File filtersFile) throws BuildException { if (isReference()) { throw tooManyAttributes(); } - readFiltersFromFile(filtersFile); + filtersFiles.add(filtersFile); } /** @@ -292,7 +340,7 @@ public class FilterSet extends DataType implements Cloneable { throw tooManyAttributes(); } if (!filtersFile.exists()) { - throw new BuildException("Could not read filters from file " + handleMissingFile("Could not read filters from file " + filtersFile + " as it doesn't exist."); } if (filtersFile.isFile()) { @@ -312,13 +360,14 @@ public class FilterSet extends DataType implements Cloneable { } } catch (Exception ex) { throw new BuildException("Could not read filters from file: " - + filtersFile); + + filtersFile); } finally { FileUtils.close(in); } } else { - throw new BuildException("Must specify a file not a directory in " - + "the filtersfile attribute:" + filtersFile); + handleMissingFile( + "Must specify a file rather than a directory in " + + "the filtersfile attribute:" + filtersFile); } filterHash = null; } @@ -338,6 +387,104 @@ public class FilterSet extends DataType implements Cloneable { return iReplaceTokens(line); } + /** + * Add a new filter. + * + * @param filter the filter to be added. + */ + public synchronized void addFilter(Filter filter) { + if (isReference()) { + throw noChildrenAllowed(); + } + filters.addElement(filter); + filterHash = null; + } + + /** + * Create a new FiltersFile. + * + * @return The filtersfile that was created. + */ + public FiltersFile createFiltersfile() { + if (isReference()) { + throw noChildrenAllowed(); + } + return new FiltersFile(); + } + + /** + * Add a new filter made from the given token and value. + * + * @param token The token for the new filter. + * @param value The value for the new filter. + */ + public synchronized void addFilter(String token, String value) { + if (isReference()) { + throw noChildrenAllowed(); + } + addFilter(new Filter(token, value)); + } + + /** + * Add a Filterset to this filter set. + * + * @param filterSet the filterset to be added to this filterset + */ + public synchronized void addConfiguredFilterSet(FilterSet filterSet) { + if (isReference()) { + throw noChildrenAllowed(); + } + for (Enumeration e = filterSet.getFilters().elements(); e.hasMoreElements();) { + addFilter((Filter) e.nextElement()); + } + } + + /** + * Test to see if this filter set has filters. + * + * @return Return true if there are filters in this set. + */ + public synchronized boolean hasFilters() { + return getFilters().size() > 0; + } + + /** + * Clone the filterset. + * + * @return a deep clone of this filterset. + * + * @throws BuildException if the clone cannot be performed. + */ + public synchronized Object clone() throws BuildException { + if (isReference()) { + return ((FilterSet) getRef()).clone(); + } + try { + FilterSet fs = (FilterSet) super.clone(); + fs.filters = (Vector) getFilters().clone(); + fs.setProject(getProject()); + return fs; + } catch (CloneNotSupportedException e) { + throw new BuildException(e); + } + } + + /** + * Set the behavior WRT missing filtersfiles. + * @param onMissingFiltersFile the OnMissing describing the behavior. + */ + public void setOnMissingFiltersFile(OnMissing onMissingFiltersFile) { + this.onMissingFiltersFile = onMissingFiltersFile; + } + + /** + * Get the onMissingFiltersFile setting. + * @return the OnMissing instance. + */ + public OnMissing getOnMissingFiltersFile() { + return onMissingFiltersFile; + } + /** * Does replacement on the given string with token matching. * This uses the defined begintoken and endtoken values which default @@ -438,87 +585,21 @@ public class FilterSet extends DataType implements Cloneable { return value; } - /** - * Add a new filter. - * - * @param filter the filter to be added. - */ - public synchronized void addFilter(Filter filter) { - if (isReference()) { - throw noChildrenAllowed(); - } - filters.addElement(filter); - filterHash = null; - } - - /** - * Create a new FiltersFile. - * - * @return The filtersfile that was created. - */ - public FiltersFile createFiltersfile() { - if (isReference()) { - throw noChildrenAllowed(); - } - return new FiltersFile(); - } - - /** - * Add a new filter made from the given token and value. - * - * @param token The token for the new filter. - * @param value The value for the new filter. - */ - public synchronized void addFilter(String token, String value) { - if (isReference()) { - throw noChildrenAllowed(); + private void addFiltersFile(File f) { + if (!filtersFiles.contains(f)) { + filtersFiles.add(f); } - addFilter(new Filter(token, value)); } - /** - * Add a Filterset to this filter set. - * - * @param filterSet the filterset to be added to this filterset - */ - public synchronized void addConfiguredFilterSet(FilterSet filterSet) { - if (isReference()) { - throw noChildrenAllowed(); - } - for (Enumeration e = filterSet.getFilters().elements(); e.hasMoreElements();) { - addFilter((Filter) e.nextElement()); + private void handleMissingFile(String message) { + switch (onMissingFiltersFile.getIndex()) { + case OnMissing.IGNORE_INDEX: + return; + case OnMissing.FAIL_INDEX: + throw new BuildException(message); + case OnMissing.WARN_INDEX: + log(message, Project.MSG_WARN); } } - /** - * Test to see if this filter set has filters. - * - * @return Return true if there are filters in this set. - */ - public synchronized boolean hasFilters() { - return getFilters().size() > 0; - } - - /** - * Clone the filterset. - * - * @return a deep clone of this filterset. - * - * @throws BuildException if the clone cannot be performed. - */ - public synchronized Object clone() throws BuildException { - if (isReference()) { - return ((FilterSet) getRef()).clone(); - } else { - try { - FilterSet fs = (FilterSet) super.clone(); - fs.filters = (Vector) getFilters().clone(); - fs.setProject(getProject()); - return fs; - } catch (CloneNotSupportedException e) { - throw new BuildException(e); - } - } - } } - diff --git a/src/testcases/org/apache/tools/ant/types/FilterSetTest.java b/src/testcases/org/apache/tools/ant/types/FilterSetTest.java index fe23a7671..108420f7a 100644 --- a/src/testcases/org/apache/tools/ant/types/FilterSetTest.java +++ b/src/testcases/org/apache/tools/ant/types/FilterSetTest.java @@ -141,6 +141,27 @@ public class FilterSetTest extends BuildFileTest { assertEquals("value1", filters.get("token1")); } + public void testFiltersFileElement() { + executeTarget("testFiltersFileElement"); + } + + public void testFiltersFileAttribute() { + executeTarget("testFiltersFileAttribute"); + } + + public void testMultipleFiltersFiles() { + executeTarget("testMultipleFiltersFiles"); + } + + public void testMissingFiltersFile() { + expectBuildException("testMissingFiltersFile", + "should fail due to missing filtersfile"); + } + + public void testAllowMissingFiltersFile() { + executeTarget("testAllowMissingFiltersFile"); + } + private boolean compareFiles(String name1, String name2) { File file1 = new File(System.getProperty("root"), name1); File file2 = new File(System.getProperty("root"), name2);