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)); | |||
} | |||
} |