This is an automated email from the ASF dual-hosted git repository. bodewig pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ant.git
The following commit(s) were added to refs/heads/master by this push: new 3ec6100 #64855 Add filterbeforeconcat option to Concat new a29c130 Merge pull request #141 from TheConstructor/input-file-tokenizer 3ec6100 is described below commit 3ec610046f33d540c3d533ad34529c7ee869a215 Author: Matthias Vill <git...@cconstruct.de> AuthorDate: Thu Oct 29 17:53:57 2020 +0100 #64855 Add filterbeforeconcat option to Concat --- manual/Tasks/concat.html | 9 + src/main/org/apache/tools/ant/taskdefs/Concat.java | 216 +++++++++++++++------ src/tests/antunit/taskdefs/concat-test.xml | 44 +++++ 3 files changed, 209 insertions(+), 60 deletions(-) diff --git a/manual/Tasks/concat.html b/manual/Tasks/concat.html index 513797c..71aba61 100644 --- a/manual/Tasks/concat.html +++ b/manual/Tasks/concat.html @@ -125,6 +125,15 @@ <td>No; default is <q>false</q></td> </tr> <tr> + <td>filterbeforeconcat</td> + <td>If this attribute is set to <q>true</q>, the task applies the filterchain to each + input after applying <code>fixlastline</code>. If this attribute is <q>false</q>, concat + will apply the filterchain only once to the already concatenated inputs. Filtering of + <code>header</code> and <code>footer</code> is not affected by this setting. + <em>Since Ant 1.10.10</em></td> + <td>No; default is <q>false</q></td> + </tr> + <tr> <td>ignoreempty</td> <td><em>Since Ant 1.8.0</em> Specifies whether or not the file specified by <var>destfile</var> should be created if the source resource list is empty. diff --git a/src/main/org/apache/tools/ant/taskdefs/Concat.java b/src/main/org/apache/tools/ant/taskdefs/Concat.java index 333bad9..8a56046 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Concat.java +++ b/src/main/org/apache/tools/ant/taskdefs/Concat.java @@ -212,34 +212,17 @@ public class Concat extends Task implements ResourceCollection { } /** - * This class reads from each of the source files in turn. - * The concatenated result can then be filtered as - * a single stream. + * This class reads a Reader and ensures it ends with the desired linebreak + * @since Ant 1.10.10 */ - private final class MultiReader<S> extends Reader { - private Reader reader = null; - private int lastPos = 0; - private char[] lastChars = new char[eolString.length()]; + private final class LastLineFixingReader extends Reader { + private final Reader reader; + private int lastPos = 0; + private final char[] lastChars = new char[eolString.length()]; private boolean needAddSeparator = false; - private Iterator<S> readerSources; - private ReaderFactory<S> factory; - - private MultiReader(Iterator<S> readerSources, ReaderFactory<S> factory) { - this.readerSources = readerSources; - this.factory = factory; - } - - private Reader getReader() throws IOException { - if (reader == null && readerSources.hasNext()) { - reader = factory.getReader(readerSources.next()); - Arrays.fill(lastChars, (char) 0); - } - return reader; - } - private void nextReader() throws IOException { - close(); - reader = null; + private LastLineFixingReader(Reader reader) { + this.reader = reader; } /** @@ -253,25 +236,21 @@ public class Concat extends Task implements ResourceCollection { public int read() throws IOException { if (needAddSeparator) { if (lastPos >= eolString.length()) { - lastPos = 0; - needAddSeparator = false; + return -1; } else { return eolString.charAt(lastPos++); } } - while (getReader() != null) { - int ch = getReader().read(); - if (ch == -1) { - nextReader(); - if (isFixLastLine() && isMissingEndOfLine()) { - needAddSeparator = true; - lastPos = 1; - return eolString.charAt(0); - } - } else { - addLastChar((char) ch); - return ch; + int ch = reader.read(); + if (ch == -1) { + if (isMissingEndOfLine()) { + needAddSeparator = true; + lastPos = 1; + return eolString.charAt(0); } + } else { + addLastChar((char) ch); + return ch; } return -1; } @@ -289,13 +268,12 @@ public class Concat extends Task implements ResourceCollection { throws IOException { int amountRead = 0; - while (getReader() != null || needAddSeparator) { + while (true) { if (needAddSeparator) { - cbuf[off] = eolString.charAt(lastPos++); if (lastPos >= eolString.length()) { - lastPos = 0; - needAddSeparator = false; + break; } + cbuf[off] = eolString.charAt(lastPos++); len--; off++; amountRead++; @@ -304,23 +282,22 @@ public class Concat extends Task implements ResourceCollection { } continue; } - int nRead = getReader().read(cbuf, off, len); + int nRead = reader.read(cbuf, off, len); if (nRead == -1 || nRead == 0) { - nextReader(); - if (isFixLastLine() && isMissingEndOfLine()) { + if (isMissingEndOfLine()) { needAddSeparator = true; lastPos = 0; + } else { + break; } } else { - if (isFixLastLine()) { - for (int i = nRead; - i > (nRead - lastChars.length); - --i) { - if (i <= 0) { - break; - } - addLastChar(cbuf[off + i - 1]); + for (int i = nRead; + i > (nRead - lastChars.length); + --i) { + if (i <= 0) { + break; } + addLastChar(cbuf[off + i - 1]); } len -= nRead; off += nRead; @@ -341,9 +318,7 @@ public class Concat extends Task implements ResourceCollection { */ @Override public void close() throws IOException { - if (reader != null) { - reader.close(); - } + reader.close(); } /** @@ -367,6 +342,107 @@ public class Concat extends Task implements ResourceCollection { } return false; } + } + + /** + * This class reads from each of the source files in turn. + * The concatenated result can then be filtered as + * a single stream. + */ + private final class MultiReader<S> extends Reader { + private Reader reader = null; + private Iterator<S> readerSources; + private ReaderFactory<S> factory; + private final boolean filterBeforeConcat; + + private MultiReader(Iterator<S> readerSources, ReaderFactory<S> factory, + boolean filterBeforeConcat) { + this.readerSources = readerSources; + this.factory = factory; + this.filterBeforeConcat = filterBeforeConcat; + } + + private Reader getReader() throws IOException { + if (reader == null && readerSources.hasNext()) { + reader = factory.getReader(readerSources.next()); + if(isFixLastLine()) + { + reader = new LastLineFixingReader(reader); + } + if(filterBeforeConcat) + { + reader = getFilteredReader(reader); + } + } + return reader; + } + + private void nextReader() throws IOException { + close(); + reader = null; + } + + /** + * Read a character from the current reader object. Advance + * to the next if the reader is finished. + * @return the character read, -1 for EOF on the last reader. + * @exception IOException - possibly thrown by the read for a reader + * object. + */ + @Override + public int read() throws IOException { + while (getReader() != null) { + int ch = getReader().read(); + if (ch == -1) { + nextReader(); + } else { + return ch; + } + } + return -1; + } + + /** + * Read into the buffer <code>cbuf</code>. + * @param cbuf The array to be read into. + * @param off The offset. + * @param len The length to read. + * @exception IOException - possibly thrown by the reads to the + * reader objects. + */ + @Override + public int read(char[] cbuf, int off, int len) + throws IOException { + + int amountRead = 0; + while (getReader() != null) { + int nRead = getReader().read(cbuf, off, len); + if (nRead == -1 || nRead == 0) { + nextReader(); + } else { + len -= nRead; + off += nRead; + amountRead += nRead; + if (len == 0) { + return amountRead; + } + } + } + if (amountRead == 0) { + return -1; + } + return amountRead; + } + + /** + * Close the current reader + */ + @Override + public void close() throws IOException { + if (reader != null) { + reader.close(); + } + } private boolean isFixLastLine() { return fixLastLine && textBuffer == null; @@ -386,8 +462,14 @@ public class Concat extends Task implements ResourceCollection { result.setManagingComponent(this); return result; } - Reader resourceReader = getFilteredReader( - new MultiReader<>(c.iterator(), resourceReaderFactory)); + Reader resourceReader; + if(filterBeforeConcat) { + resourceReader = new MultiReader<>(c.iterator(), + resourceReaderFactory, true); + } else { + resourceReader = getFilteredReader( + new MultiReader<>(c.iterator(), resourceReaderFactory, false)); + } Reader rdr; if (header == null && footer == null) { rdr = resourceReader; @@ -416,7 +498,7 @@ public class Concat extends Task implements ResourceCollection { } } rdr = new MultiReader<>(Arrays.asList(readers).iterator(), - identityReaderFactory); + identityReaderFactory, false); } return outputEncoding == null ? new ReaderInputStream(rdr) : new ReaderInputStream(rdr, outputEncoding); @@ -454,6 +536,9 @@ public class Concat extends Task implements ResourceCollection { /** Stores the binary attribute */ private boolean binary; + /** Stores the filterBeforeConcat attribute */ + private boolean filterBeforeConcat; + // Child elements. /** @@ -780,6 +865,17 @@ public class Concat extends Task implements ResourceCollection { } /** + * Set the filterBeforeConcat attribute. If true, concat will filter each + * input through the filterchain before concatenating the results. This + * allows to e.g. use the FileTokenizer to tokenize each input. + * @param filterBeforeConcat if true, filter each input before concatenation + * @since Ant 1.10.10 + */ + public void setFilterBeforeConcat(final boolean filterBeforeConcat) { + this.filterBeforeConcat = filterBeforeConcat; + } + + /** * Execute the concat task. */ @Override diff --git a/src/tests/antunit/taskdefs/concat-test.xml b/src/tests/antunit/taskdefs/concat-test.xml index c596d90..82182ff 100644 --- a/src/tests/antunit/taskdefs/concat-test.xml +++ b/src/tests/antunit/taskdefs/concat-test.xml @@ -118,6 +118,50 @@ </au:assertTrue> </target> + <target name="testFilterIsAppliedToConcatenation" + depends="-fixlastline-setup" + description="https://bz.apache.org/bugzilla/show_bug.cgi?id=64855"> + <au:assertTrue> + <resourcesmatch> + <string>1${line.separator}2${line.separator}1${line.separator}2${line.separator}</string> + <concat fixlastline="true"> + <filelist dir="${input}"> + <file name="1"/> + <file name="2"/> + </filelist> + <filterchain> + <tokenfilter> + <filetokenizer/> + <replaceregex pattern="(.*)" flags="s" replace="\1\1"/> + </tokenfilter> + </filterchain> + </concat> + </resourcesmatch> + </au:assertTrue> + </target> + + <target name="testFilterBeforeConcatActuallyAppliesFilterToEachInput" + depends="-fixlastline-setup" + description="https://bz.apache.org/bugzilla/show_bug.cgi?id=64855"> + <au:assertTrue> + <resourcesmatch> + <string>1${line.separator}1${line.separator}2${line.separator}2${line.separator}</string> + <concat fixlastline="true" filterbeforeconcat="true"> + <filelist dir="${input}"> + <file name="1"/> + <file name="2"/> + </filelist> + <filterchain> + <tokenfilter> + <filetokenizer/> + <replaceregex pattern="(.*)" flags="s" replace="\1\1"/> + </tokenfilter> + </filterchain> + </concat> + </resourcesmatch> + </au:assertTrue> + </target> + <target name="testIgnoreEmptyFalseFileIsCreated"> <mkdir dir="${input}" /> <mkdir dir="${output}" />