You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by EL...@desknetinc.com on 2000/07/17 19:02:35 UTC
Multiline Replace Task
As this is my first ant-dev posting, please feel free to point out any
mailing list wrongdoings I may be guilty of... :-).
I had a need to do multiline replaces with Ant, but couldn't figure out a
solution using the current <replace> task. Therefore, I created a new
task, <dnreplace>, that uses nested tasks, <dntoken> and <dnvalue>, to
specify the token and value.
As an example of it's use:
<dnreplace file="foo.txt">
<dntoken><![CDATA[I am a
multiline
token]]></dntoken>
<dnvalue><![CDATA[I am a
multiline
value]]></dnvalue>
</dnreplace>
This snippet would replace "I am a\nmultiline\ntoken" with "I am
a\nmultiline\nvalue" in the file foo.txt, where '\n' is os-dependent.
For those that might be interested, here are the 3 source files:
===================================================
DnToken.java
===================================================
/*
This task is used with DnReplace.java.
*/
package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.Task;
public class DnToken extends Task {
String text;
public Object addText(String text) {
this.text = text;
return null;
}
public String getText() {
return text;
}
}
===================================================
DnValue.java
===================================================
/*
This task is used with DnReplace.java.
*/
package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.Task;
public class DnValue extends Task {
String text;
public Object addText(String text) {
this.text = text;
return null;
}
public String getText() {
return text;
}
}
===================================================
DnReplace.java
===================================================
/*
This task is used to replace a token with a value in a file. Instead
of using
attributes to assign the token and value, it uses included tasks.
This allows
for multi-line tokens and values.
<dntoken> is required and must have a non-empty value (e.g.,
<dntoken></dntoken) is not allowed)
if <dnvalue> is not supplied or is supplied with an empty value, the
token will be
replaced with nothing.
**NOTE: the length of the file must fit into an integer (we cast from
long to int)
Example:
<dnreplace file="foo.txt">
<dntoken><![CDATA[I am a
multiline
token]]></dntoken>
<dnvalue><![CDATA[I am a
multiline
value]]></dnvalue>
</dnreplace>
*/
package org.apache.tools.ant.taskdefs;
import java.util.*;
import java.io.*;
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.DnToken;
import org.apache.tools.ant.taskdefs.DnValue;
public class DnReplace extends Task {
private File src = null;
private File dest = null;
DnToken dnToken = null;
DnValue dnValue = null;
String token = null;
String value = null;
// a mutable integer class
class IntMut {
int val;
IntMut(int i) {
setVal(i);
}
void setVal(int i) {
val = i;
}
int getVal() {
return val;
}
}
// The method executing the task
public void execute() throws BuildException {
String token,value;
// get and check token and value strings
if (dnToken == null) {
project.log("A token must be provided using the <dntoken>
element.");
return;
}
token = dnToken.getText();
if (token == null || token.length() == 0) {
project.log("The token must have length > 0.");
return;
}
if (dnValue == null) {
value = null;
} else {
value = dnValue.getText();
}
// replace properties in token & value
if (token != null) {
token =
ProjectHelper.replaceProperties(token,project.getProperties());
}
if (value != null) {
value =
ProjectHelper.replaceProperties(value,project.getProperties());
}
// check file
if (src == null) {
project.log("The file must not be null.");
}
if (dest == null) {
throw new BuildException("Error creating temp file.");
}
// tell the user what we're doing
project.log("Replacing:\n" + token + "\nwith:\n" + value);
// do the replace
try {
BufferedReader br = new BufferedReader(new FileReader(src));
BufferedWriter bw = new BufferedWriter(new
FileWriter(dest));
// read the entire file into a char[]
int fileLength = (int)(src.length());
char[] tmpBuf = new char[fileLength];
int numread = 0;
int totread = 0;
while (numread != -1 && totread < fileLength) {
numread = br.read(tmpBuf,totread,fileLength);
totread += numread;
}
// create a String so we can use indexOf
String buf = new String(tmpBuf);
// line separators in values and tokens are "\n"
// in order to compare with the file contents, replace them
as needed
String linesep = System.getProperty("line.separator");
if (value != null) {
value = stringReplace(value,"\n",linesep,null);
}
if (token != null) {
token = stringReplace(token,"\n",linesep,null);
}
// for each found token, replace with value and write to the
output file
IntMut numoccur = new IntMut(0);
buf = stringReplace(buf,token,value,numoccur);
bw.write(buf,0,buf.length());
bw.flush();
// report stats
System.out.println("Replaced " + numoccur.getVal() + "
occurrence(s).");
// cleanup
bw.close();
br.close();
src.delete();
dest.renameTo(src);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
// replace occurrences of str1 in string str with str2
private String stringReplace(String str, String str1, String str2,
IntMut numoccur) {
String ret = new String();
int occur = 0;
int start = 0;
int found = str.indexOf(str1);
while (found >= 0) {
occur++;
// write everything up to the found str1
if (found > start) {
ret = ret.concat(str.substring(start,found));
}
// write the replacement str2
if (str2 != null) {
ret = ret.concat(str2);
}
// search again
start = found + str1.length();
found = str.indexOf(str1,start);
}
// write the remaining characters
if (str.length() > start) {
ret = ret.concat(str.substring(start,str.length()));
}
// return results
if (numoccur != null) {
numoccur.setVal(occur);
}
return ret;
}
// print the supplied string as integer values of each character
// used for debugging only
public void debugString(String label, String str) {
System.out.println(label);
int j = 0;
while (j < str.length()) {
System.out.println("str[" + j + "] = " +
(int)str.charAt(j));
j++;
}
}
// The setter for the "file" attribute
public void setFile(String file) {
this.src = project.resolveFile(file);
this.dest = project.resolveFile(file + ".temp");
}
// Create a task for nested dntokens
public Task createDntoken() {
dnToken = (DnToken) project.createTask("dntoken");
return dnToken;
}
// Create a task for nested dnvalues
public Task createDnvalue() {
dnValue = (DnValue) project.createTask("dnvalue");
return dnValue;
}
}
______________________________________________
Erik Langenbach
erik@desknetinc.com
Re: Multiline Replace Task
Posted by Stefan Bodewig <bo...@bost.de>.
Hi Erik,
I think something like this task could be very useful indeed. Having
only a quick glance on the actual code I found a simple issue, your
addText methods need to return void or they will never be called.
Stefan