or end of a file. Discussion started at http://marc.theaimsgroup.com/?l=ant-user&m=106336791228585&w=2 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275260 13f79535-47bb-0310-9956-ffa450edef68master
@@ -604,6 +604,10 @@ Other changes: | |||
used to checkout/list files based on a date instead of a label. | |||
Bugzilla Report 20578. | |||
* New filter <concatfilter>. Adds the content of file at the beginning | |||
or end of a file. Discussion started at | |||
http://marc.theaimsgroup.com/?l=ant-user&m=106336791228585&w=2 | |||
Changes from Ant 1.5.3 to Ant 1.5.4 | |||
=================================== | |||
@@ -0,0 +1,103 @@ | |||
<?xml version="1.0"?> | |||
<project default="cleanup" basedir="."> | |||
<target name="init"> | |||
<mkdir dir="result" /> | |||
<echo file="result/before.txt" message="this-should-be-the-first-line${line.separator}"/> | |||
<echo file="result/after.txt" message="this-should-be-the-last-line${line.separator}"/> | |||
<copy file="input/head-tail.test" tofile="input/concatfilter.test"/> | |||
<fixcrlf srcDir="input" includes="concatfilter.test"/> | |||
</target> | |||
<target name="cleanup"> | |||
<delete dir="result"/> | |||
<delete> | |||
<fileset dir="input" includes="concatfilter.test"/> | |||
</delete> | |||
</target> | |||
<target name="testFilterReaderNoArgs" depends="init"> | |||
<copy file="input/concatfilter.test" | |||
tofile="result/concat.filterReaderNoArgs.test"> | |||
<filterchain> | |||
<filterreader classname="org.apache.tools.ant.filters.ConcatFilter"/> | |||
</filterchain> | |||
</copy> | |||
</target> | |||
<target name="testFilterReaderBefore" depends="init"> | |||
<copy file="input/concatfilter.test" | |||
tofile="result/concat.filterReaderBefore.test"> | |||
<filterchain> | |||
<filterreader classname="org.apache.tools.ant.filters.ConcatFilter"> | |||
<param name="before" value="result/before.txt"/> | |||
</filterreader> | |||
</filterchain> | |||
</copy> | |||
</target> | |||
<target name="testFilterReaderAfter" depends="init"> | |||
<copy file="input/concatfilter.test" | |||
tofile="result/concat.filterReaderAfter.test"> | |||
<filterchain> | |||
<filterreader classname="org.apache.tools.ant.filters.ConcatFilter"> | |||
<param name="after" value="result/after.txt"/> | |||
</filterreader> | |||
</filterchain> | |||
</copy> | |||
</target> | |||
<target name="testFilterReaderBeforeAfter" depends="init"> | |||
<copy file="input/concatfilter.test" | |||
tofile="result/concat.filterReaderBeforeAfter.test"> | |||
<filterchain> | |||
<filterreader classname="org.apache.tools.ant.filters.ConcatFilter"> | |||
<param name="before" value="result/before.txt"/> | |||
<param name="after" value="result/after.txt"/> | |||
</filterreader> | |||
</filterchain> | |||
</copy> | |||
</target> | |||
<target name="testConcatFilter" depends="init"> | |||
<typedef name="concatfilter" classname="org.apache.tools.ant.filters.ConcatFilter"/> | |||
<copy file="input/concatfilter.test" | |||
tofile="result/concat.concatfilter.test"> | |||
<filterchain> | |||
<concatfilter/> | |||
</filterchain> | |||
</copy> | |||
</target> | |||
<target name="testConcatFilterBefore" depends="init"> | |||
<typedef name="concatfilter" classname="org.apache.tools.ant.filters.ConcatFilter"/> | |||
<copy file="input/concatfilter.test" | |||
tofile="result/concat.concatfilterBefore.test"> | |||
<filterchain> | |||
<concatfilter before="result/before.txt"/> | |||
</filterchain> | |||
</copy> | |||
</target> | |||
<target name="testConcatFilterAfter" depends="init"> | |||
<typedef name="concatfilter" classname="org.apache.tools.ant.filters.ConcatFilter"/> | |||
<copy file="input/concatfilter.test" | |||
tofile="result/concat.concatfilterAfter.test"> | |||
<filterchain> | |||
<concatfilter after="result/after.txt"/> | |||
</filterchain> | |||
</copy> | |||
</target> | |||
<target name="testConcatFilterBeforeAfter" depends="init"> | |||
<typedef name="concatfilter" classname="org.apache.tools.ant.filters.ConcatFilter"/> | |||
<copy file="input/concatfilter.test" | |||
tofile="result/concat.concatfilterBeforeAfter.test"> | |||
<filterchain> | |||
<concatfilter before="result/before.txt" after="result/after.txt"/> | |||
</filterchain> | |||
</copy> | |||
</target> | |||
</project> |
@@ -0,0 +1,246 @@ | |||
/* | |||
* 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.IOException; | |||
import java.io.Reader; | |||
import java.io.File; | |||
import java.io.BufferedReader; | |||
import java.io.FileReader; | |||
import org.apache.tools.ant.types.Parameter; | |||
/** | |||
* Concats a file before and/or after the file. | |||
* | |||
* <p>Example:<pre> | |||
* <copy todir="build"> | |||
* <fileset dir="src" includes="*.java"/> | |||
* <filterchain> | |||
* <concatfilter before="apache-license-java.txt"/> | |||
* </filterchain> | |||
* </copy> | |||
* </pre> | |||
* Copies all java sources from <i>src</i> to <i>build</i> and adds the | |||
* content of <i>apache-license-java.txt</i> add the beginning of each | |||
* file.</p> | |||
* | |||
* @since 1.6 | |||
* @version 2003-09-17 | |||
* @author Jan Matèrne | |||
*/ | |||
public final class ConcatFilter extends BaseParamFilterReader | |||
implements ChainableReader { | |||
/** File to add before the content. */ | |||
private File before; | |||
/** File to add after the content. */ | |||
private File after; | |||
/** Reader for before-file. */ | |||
private Reader beforeReader = new EmptyReader(); | |||
/** Reader for after-file. */ | |||
private Reader afterReader = new EmptyReader(); | |||
/** | |||
* Constructor for "dummy" instances. | |||
* | |||
* @see BaseFilterReader#BaseFilterReader() | |||
*/ | |||
public ConcatFilter() { | |||
super(); | |||
} | |||
/** | |||
* Creates a new filtered reader. | |||
* | |||
* @param in A Reader object providing the underlying stream. | |||
* Must not be <code>null</code>. | |||
*/ | |||
public ConcatFilter(final Reader in) { | |||
super(in); | |||
} | |||
/** | |||
* 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 | |||
* 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 | |||
*/ | |||
public int read() throws IOException { | |||
// do the "singleton" initialization | |||
if (!getInitialized()) { | |||
initialize(); | |||
setInitialized(true); | |||
} | |||
int ch = -1; | |||
// The readers return -1 if they end. So simply read the "before" | |||
// after that the "content" and at the end the "after" file. | |||
ch = beforeReader.read(); | |||
if (ch == -1) { | |||
ch = super.read(); | |||
} | |||
if (ch == -1) { | |||
ch = afterReader.read(); | |||
} | |||
return ch; | |||
} | |||
/** | |||
* Sets <i>before</i> attribute. | |||
* @param before new value | |||
*/ | |||
public void setBefore(final File before) { | |||
this.before = before; | |||
} | |||
/** | |||
* Returns <i>before</i> attribute. | |||
* @return before attribute | |||
*/ | |||
public File getBefore() { | |||
return before; | |||
} | |||
/** | |||
* Sets <i>after</i> attribute. | |||
* @param after new value | |||
*/ | |||
public void setAfter(final File after) { | |||
this.after = after; | |||
} | |||
/** | |||
* Returns <i>after</i> attribute. | |||
* @return after attribute | |||
*/ | |||
public File getAfter() { | |||
return after; | |||
} | |||
/** | |||
* Creates a new ConcatReader 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 Reader chain(final Reader rdr) { | |||
ConcatFilter newFilter = new ConcatFilter(rdr); | |||
newFilter.setBefore(getBefore()); | |||
newFilter.setAfter(getAfter()); | |||
// Usually the initialized is set to true. But here it must not. | |||
// Because the before and after readers have to be instantiated | |||
// on runtime | |||
//newFilter.setInitialized(true); | |||
return newFilter; | |||
} | |||
/** | |||
* Scans the parameters list for the "lines" parameter and uses | |||
* it to set the number of lines to be returned in the filtered stream. | |||
* also scan for skip parameter. | |||
*/ | |||
private void initialize() throws IOException { | |||
// get parameters | |||
Parameter[] params = getParameters(); | |||
if (params != null) { | |||
for (int i = 0; i < params.length; i++) { | |||
if ("before".equals(params[i].getName())) { | |||
setBefore(new File(params[i].getValue())); | |||
continue; | |||
} | |||
if ("after".equals(params[i].getName())) { | |||
setAfter(new File(params[i].getValue())); | |||
continue; | |||
} | |||
} | |||
} | |||
if (before != null) { | |||
if (!before.isAbsolute()) { | |||
before = new File(getProject().getBaseDir(), before.getPath()); | |||
} | |||
beforeReader = new BufferedReader(new FileReader(before)); | |||
} | |||
if (after != null) { | |||
if (!after.isAbsolute()) { | |||
after = new File(getProject().getBaseDir(), after.getPath()); | |||
} | |||
afterReader = new BufferedReader(new FileReader(after)); | |||
} | |||
} | |||
/** | |||
* Reader which is always at the end of file. | |||
* Used for easier algorithm (polymorphism instead if-cascades). | |||
*/ | |||
private class EmptyReader extends Reader { | |||
public int read(char[] ch, int i1, int i2) { return -1; } | |||
public void close() { } | |||
} | |||
} |
@@ -0,0 +1,195 @@ | |||
/* | |||
* 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 ConcatReader | |||
* @author Jan Matèrne | |||
*/ | |||
public class ConcatFilterTest extends BuildFileTest { | |||
private static FileUtils fu = FileUtils.newFileUtils(); | |||
private static final String lSep = System.getProperty("line.separator"); | |||
private static final String FILE_BEGINNING_WITH = | |||
"this-should-be-the-first-line" + lSep | |||
+ "Line 1" + lSep | |||
+ "Line 2" + lSep | |||
+ "Line 3" + lSep | |||
+ "Line 4" + lSep | |||
; | |||
private static final String FILE_BEGINNING = | |||
"Line 1" + lSep | |||
+ "Line 2" + lSep | |||
+ "Line 3" + lSep | |||
+ "Line 4" + lSep | |||
+ "Line 5" + lSep | |||
; | |||
private static final String FILE_ENDING_WITH = | |||
"Line 57" + lSep | |||
+ "Line 58" + lSep | |||
+ "Line 59" + lSep | |||
+ "Line 60" + lSep | |||
+ "this-should-be-the-last-line" + lSep | |||
; | |||
private static final String FILE_ENDING = | |||
"Line 56" + lSep | |||
+ "Line 57" + lSep | |||
+ "Line 58" + lSep | |||
+ "Line 59" + lSep | |||
+ "Line 60" + lSep | |||
; | |||
public ConcatFilterTest(String name) { | |||
super(name); | |||
} | |||
public void setUp() { | |||
configureProject("src/etc/testcases/filters/concat.xml"); | |||
} | |||
public void tearDown() { | |||
// I dont know why - but on my machine I always get a | |||
// "Unable to delete file ...result\after.txt" (or before.txt) | |||
// from Delete.removeDir(Delete.java:612). | |||
// Win2000, JDK 1.4.1_02 | |||
// A <sleep> before <delete> doesn´t work. From 10ms to 3000ms. | |||
// I modified the taskdefs.Delete.DELETE_RETRY_SLEEP_MILLIS | |||
// from 10 up to 2000 ms, but no success. | |||
// So I give up - and hope for a suggestion from another one. | |||
// But this shouldn´t let the testcases fail, so I do the cleanup | |||
// inside a try-block | |||
// Jan | |||
try { | |||
executeTarget("cleanup"); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
public void testFilterReaderNoArgs() throws IOException { | |||
executeTarget("testFilterReaderNoArgs"); | |||
File expected = getProject().resolveFile("input/concatfilter.test"); | |||
File result = getProject().resolveFile("result/concat.filterReaderNoArgs.test"); | |||
assertTrue("testFilterReaderNoArgs: Result not like expected", fu.contentEquals(expected, result)); | |||
} | |||
public void testFilterReaderBefore() throws IOException { | |||
executeTarget("testFilterReaderBefore"); | |||
File resultFile = getProject().resolveFile("result/concat.filterReaderBefore.test"); | |||
String resultContent = fu.readFully(new java.io.FileReader(resultFile)); | |||
assertTrue("First 5 lines differs.", resultContent.startsWith(FILE_BEGINNING_WITH)); | |||
assertTrue("Last 5 lines differs.", resultContent.endsWith(FILE_ENDING)); | |||
} | |||
public void testFilterReaderAfter() throws IOException { | |||
executeTarget("testFilterReaderAfter"); | |||
File resultFile = getProject().resolveFile("result/concat.filterReaderAfter.test"); | |||
String resultContent = fu.readFully(new java.io.FileReader(resultFile)); | |||
assertTrue("First 5 lines differs.", resultContent.startsWith(FILE_BEGINNING)); | |||
assertTrue("Last 5 lines differs.", resultContent.endsWith(FILE_ENDING_WITH)); | |||
} | |||
public void testFilterReaderBeforeAfter() throws IOException { | |||
executeTarget("testFilterReaderBeforeAfter"); | |||
File resultFile = getProject().resolveFile("result/concat.filterReaderBeforeAfter.test"); | |||
String resultContent = fu.readFully(new java.io.FileReader(resultFile)); | |||
assertTrue("First 5 lines differs.", resultContent.startsWith(FILE_BEGINNING_WITH)); | |||
assertTrue("Last 5 lines differs.", resultContent.endsWith(FILE_ENDING_WITH)); | |||
} | |||
public void testConcatFilter() throws IOException { | |||
executeTarget("testConcatFilter"); | |||
File resultFile = getProject().resolveFile("result/concat.concatfilter.test"); | |||
String resultContent = fu.readFully(new java.io.FileReader(resultFile)); | |||
assertTrue("First 5 lines differs.", resultContent.startsWith(FILE_BEGINNING)); | |||
assertTrue("Last 5 lines differs.", resultContent.endsWith(FILE_ENDING)); | |||
} | |||
public void testConcatFilterBefore() throws IOException { | |||
executeTarget("testConcatFilterBefore"); | |||
File resultFile = getProject().resolveFile("result/concat.concatfilterBefore.test"); | |||
String resultContent = fu.readFully(new java.io.FileReader(resultFile)); | |||
assertTrue("First 5 lines differs.", resultContent.startsWith(FILE_BEGINNING_WITH)); | |||
assertTrue("Last 5 lines differs.", resultContent.endsWith(FILE_ENDING)); | |||
} | |||
public void testConcatFilterAfter() throws IOException { | |||
executeTarget("testConcatFilterAfter"); | |||
File resultFile = getProject().resolveFile("result/concat.concatfilterAfter.test"); | |||
String resultContent = fu.readFully(new java.io.FileReader(resultFile)); | |||
assertTrue("First 5 lines differs.", resultContent.startsWith(FILE_BEGINNING)); | |||
assertTrue("Last 5 lines differs.", resultContent.endsWith(FILE_ENDING_WITH)); | |||
} | |||
public void testConcatFilterBeforeAfter() throws IOException { | |||
executeTarget("testConcatFilterBeforeAfter"); | |||
File resultFile = getProject().resolveFile("result/concat.concatfilterBeforeAfter.test"); | |||
String resultContent = fu.readFully(new java.io.FileReader(resultFile)); | |||
assertTrue("First 5 lines differs.", resultContent.startsWith(FILE_BEGINNING_WITH)); | |||
assertTrue("Last 5 lines differs.", resultContent.endsWith(FILE_ENDING_WITH)); | |||
} | |||
} |