diff --git a/WHATSNEW b/WHATSNEW index 5bbd50327..63bb359c4 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -60,6 +60,16 @@ Other changes: strings to be present in the line. Bugzilla Report 62313 + * has a new basedir attribute that can be used to + resolve relative names and provides a root for the FileResources + generated. + Bugzilla Report 62379 + + * The and nested elements of + and now support an encoding attribute that + can be used to specify the file's encoding. + Bugzilla Report 62379 + Changes from Ant 1.10.2 TO Ant 1.10.3 ===================================== diff --git a/manual/Types/patternset.html b/manual/Types/patternset.html index 837740b50..9218a154e 100644 --- a/manual/Types/patternset.html +++ b/manual/Types/patternset.html @@ -122,6 +122,11 @@ attributes you can use to test the existence of a property.

is not set. No + + encoding + The encoding of the file. Since Ant 1.10.4 + No, default is platform default +

patternset

Patternsets may be nested within one another, adding the nested patterns to the parent diff --git a/manual/Types/resources.html b/manual/Types/resources.html index 160c96f65..b07f73be5 100644 --- a/manual/Types/resources.html +++ b/manual/Types/resources.html @@ -1249,6 +1249,15 @@ of <filelist>.

The encoding of the nested resources No; default is default JVM character encoding + + basedir + Base directory that is used to resolve relative file names + against. Is also used to provide a base directory to the + FileResources created by this resource collection. Since Ant + 1.10.4 + + No +
Parameters specified as nested elements
diff --git a/src/etc/testcases/types/fileset.xml b/src/etc/testcases/types/fileset.xml new file mode 100644 index 000000000..c0f6949ff --- /dev/null +++ b/src/etc/testcases/types/fileset.xml @@ -0,0 +1,40 @@ + + + + + fileset.xml + + + + + + + ${property} + + + + fileset.xml + + + + + + + ${property} + + diff --git a/src/main/org/apache/tools/ant/taskdefs/Delete.java b/src/main/org/apache/tools/ant/taskdefs/Delete.java index b80c0f05d..22eefa132 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Delete.java +++ b/src/main/org/apache/tools/ant/taskdefs/Delete.java @@ -254,7 +254,7 @@ public class Delete extends MatchingTask { /** * add a name entry on the include files list - * @return a NameEntry object to be configured + * @return a PatternFileNameEntry object to be configured */ @Override public PatternSet.NameEntry createIncludesFile() { @@ -274,7 +274,7 @@ public class Delete extends MatchingTask { /** * add a name entry on the include files list - * @return a NameEntry object to be configured + * @return a PatternFileNameEntry object to be configured */ @Override public PatternSet.NameEntry createExcludesFile() { diff --git a/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java b/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java index 8654bda7b..b659c7488 100644 --- a/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java @@ -78,7 +78,7 @@ public abstract class MatchingTask extends Task implements SelectorContainer { /** * add a name entry on the include files list - * @return an NameEntry object to be configured + * @return an PatternFileNameEntry object to be configured */ public PatternSet.NameEntry createIncludesFile() { return fileset.createIncludesFile(); @@ -94,7 +94,7 @@ public abstract class MatchingTask extends Task implements SelectorContainer { /** * add a name entry on the include files list - * @return an NameEntry object to be configured + * @return an PatternFileNameEntry object to be configured */ public PatternSet.NameEntry createExcludesFile() { return fileset.createExcludesFile(); diff --git a/src/main/org/apache/tools/ant/types/AbstractFileSet.java b/src/main/org/apache/tools/ant/types/AbstractFileSet.java index 482fef4e4..794931a86 100644 --- a/src/main/org/apache/tools/ant/types/AbstractFileSet.java +++ b/src/main/org/apache/tools/ant/types/AbstractFileSet.java @@ -197,7 +197,7 @@ public abstract class AbstractFileSet extends DataType /** * Add a name entry to the include files list. - * @return PatternSet.NameEntry. + * @return PatternSet.PatternFileNameEntry. */ public synchronized PatternSet.NameEntry createIncludesFile() { if (isReference()) { @@ -221,7 +221,7 @@ public abstract class AbstractFileSet extends DataType /** * Add a name entry to the excludes files list. - * @return PatternSet.NameEntry. + * @return PatternSet.PatternFileNameEntry. */ public synchronized PatternSet.NameEntry createExcludesFile() { if (isReference()) { diff --git a/src/main/org/apache/tools/ant/types/PatternSet.java b/src/main/org/apache/tools/ant/types/PatternSet.java index 8a833c87f..cc92a3e28 100644 --- a/src/main/org/apache/tools/ant/types/PatternSet.java +++ b/src/main/org/apache/tools/ant/types/PatternSet.java @@ -19,8 +19,11 @@ package org.apache.tools.ant.types; import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -41,8 +44,8 @@ import org.apache.tools.ant.PropertyHelper; public class PatternSet extends DataType implements Cloneable { private List includeList = new ArrayList<>(); private List excludeList = new ArrayList<>(); - private List includesFileList = new ArrayList<>(); - private List excludesFileList = new ArrayList<>(); + private List includesFileList = new ArrayList<>(); + private List excludesFileList = new ArrayList<>(); /** * inner class to hold a name on list. "If" and "Unless" attributes @@ -178,6 +181,45 @@ public class PatternSet extends DataType implements Cloneable { } } + /** + * Adds encoding support to {@link NameEntry}. + * @since Ant 1.10.4 + */ + public class PatternFileNameEntry extends NameEntry { + private String encoding; + + /** + * Encoding to use when reading the file, defaults to the platform's default + * encoding. + * + *

+ * For a list of possible values see + * + * https://docs.oracle.com/javase/1.5.0/docs/guide/intl/encoding.doc.html. + *

+ * + * @param encoding String + */ + public final void setEncoding(String encoding) { + this.encoding = encoding; + } + + /** + * Encoding to use when reading the file, defaults to the platform's default + * encoding. + */ + public final String getEncoding() { + return encoding; + } + + @Override + public String toString() { + String baseString = super.toString(); + return encoding == null ? baseString + : new StringBuilder(baseString).append(";encoding->").append(encoding).toString(); + } + } + private static final class InvertedPatternSet extends PatternSet { private InvertedPatternSet(PatternSet p) { setProject(p.getProject()); @@ -260,7 +302,7 @@ public class PatternSet extends DataType implements Cloneable { if (isReference()) { throw noChildrenAllowed(); } - return addPatternToList(includesFileList); + return addPatternFileToList(includesFileList); } /** @@ -282,7 +324,7 @@ public class PatternSet extends DataType implements Cloneable { if (isReference()) { throw noChildrenAllowed(); } - return addPatternToList(excludesFileList); + return addPatternFileToList(excludesFileList); } /** @@ -330,6 +372,15 @@ public class PatternSet extends DataType implements Cloneable { return result; } + /** + * add a pattern file name entry to the given list + */ + private PatternFileNameEntry addPatternFileToList(List list) { + PatternFileNameEntry result = new PatternFileNameEntry(); + list.add(result); + return result; + } + /** * Sets the name of the file containing the includes patterns. * @@ -360,11 +411,12 @@ public class PatternSet extends DataType implements Cloneable { * Reads path matching patterns from a file and adds them to the * includes or excludes list (as appropriate). */ - private void readPatterns(File patternfile, List patternlist, Project p) + private void readPatterns(File patternfile, String encoding, List patternlist, Project p) throws BuildException { - try (BufferedReader patternReader = - new BufferedReader(new FileReader(patternfile))) { + try (Reader r = encoding == null ? new FileReader(patternfile) + : new InputStreamReader(new FileInputStream(patternfile), encoding); + BufferedReader patternReader = new BufferedReader(r)) { // Create one NameEntry in the appropriate pattern list for each // line in the file. @@ -470,7 +522,7 @@ public class PatternSet extends DataType implements Cloneable { */ private void readFiles(Project p) { if (!includesFileList.isEmpty()) { - for (NameEntry ne : includesFileList) { + for (PatternFileNameEntry ne : includesFileList) { String fileName = ne.evalName(p); if (fileName != null) { File inclFile = p.resolveFile(fileName); @@ -478,13 +530,13 @@ public class PatternSet extends DataType implements Cloneable { throw new BuildException("Includesfile " + inclFile.getAbsolutePath() + " not found."); } - readPatterns(inclFile, includeList, p); + readPatterns(inclFile, ne.getEncoding(), includeList, p); } } includesFileList.clear(); } if (!excludesFileList.isEmpty()) { - for (NameEntry ne : excludesFileList) { + for (PatternFileNameEntry ne : excludesFileList) { String fileName = ne.evalName(p); if (fileName != null) { File exclFile = p.resolveFile(fileName); @@ -492,7 +544,7 @@ public class PatternSet extends DataType implements Cloneable { throw new BuildException("Excludesfile " + exclFile.getAbsolutePath() + " not found."); } - readPatterns(exclFile, excludeList, p); + readPatterns(exclFile, ne.getEncoding(), excludeList, p); } } excludesFileList.clear(); diff --git a/src/main/org/apache/tools/ant/types/resources/Files.java b/src/main/org/apache/tools/ant/types/resources/Files.java index 43feb64cc..ed56f4d3c 100644 --- a/src/main/org/apache/tools/ant/types/resources/Files.java +++ b/src/main/org/apache/tools/ant/types/resources/Files.java @@ -123,7 +123,7 @@ public class Files extends AbstractSelectorContainer /** * Add a name entry to the include files list. - * @return PatternSet.NameEntry. + * @return PatternSet.PatternFileNameEntry. */ public synchronized PatternSet.NameEntry createIncludesFile() { if (isReference()) { @@ -147,7 +147,7 @@ public class Files extends AbstractSelectorContainer /** * Add a name entry to the excludes files list. - * @return PatternSet.NameEntry. + * @return PatternSet.PatternFileNameEntry. */ public synchronized PatternSet.NameEntry createExcludesFile() { if (isReference()) { diff --git a/src/main/org/apache/tools/ant/types/resources/ResourceList.java b/src/main/org/apache/tools/ant/types/resources/ResourceList.java index 3de844990..9a5fef00f 100644 --- a/src/main/org/apache/tools/ant/types/resources/ResourceList.java +++ b/src/main/org/apache/tools/ant/types/resources/ResourceList.java @@ -19,6 +19,7 @@ package org.apache.tools.ant.types.resources; import java.io.BufferedInputStream; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; @@ -49,6 +50,7 @@ public class ResourceList extends DataType implements ResourceCollection { private final Union cachedResources = new Union(); private volatile boolean cached = false; private String encoding = null; + private File baseDir; public ResourceList() { cachedResources.setCache(true); @@ -99,6 +101,21 @@ public class ResourceList extends DataType implements ResourceCollection { this.encoding = encoding; } + /** + * Basedir to use for file resources read from nested resources - + * this allows the resources contained inside this collection to + * be considered relative to a certain base directory. + * + * @param basedir the basedir + * @since Ant 1.10.4 + */ + public final void setBasedir(File baseDir) { + if (isReference()) { + throw tooManyAttributes(); + } + this.baseDir = baseDir; + } + /** * Makes this instance in effect a reference to another ResourceList * instance. @@ -242,6 +259,11 @@ public class ResourceList extends DataType implements ResourceCollection { // resource } } + if (baseDir != null) { + FileResource fr = new FileResource(baseDir, expandedLine); + fr.setProject(getProject()); + return fr; + } return new FileResource(getProject(), expandedLine); } diff --git a/src/tests/antunit/taskdefs/copy-test.xml b/src/tests/antunit/taskdefs/copy-test.xml index b26da75b7..d0fb49d87 100644 --- a/src/tests/antunit/taskdefs/copy-test.xml +++ b/src/tests/antunit/taskdefs/copy-test.xml @@ -476,4 +476,22 @@ public class NullByteStreamResource extends Resource { + + + + + + + Testfile + + + + + + + + + + diff --git a/src/tests/junit/org/apache/tools/ant/types/FileSetTest.java b/src/tests/junit/org/apache/tools/ant/types/FileSetTest.java index e5aa8758f..3ca5faa46 100644 --- a/src/tests/junit/org/apache/tools/ant/types/FileSetTest.java +++ b/src/tests/junit/org/apache/tools/ant/types/FileSetTest.java @@ -18,17 +18,41 @@ package org.apache.tools.ant.types; +import org.apache.tools.ant.BuildFileRule; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; /** * JUnit 4 testcases for org.apache.tools.ant.types.FileSet. - * - *

This doesn't actually test much, mainly reference handling.

*/ public class FileSetTest extends AbstractFileSetTest { + @Rule + public BuildFileRule buildRule = new BuildFileRule(); + + @Before + public void buildFileRuleSetUp() { + buildRule.configureProject("src/etc/testcases/types/fileset.xml"); + } + protected AbstractFileSet getInstance() { return new FileSet(); } + @Test + public void testNoEncoding() { + buildRule.executeTarget("no-encoding"); + assertEquals("/abc/fileset.xml", buildRule.getLog()); + } + + @Test + public void testEncoding() { + buildRule.executeTarget("encoding"); + assertEquals("/abc/fileset.xml", buildRule.getLog()); + } + } diff --git a/src/tests/junit/org/apache/tools/ant/types/PatternSetTest.java b/src/tests/junit/org/apache/tools/ant/types/PatternSetTest.java index 1cd61e4fe..031c7abad 100644 --- a/src/tests/junit/org/apache/tools/ant/types/PatternSetTest.java +++ b/src/tests/junit/org/apache/tools/ant/types/PatternSetTest.java @@ -20,13 +20,20 @@ package org.apache.tools.ant.types; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; +import org.apache.tools.ant.util.FileUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; /** @@ -211,4 +218,26 @@ public class PatternSetTest { assertEquals("Includes", "**/*.java", includes[0]); assertEquals("Excludes", "**/*.class", excludes[0]); } + + @Test + public void testEncodingOfIncludesFile() throws IOException { + File testFile = File.createTempFile("ant-", ".pattern"); + testFile.deleteOnExit(); + OutputStream o = null; + Writer w = null; + try { + o = new FileOutputStream(testFile); + w = new OutputStreamWriter(o, "UTF-16LE"); + w.write("\u00e4\n"); + } finally { + FileUtils.close(w); + FileUtils.close(o); + } + PatternSet p = new PatternSet(); + PatternSet.PatternFileNameEntry ne = + (PatternSet.PatternFileNameEntry) p.createIncludesFile(); + ne.setName(testFile.getAbsolutePath()); + ne.setEncoding("UTF-16LE"); + assertArrayEquals(new String[] { "\u00e4" }, p.getIncludePatterns(project)); + } }