From 3ec610046f33d540c3d533ad34529c7ee869a215 Mon Sep 17 00:00:00 2001 From: Matthias Vill Date: Thu, 29 Oct 2020 17:53:57 +0100 Subject: [PATCH] #64855 Add filterbeforeconcat option to Concat --- manual/Tasks/concat.html | 9 + .../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 513797ce7..71aba6148 100644 --- a/manual/Tasks/concat.html +++ b/manual/Tasks/concat.html @@ -124,6 +124,15 @@ be used. No; default is false + + filterbeforeconcat + If this attribute is set to true, the task applies the filterchain to each + input after applying fixlastline. If this attribute is false, concat + will apply the filterchain only once to the already concatenated inputs. Filtering of + header and footer is not affected by this setting. + Since Ant 1.10.10 + No; default is false + ignoreempty Since Ant 1.8.0 Specifies whether or not the file specified diff --git a/src/main/org/apache/tools/ant/taskdefs/Concat.java b/src/main/org/apache/tools/ant/taskdefs/Concat.java index 333bad905..8a56046c6 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 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 readerSources; - private ReaderFactory factory; - - private MultiReader(Iterator readerSources, ReaderFactory 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 extends Reader { + private Reader reader = null; + private Iterator readerSources; + private ReaderFactory factory; + private final boolean filterBeforeConcat; + + private MultiReader(Iterator readerSources, ReaderFactory 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 cbuf. + * @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. /** @@ -779,6 +864,17 @@ public class Concat extends Task implements ResourceCollection { this.binary = binary; } + /** + * 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. */ diff --git a/src/tests/antunit/taskdefs/concat-test.xml b/src/tests/antunit/taskdefs/concat-test.xml index c596d904d..82182ffb2 100644 --- a/src/tests/antunit/taskdefs/concat-test.xml +++ b/src/tests/antunit/taskdefs/concat-test.xml @@ -118,6 +118,50 @@ + + + + 1${line.separator}2${line.separator}1${line.separator}2${line.separator} + + + + + + + + + + + + + + + + + + + + 1${line.separator}1${line.separator}2${line.separator}2${line.separator} + + + + + + + + + + + + + + + +