PR: 18849 Submitted by: jan@materne.de (Jan Mat�rne) git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274446 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -32,6 +32,9 @@ Changes that could break older environments: | |||
| Fixed bugs: | |||
| ----------- | |||
| * A new attribute named skip is added to the TailFilter and | |||
| HeadFilter filter readers. | |||
| * Expand tasks did not behave as expected with PatternSets. | |||
| * <property environment=... /> now works on OS/400. | |||
| @@ -240,7 +240,14 @@ This filter reads the first few lines from the data supplied to it. | |||
| <TR> | |||
| <TD vAlign=top>lines</TD> | |||
| <TD vAlign=top align="center">Number of lines to be read. | |||
| Defaults to "10"</TD> | |||
| Defaults to "10" <BR> A negative value means that all lines are | |||
| passed (useful with <I>skip</I>)</TD> | |||
| <TD vAlign=top align="center">No</TD> | |||
| </TR> | |||
| <TR> | |||
| <TD vAlign=top>skip</TD> | |||
| <TD vAlign=top align="center">Number of lines to be skipped (from the beginning). | |||
| Defaults to "0"</TD> | |||
| <TD vAlign=top align="center">No</TD> | |||
| </TR> | |||
| </TABLE> | |||
| @@ -267,6 +274,19 @@ Convenience method: | |||
| </loadfile> | |||
| </PRE></BLOCKQUOTE> | |||
| This stores the first 15 lines, skipping the first 2 lines, of the supplied data | |||
| in the porperty ${src.file.head}. (Means: lines 3-17) | |||
| <BLOCKQUOTE><PRE> | |||
| <loadfile srcfile="${src.file}" property="${src.file.head}"> | |||
| <filterchain> | |||
| <headfilter lines="15" skip="2"/> | |||
| </filterchain> | |||
| </loadfile> | |||
| </PRE></BLOCKQUOTE> | |||
| See the testcases for more examples (<I>src\etc\testcases\filters\head-tail.xml</I> in the | |||
| source distribution). | |||
| <H3><a name="linecontains">LineContains</a></H3> | |||
| This filter includes only those lines that contain all the user-specified | |||
| @@ -602,11 +622,110 @@ This filter reads the last few lines from the data supplied to it. | |||
| <TR> | |||
| <TD vAlign=top>lines</TD> | |||
| <TD vAlign=top align="center">Number of lines to be read. | |||
| Defaults to "10"</TD> | |||
| Defaults to "10" <BR> A negative value means that all lines are | |||
| passed (useful with <I>skip</I>)</TD> | |||
| <TD vAlign=top align="center">No</TD> | |||
| </TR> | |||
| <TR> | |||
| <TD vAlign=top>skip</TD> | |||
| <TD vAlign=top align="center">Number of lines to be skipped (from the end). | |||
| Defaults to "0" </TD> | |||
| <TD vAlign=top align="center">No</TD> | |||
| </TR> | |||
| </TABLE> | |||
| <P> | |||
| <H4>Background:</H4> | |||
| With HeadFilter and TailFilter you can extract each part of a text file you want. | |||
| This graphic shows the dependencies: | |||
| <TABLE cellSpacing=0 cellPadding=2 border=1> | |||
| <TR> | |||
| <TH> Content </TH> | |||
| <TH></TH> | |||
| <TH></TH> | |||
| <TH></TH> | |||
| <TH> Filter </TH> | |||
| </TR> | |||
| <TR> | |||
| <TD> Line 1 </TD> | |||
| <TD rowspan="2" bgcolor="#C0C0C0"> </TD> | |||
| <TD rowspan="9" bgcolor="#FF00FF"> </TD> | |||
| <TD rowspan="4"> </TD> | |||
| <TD rowspan="11"> | |||
| <TABLE> | |||
| <TR> | |||
| <TD bgcolor="#C0C0C0"> </TD> | |||
| <TD><PRE><filterchain> | |||
| <headfilter lines="2"/> | |||
| </filterchain></PRE></TD> | |||
| </TR> | |||
| <TR> | |||
| <TD bgcolor="#FF00FF"> </TD> | |||
| <TD><PRE><filterchain> | |||
| <tailfilter lines="-1" skip="2"/> | |||
| </filterchain></PRE></TD> | |||
| </TR> | |||
| <TR> | |||
| <TD bgcolor="#008000"> </TD> | |||
| <TD><PRE><filterchain> | |||
| <headfilter lines="-1" skip="2"/> | |||
| </filterchain></PRE></TD> | |||
| </TR> | |||
| <TR> | |||
| <TD bgcolor="#0000FF"> </TD> | |||
| <TD><PRE><filterchain> | |||
| <headfilter lines="-1" skip="2"/> | |||
| <tailfilter lines="-1" skip="2"/> | |||
| </filterchain></PRE></TD> | |||
| </TR> | |||
| <TR> | |||
| <TD bgcolor="#00FF00"> </TD> | |||
| <TD><PRE><filterchain> | |||
| <tailfilter lines="2"/> | |||
| </filterchain></PRE></TD> | |||
| </TR> | |||
| </TABLE> | |||
| </TD> | |||
| </TR> | |||
| <TR> | |||
| <TD> Line 2 </TD> | |||
| </TR> | |||
| <TR> | |||
| <TD> Line 3 </TD> | |||
| <TD rowspan="9" bgcolor="#008000"> </TD> | |||
| </TR> | |||
| <TR> | |||
| <TD> Line 4 </TD> | |||
| </TR> | |||
| <TR> | |||
| <TD> Line 5 </TD> | |||
| <TD rowspan="3" bgcolor="#0000FF"> </TD> | |||
| </TR> | |||
| <TR> | |||
| <TD> Lines ... </TD> | |||
| </TR> | |||
| <TR> | |||
| <TD> Line 95 </TD> | |||
| </TR> | |||
| <TR> | |||
| <TD> Line 96 </TD> | |||
| <TD rowspan="4"> </TD> | |||
| </TR> | |||
| <TR> | |||
| <TD> Line 97 </TD> | |||
| </TR> | |||
| <TR> | |||
| <TD> Line 98 </TD> | |||
| <TD rowspan="2" bgcolor="#00FF00"> </TD> | |||
| </TR> | |||
| <TR> | |||
| <TD> Line 99 </TD> | |||
| </TR> | |||
| </TABLE> | |||
| <H4>Examples:</H4> | |||
| This stores the last 15 lines of the supplied data in the property ${src.file.tail} | |||
| @@ -655,6 +774,18 @@ Convenience method: | |||
| </loadfile> | |||
| </PRE></BLOCKQUOTE> | |||
| This stores the last 10 lines, skipping the last 2 lines, of the supplied data | |||
| in the porperty ${src.file.head}. (Means: if supplied data contains 60 lines, | |||
| lines 49-58 are extracted) | |||
| <BLOCKQUOTE><PRE> | |||
| <loadfile srcfile="${src.file}" property="${src.file.head}"> | |||
| <filterchain> | |||
| <tailfilter lines="10" skip="2"/> | |||
| </filterchain> | |||
| </loadfile> | |||
| </PRE></BLOCKQUOTE> | |||
| <HR> | |||
| <P align=center>Copyright © 2002-2003 Apache Software Foundation. All rights | |||
| @@ -0,0 +1,10 @@ | |||
| Line 1 | |||
| Line 2 | |||
| Line 3 | |||
| Line 4 | |||
| Line 5 | |||
| Line 6 | |||
| Line 7 | |||
| Line 8 | |||
| Line 9 | |||
| Line 10 | |||
| @@ -0,0 +1,58 @@ | |||
| Line 3 | |||
| Line 4 | |||
| Line 5 | |||
| Line 6 | |||
| Line 7 | |||
| Line 8 | |||
| Line 9 | |||
| Line 10 | |||
| Line 11 | |||
| Line 12 | |||
| Line 13 | |||
| Line 14 | |||
| Line 15 | |||
| Line 16 | |||
| Line 17 | |||
| Line 18 | |||
| Line 19 | |||
| Line 20 | |||
| Line 21 | |||
| Line 22 | |||
| Line 23 | |||
| Line 24 | |||
| Line 25 | |||
| Line 26 | |||
| Line 27 | |||
| Line 28 | |||
| Line 29 | |||
| Line 30 | |||
| Line 31 | |||
| Line 32 | |||
| Line 33 | |||
| Line 34 | |||
| Line 35 | |||
| Line 36 | |||
| Line 37 | |||
| Line 38 | |||
| Line 39 | |||
| Line 40 | |||
| Line 41 | |||
| Line 42 | |||
| Line 43 | |||
| Line 44 | |||
| Line 45 | |||
| Line 46 | |||
| Line 47 | |||
| Line 48 | |||
| Line 49 | |||
| Line 50 | |||
| Line 51 | |||
| Line 52 | |||
| Line 53 | |||
| Line 54 | |||
| Line 55 | |||
| Line 56 | |||
| Line 57 | |||
| Line 58 | |||
| Line 59 | |||
| Line 60 | |||
| @@ -0,0 +1,2 @@ | |||
| Line 1 | |||
| Line 2 | |||
| @@ -0,0 +1,2 @@ | |||
| Line 3 | |||
| Line 4 | |||
| @@ -0,0 +1,10 @@ | |||
| Line 3 | |||
| Line 4 | |||
| Line 5 | |||
| Line 6 | |||
| Line 7 | |||
| Line 8 | |||
| Line 9 | |||
| Line 10 | |||
| Line 11 | |||
| Line 12 | |||
| @@ -0,0 +1 @@ | |||
| Line 4 | |||
| @@ -0,0 +1,10 @@ | |||
| Line 51 | |||
| Line 52 | |||
| Line 53 | |||
| Line 54 | |||
| Line 55 | |||
| Line 56 | |||
| Line 57 | |||
| Line 58 | |||
| Line 59 | |||
| Line 60 | |||
| @@ -0,0 +1,58 @@ | |||
| Line 1 | |||
| Line 2 | |||
| Line 3 | |||
| Line 4 | |||
| Line 5 | |||
| Line 6 | |||
| Line 7 | |||
| Line 8 | |||
| Line 9 | |||
| Line 10 | |||
| Line 11 | |||
| Line 12 | |||
| Line 13 | |||
| Line 14 | |||
| Line 15 | |||
| Line 16 | |||
| Line 17 | |||
| Line 18 | |||
| Line 19 | |||
| Line 20 | |||
| Line 21 | |||
| Line 22 | |||
| Line 23 | |||
| Line 24 | |||
| Line 25 | |||
| Line 26 | |||
| Line 27 | |||
| Line 28 | |||
| Line 29 | |||
| Line 30 | |||
| Line 31 | |||
| Line 32 | |||
| Line 33 | |||
| Line 34 | |||
| Line 35 | |||
| Line 36 | |||
| Line 37 | |||
| Line 38 | |||
| Line 39 | |||
| Line 40 | |||
| Line 41 | |||
| Line 42 | |||
| Line 43 | |||
| Line 44 | |||
| Line 45 | |||
| Line 46 | |||
| Line 47 | |||
| Line 48 | |||
| Line 49 | |||
| Line 50 | |||
| Line 51 | |||
| Line 52 | |||
| Line 53 | |||
| Line 54 | |||
| Line 55 | |||
| Line 56 | |||
| Line 57 | |||
| Line 58 | |||
| @@ -0,0 +1,2 @@ | |||
| Line 59 | |||
| Line 60 | |||
| @@ -0,0 +1,2 @@ | |||
| Line 57 | |||
| Line 58 | |||
| @@ -0,0 +1,10 @@ | |||
| Line 49 | |||
| Line 50 | |||
| Line 51 | |||
| Line 52 | |||
| Line 53 | |||
| Line 54 | |||
| Line 55 | |||
| Line 56 | |||
| Line 57 | |||
| Line 58 | |||
| @@ -0,0 +1,107 @@ | |||
| <?xml version="1.0"?> | |||
| <project default="cleanup" basedir="."> | |||
| <target name="init"> | |||
| <mkdir dir="result" /> | |||
| </target> | |||
| <target name="cleanup"> | |||
| <delete dir="result"/> | |||
| </target> | |||
| <!-- Testcases for HeadFilter --> | |||
| <target name="testHead" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.head.test"> | |||
| <filterchain> | |||
| <headfilter/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| <target name="testHeadLines" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.headLines.test"> | |||
| <filterchain> | |||
| <headfilter lines="2"/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| <target name="testHeadSkip" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.headSkip.test"> | |||
| <filterchain> | |||
| <headfilter skip="2"/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| <target name="testHeadLinesSkip" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.headLinesSkip.test"> | |||
| <filterchain> | |||
| <headfilter lines="2" skip="2"/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| <target name="testHeadAllSkip" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.headAllSkip.test"> | |||
| <filterchain> | |||
| <headfilter lines="-1" skip="2"/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| <!-- Testcases for TailFilter --> | |||
| <target name="testTail" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.tail.test"> | |||
| <filterchain> | |||
| <tailfilter/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| <target name="testTailLines" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.tailLines.test"> | |||
| <filterchain> | |||
| <tailfilter lines="2"/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| <target name="testTailSkip" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.tailSkip.test"> | |||
| <filterchain> | |||
| <tailfilter skip="2"/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| <target name="testTailLinesSkip" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.tailLinesSkip.test"> | |||
| <filterchain> | |||
| <tailfilter lines="2" skip="2"/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| <target name="testTailAllSkip" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.tailAllSkip.test"> | |||
| <filterchain> | |||
| <tailfilter lines="-1" skip="2"/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| <!-- Testcases for combined scenarios --> | |||
| <target name="testHeadTail" depends="init"> | |||
| <copy file="input/head-tail.test" tofile="result/head-tail.headtail.test"> | |||
| <filterchain> | |||
| <headfilter lines="4"/> | |||
| <tailfilter lines="2"/> | |||
| </filterchain> | |||
| </copy> | |||
| </target> | |||
| </project> | |||
| @@ -0,0 +1,5 @@ | |||
| Line 1 | |||
| Line 2 | |||
| Line 3 | |||
| Line 4 | |||
| Line 5 | |||
| @@ -0,0 +1,60 @@ | |||
| Line 1 | |||
| Line 2 | |||
| Line 3 | |||
| Line 4 | |||
| Line 5 | |||
| Line 6 | |||
| Line 7 | |||
| Line 8 | |||
| Line 9 | |||
| Line 10 | |||
| Line 11 | |||
| Line 12 | |||
| Line 13 | |||
| Line 14 | |||
| Line 15 | |||
| Line 16 | |||
| Line 17 | |||
| Line 18 | |||
| Line 19 | |||
| Line 20 | |||
| Line 21 | |||
| Line 22 | |||
| Line 23 | |||
| Line 24 | |||
| Line 25 | |||
| Line 26 | |||
| Line 27 | |||
| Line 28 | |||
| Line 29 | |||
| Line 30 | |||
| Line 31 | |||
| Line 32 | |||
| Line 33 | |||
| Line 34 | |||
| Line 35 | |||
| Line 36 | |||
| Line 37 | |||
| Line 38 | |||
| Line 39 | |||
| Line 40 | |||
| Line 41 | |||
| Line 42 | |||
| Line 43 | |||
| Line 44 | |||
| Line 45 | |||
| Line 46 | |||
| Line 47 | |||
| Line 48 | |||
| Line 49 | |||
| Line 50 | |||
| Line 51 | |||
| Line 52 | |||
| Line 53 | |||
| Line 54 | |||
| Line 55 | |||
| Line 56 | |||
| Line 57 | |||
| Line 58 | |||
| Line 59 | |||
| Line 60 | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2002 The Apache Software Foundation. All rights | |||
| * Copyright (c) 2002-2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| @@ -76,15 +76,21 @@ public final class HeadFilter | |||
| /** Parameter name for the number of lines to be returned. */ | |||
| private static final String LINES_KEY = "lines"; | |||
| /** Parameter name for the number of lines to be skipped. */ | |||
| private static final String SKIP_KEY = "skip"; | |||
| /** Number of lines currently read in. */ | |||
| private long linesRead = 0; | |||
| /** Number of lines to be returned in the filtered stream. */ | |||
| private long lines = 10; | |||
| /** Number of lines to be skipped. */ | |||
| private long skip = 0; | |||
| /** | |||
| * Constructor for "dummy" instances. | |||
| * | |||
| * | |||
| * @see BaseFilterReader#BaseFilterReader() | |||
| */ | |||
| public HeadFilter() { | |||
| @@ -104,14 +110,14 @@ public final class HeadFilter | |||
| /** | |||
| * Returns the next character in the filtered stream. If the desired | |||
| * number of lines have already been read, the resulting stream is | |||
| * effectively at an end. Otherwise, the next character from the | |||
| * effectively at an end. Otherwise, the next character from the | |||
| * underlying stream is read and returned. | |||
| * | |||
| * | |||
| * @return the next character in the resulting stream, or -1 | |||
| * if the end of the resulting stream has been reached | |||
| * | |||
| * | |||
| * @exception IOException if the underlying stream throws an IOException | |||
| * during reading | |||
| * during reading | |||
| */ | |||
| public final int read() throws IOException { | |||
| if (!getInitialized()) { | |||
| @@ -121,7 +127,13 @@ public final class HeadFilter | |||
| int ch = -1; | |||
| if (linesRead < lines) { | |||
| // skip the lines (if set) | |||
| while (skip > 0) { | |||
| for (int tmp = in.read(); tmp != '\n'; tmp = in.read()); | |||
| skip--; | |||
| } | |||
| if ( (linesRead < lines) || (lines < 0) ){ | |||
| ch = in.read(); | |||
| @@ -135,7 +147,7 @@ public final class HeadFilter | |||
| /** | |||
| * Sets the number of lines to be returned in the filtered stream. | |||
| * | |||
| * | |||
| * @param lines the number of lines to be returned in the filtered stream | |||
| */ | |||
| public final void setLines(final long lines) { | |||
| @@ -144,26 +156,45 @@ public final class HeadFilter | |||
| /** | |||
| * Returns the number of lines to be returned in the filtered stream. | |||
| * | |||
| * | |||
| * @return the number of lines to be returned in the filtered stream | |||
| */ | |||
| private final long getLines() { | |||
| return lines; | |||
| } | |||
| /** | |||
| * Sets the number of lines to be skipped in the filtered stream. | |||
| * | |||
| * @param lines the number of lines to be skipped in the filtered stream | |||
| */ | |||
| public final void setSkip(final long skip) { | |||
| this.skip = skip; | |||
| } | |||
| /** | |||
| * Returns the number of lines to be skipped in the filtered stream. | |||
| * | |||
| * @return the number of lines to be skipped in the filtered stream | |||
| */ | |||
| private final long getSkip() { | |||
| return skip; | |||
| } | |||
| /** | |||
| * Creates a new HeadFilter using the passed in | |||
| * Reader for instantiation. | |||
| * | |||
| * | |||
| * @param rdr A Reader object providing the underlying stream. | |||
| * Must not be <code>null</code>. | |||
| * | |||
| * | |||
| * @return a new filter based on this configuration, but filtering | |||
| * the specified reader | |||
| */ | |||
| public final Reader chain(final Reader rdr) { | |||
| HeadFilter newFilter = new HeadFilter(rdr); | |||
| newFilter.setLines(getLines()); | |||
| newFilter.setSkip(getSkip()); | |||
| newFilter.setInitialized(true); | |||
| return newFilter; | |||
| } | |||
| @@ -180,6 +211,10 @@ public final class HeadFilter | |||
| lines = new Long(params[i].getValue()).longValue(); | |||
| break; | |||
| } | |||
| if (SKIP_KEY.equals(params[i].getName())) { | |||
| skip = new Long(params[i].getValue()).longValue(); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2002 The Apache Software Foundation. All rights | |||
| * Copyright (c) 2002-2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| @@ -78,12 +78,18 @@ public final class TailFilter | |||
| /** Parameter name for the number of lines to be returned. */ | |||
| private static final String LINES_KEY = "lines"; | |||
| /** Parameter name for the number of lines to be skipped. */ | |||
| private static final String SKIP_KEY = "skip"; | |||
| /** Number of lines currently read in. */ | |||
| private long linesRead = 0; | |||
| /** Number of lines to be returned in the filtered stream. */ | |||
| private long lines = 10; | |||
| /** Number of lines to be skipped. */ | |||
| private long skip = 0; | |||
| /** Buffer to hold in characters read ahead. */ | |||
| private char[] buffer = new char[4096]; | |||
| @@ -98,7 +104,7 @@ public final class TailFilter | |||
| /** | |||
| * Constructor for "dummy" instances. | |||
| * | |||
| * | |||
| * @see BaseFilterReader#BaseFilterReader() | |||
| */ | |||
| public TailFilter() { | |||
| @@ -121,12 +127,12 @@ public final class TailFilter | |||
| * Otherwise, the stream is read to the end and buffered (with the buffer | |||
| * growing as necessary), then the appropriate position in the buffer is | |||
| * set to read from. | |||
| * | |||
| * | |||
| * @return the next character in the resulting stream, or -1 | |||
| * if the end of the resulting stream has been reached | |||
| * | |||
| * | |||
| * @exception IOException if the underlying stream throws an IOException | |||
| * during reading | |||
| * during reading | |||
| */ | |||
| public final int read() throws IOException { | |||
| if (!getInitialized()) { | |||
| @@ -152,16 +158,18 @@ public final class TailFilter | |||
| } | |||
| } | |||
| if (ch == '\n' || ch == -1) { | |||
| ++linesRead; | |||
| if (lines > 0) { | |||
| if (ch == '\n' || ch == -1) { | |||
| ++linesRead; | |||
| if (linesRead == lines) { | |||
| int i = 0; | |||
| for (i = returnedCharPos + 1; | |||
| buffer[i] != 0 && buffer[i] != '\n'; i++) { | |||
| if ((linesRead == lines + skip)) { | |||
| int i = 0; | |||
| for (i = returnedCharPos + 1; | |||
| buffer[i] != 0 && buffer[i] != '\n'; i++) { | |||
| } | |||
| returnedCharPos = i; | |||
| --linesRead; | |||
| } | |||
| returnedCharPos = i; | |||
| --linesRead; | |||
| } | |||
| } | |||
| if (ch == -1) { | |||
| @@ -174,6 +182,26 @@ public final class TailFilter | |||
| completedReadAhead = true; | |||
| } | |||
| // Because the complete stream is read into the buffer I can delete | |||
| // the "skip lines" from back to the beginning. | |||
| if (skip > 0) { | |||
| // searching... | |||
| int i; | |||
| for (i = buffer.length - 1; skip > 0; i--) { | |||
| if (buffer[i]=='\n') { | |||
| skip--; | |||
| } | |||
| } | |||
| // cut the buffer to the new length | |||
| char[] newBuffer = new char[i]; | |||
| System.arraycopy(buffer, 0, newBuffer, 0, i); | |||
| buffer = newBuffer; | |||
| // don´t forget to set the "lastposition" new | |||
| bufferPos = i; | |||
| } | |||
| ++returnedCharPos; | |||
| if (returnedCharPos >= bufferPos) { | |||
| return -1; | |||
| @@ -184,7 +212,7 @@ public final class TailFilter | |||
| /** | |||
| * Sets the number of lines to be returned in the filtered stream. | |||
| * | |||
| * | |||
| * @param lines the number of lines to be returned in the filtered stream | |||
| */ | |||
| public final void setLines(final long lines) { | |||
| @@ -193,26 +221,45 @@ public final class TailFilter | |||
| /** | |||
| * Returns the number of lines to be returned in the filtered stream. | |||
| * | |||
| * | |||
| * @return the number of lines to be returned in the filtered stream | |||
| */ | |||
| private final long getLines() { | |||
| return lines; | |||
| } | |||
| /** | |||
| * Sets the number of lines to be skipped in the filtered stream. | |||
| * | |||
| * @param lines the number of lines to be skipped in the filtered stream | |||
| */ | |||
| public final void setSkip(final long skip) { | |||
| this.skip = skip; | |||
| } | |||
| /** | |||
| * Returns the number of lines to be skipped in the filtered stream. | |||
| * | |||
| * @return the number of lines to be skipped in the filtered stream | |||
| */ | |||
| private final long getSkip() { | |||
| return skip; | |||
| } | |||
| /** | |||
| * Creates a new TailFilter using the passed in | |||
| * Reader for instantiation. | |||
| * | |||
| * | |||
| * @param rdr A Reader object providing the underlying stream. | |||
| * Must not be <code>null</code>. | |||
| * | |||
| * | |||
| * @return a new filter based on this configuration, but filtering | |||
| * the specified reader | |||
| */ | |||
| public final Reader chain(final Reader rdr) { | |||
| TailFilter newFilter = new TailFilter(rdr); | |||
| newFilter.setLines(getLines()); | |||
| newFilter.setSkip(getSkip()); | |||
| newFilter.setInitialized(true); | |||
| return newFilter; | |||
| } | |||
| @@ -229,6 +276,10 @@ public final class TailFilter | |||
| setLines(new Long(params[i].getValue()).longValue()); | |||
| break; | |||
| } | |||
| if (SKIP_KEY.equals(params[i].getName())) { | |||
| skip = new Long(params[i].getValue()).longValue(); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,155 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "Ant" and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * permission, please contact apache@apache.org. | |||
| * | |||
| * 5. Products derived from this software may not be called "Apache" | |||
| * nor may "Apache" appear in their names without prior written | |||
| * permission of the Apache Group. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
| * SUCH DAMAGE. | |||
| * ==================================================================== | |||
| * | |||
| * This software consists of voluntary contributions made by many | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.filters; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import org.apache.tools.ant.BuildFileTest; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| /** JUnit Testcases for TailFilter and HeadFilter | |||
| * @author <a href="mailto:jan@materne.de">Jan Matèrne</a> | |||
| */ | |||
| /* I wrote the testcases in one java file because I want also to test the | |||
| * combined behaviour (see end of the class). | |||
| */ | |||
| public class HeadTailTest extends BuildFileTest { | |||
| public HeadTailTest(String name) { | |||
| super(name); | |||
| } | |||
| public void setUp() { | |||
| configureProject("src/etc/testcases/filters/head-tail.xml"); | |||
| } | |||
| public void tearDown() { | |||
| executeTarget("cleanup"); | |||
| } | |||
| public void testHead() throws IOException { | |||
| executeTarget("testHead"); | |||
| File expected = getProject().resolveFile("expected/head-tail.head.test"); | |||
| File result = getProject().resolveFile("result/head-tail.head.test"); | |||
| FileUtils fu = FileUtils.newFileUtils(); | |||
| assertTrue("testHead: Result not like expected", fu.contentEquals(expected, result)); | |||
| } | |||
| public void testHeadLines() throws IOException { | |||
| executeTarget("testHeadLines"); | |||
| File expected = getProject().resolveFile("expected/head-tail.headLines.test"); | |||
| File result = getProject().resolveFile("result/head-tail.headLines.test"); | |||
| FileUtils fu = FileUtils.newFileUtils(); | |||
| assertTrue("testHeadLines: Result not like expected", fu.contentEquals(expected, result)); | |||
| } | |||
| public void testHeadSkip() throws IOException { | |||
| executeTarget("testHeadSkip"); | |||
| File expected = getProject().resolveFile("expected/head-tail.headSkip.test"); | |||
| File result = getProject().resolveFile("result/head-tail.headSkip.test"); | |||
| FileUtils fu = FileUtils.newFileUtils(); | |||
| assertTrue("testHeadSkip: Result not like expected", fu.contentEquals(expected, result)); | |||
| } | |||
| public void testHeadLinesSkip() throws IOException { | |||
| executeTarget("testHeadLinesSkip"); | |||
| File expected = getProject().resolveFile("expected/head-tail.headLinesSkip.test"); | |||
| File result = getProject().resolveFile("result/head-tail.headLinesSkip.test"); | |||
| FileUtils fu = FileUtils.newFileUtils(); | |||
| assertTrue("testHeadLinesSkip: Result not like expected", fu.contentEquals(expected, result)); | |||
| } | |||
| public void testTail() throws IOException { | |||
| executeTarget("testTail"); | |||
| File expected = getProject().resolveFile("expected/head-tail.tail.test"); | |||
| File result = getProject().resolveFile("result/head-tail.tail.test"); | |||
| FileUtils fu = FileUtils.newFileUtils(); | |||
| assertTrue("testTail: Result not like expected", fu.contentEquals(expected, result)); | |||
| } | |||
| public void testTailLines() throws IOException { | |||
| executeTarget("testTailLines"); | |||
| File expected = getProject().resolveFile("expected/head-tail.tailLines.test"); | |||
| File result = getProject().resolveFile("result/head-tail.tailLines.test"); | |||
| FileUtils fu = FileUtils.newFileUtils(); | |||
| assertTrue("testTailLines: Result not like expected", fu.contentEquals(expected, result)); | |||
| } | |||
| public void testTailSkip() throws IOException { | |||
| executeTarget("testTailSkip"); | |||
| File expected = getProject().resolveFile("expected/head-tail.tailSkip.test"); | |||
| File result = getProject().resolveFile("result/head-tail.tailSkip.test"); | |||
| FileUtils fu = FileUtils.newFileUtils(); | |||
| assertTrue("testTailSkip: Result not like expected", fu.contentEquals(expected, result)); | |||
| } | |||
| public void testTailLinesSkip() throws IOException { | |||
| executeTarget("testTailLinesSkip"); | |||
| File expected = getProject().resolveFile("expected/head-tail.tailLinesSkip.test"); | |||
| File result = getProject().resolveFile("result/head-tail.tailLinesSkip.test"); | |||
| FileUtils fu = FileUtils.newFileUtils(); | |||
| assertTrue("testTailLinesSkip: Result not like expected", fu.contentEquals(expected, result)); | |||
| } | |||
| public void testHeadTail() throws IOException { | |||
| executeTarget("testHeadTail"); | |||
| File expected = getProject().resolveFile("expected/head-tail.headTail.test"); | |||
| File result = getProject().resolveFile("result/head-tail.headTail.test"); | |||
| FileUtils fu = FileUtils.newFileUtils(); | |||
| assertTrue("testHeadTail: Result not like expected", fu.contentEquals(expected, result)); | |||
| } | |||
| } | |||