@@ -24,7 +24,9 @@ import java.io.Reader;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import org.apache.tools.ant.BuildException;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.tools.ant.types.Parameter;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.resources.FileResource;
@@ -52,13 +54,19 @@ public final class ReplaceTokens
extends BaseParamFilterReader
implements ChainableReader {
/** Default "begin token" character. */
private static final char DEFAULT_BEGIN_TOKEN = '@' ;
private static final String DEFAULT_BEGIN_TOKEN = "@" ;
/** Default "end token" character. */
private static final char DEFAULT_END_TOKEN = '@';
private static final String DEFAULT_END_TOKEN = "@";
/** Hashtable to holds the original replacee-replacer pairs (String to String). */
private Hashtable<String, String> hash = new Hashtable<String, String>();
/** Data to be used before reading from stream again */
private String queuedData = null;
/** This map holds the "resolved" tokens (begin- and end-tokens are added to make searching simpler) */
private final TreeMap<String, String> resolvedTokens = new TreeMap<String, String>();
private boolean resolvedTokensBuilt = false;
/** Used for comparisons and lookup into the resolvedTokens map. */
private String readBuffer = "";
/** replacement test from a token */
private String replaceData = null;
@@ -66,26 +74,18 @@ public final class ReplaceTokens
/** Index into replacement data */
private int replaceIndex = -1;
/** Index into queue data */
private int queueIndex = -1;
/** Hashtable to hold the replacee-replacer pairs (String to String). */
private Hashtable<String, String> hash = new Hashtable<String, String>();
/** Character marking the beginning of a token. */
private char beginToken = DEFAULT_BEGIN_TOKEN;
private String beginToken = DEFAULT_BEGIN_TOKEN;
/** Character marking the end of a token. */
private char endToken = DEFAULT_END_TOKEN;
private String endToken = DEFAULT_END_TOKEN;
/**
* Constructor for "dummy" instances.
*
* @see BaseFilterReader#BaseFilterReader()
*/
public ReplaceTokens() {
super();
}
public ReplaceTokens() {}
/**
* Creates a new filtered reader.
@@ -97,18 +97,6 @@ public final class ReplaceTokens
super(in);
}
private int getNextChar() throws IOException {
if (queueIndex != -1) {
final int ch = queuedData.charAt(queueIndex++);
if (queueIndex >= queuedData.length()) {
queueIndex = -1;
}
return ch;
}
return in.read();
}
/**
* Returns the next character in the filtered stream, replacing tokens
* from the original stream.
@@ -125,63 +113,66 @@ public final class ReplaceTokens
setInitialized(true);
}
if (replaceIndex != -1 ) {
final int ch = replaceData.charAt(replaceIndex++);
if (replaceIndex >= replaceData.length ()) {
replaceIndex = -1 ;
if (!resolvedTokensBuilt ) {
// build the resolved tokens tree map.
for (String key : hash.keySet ()) {
resolvedTokens.put(beginToken + key + endToken, hash.get(key)) ;
}
return ch ;
resolvedTokensBuilt = true ;
}
int ch = getNextChar();
if (ch == beginToken) {
final StringBuffer key = new StringBuffer("");
do {
ch = getNextChar();
if (ch != -1) {
key.append((char) ch);
} else {
break;
}
} while (ch != endToken);
if (ch == -1) {
if (queuedData == null || queueIndex == -1) {
queuedData = key.toString();
} else {
queuedData
= key.toString() + queuedData.substring(queueIndex);
}
if (queuedData.length() > 0) {
queueIndex = 0;
} else {
queueIndex = -1;
}
return beginToken;
// are we currently serving replace data?
if (replaceData != null) {
if (replaceIndex < replaceData.length()) {
return replaceData.charAt(replaceIndex++);
} else {
key.setLength(key.length() - 1);
replaceData = null;
}
}
final String replaceWith = (String) hash.get(key.toString());
if (replaceWith != null) {
if (replaceWith.length() > 0) {
replaceData = replaceWith;
replaceIndex = 0;
}
return read();
// is the read buffer empty?
if (readBuffer.length() == 0) {
int next = in.read();
if (next == -1) {
return next; // end of stream. all buffers empty.
}
readBuffer += (char)next;
}
for (;;) {
// get the closest tokens
SortedMap<String,String> possibleTokens = resolvedTokens.tailMap(readBuffer);
if (possibleTokens.isEmpty() || !possibleTokens.firstKey().startsWith(readBuffer)) { // if there is none, then deliver the first char from the buffer.
return getFirstCharacterFromReadBuffer();
} else if (readBuffer.equals(possibleTokens.firstKey())) { // there exists a nearest token - is it an exact match?
// we have found a token. prepare the replaceData buffer.
replaceData = resolvedTokens.get(readBuffer);
replaceIndex = 0;
readBuffer = ""; // destroy the readBuffer - it's contents are being replaced entirely.
// get the first character via recursive call.
return read();
} else { // nearest token is not matching exactly - read one character more.
int next = in.read();
if (next != -1) {
readBuffer += (char)next;
} else {
String newData = key.toString() + endToken;
if (queuedData == null || queueIndex == -1) {
queuedData = newData;
} else {
queuedData = newData + queuedData.substring(queueIndex);
}
queueIndex = 0;
return beginToken;
return getFirstCharacterFromReadBuffer(); // end of stream. deliver remaining characters from buffer.
}
}
}
return ch;
}
/**
* @return the first character from the read buffer or -1 if read buffer is empty.
*/
private int getFirstCharacterFromReadBuffer() {
if (readBuffer.length() > 0) {
int chr = readBuffer.charAt(0);
readBuffer = readBuffer.substring(1);
return chr;
} else {
return -1;
}
}
/**
@@ -189,7 +180,7 @@ public final class ReplaceTokens
*
* @param beginToken the character used to denote the beginning of a token
*/
public void setBeginToken(final char beginToken) {
public void setBeginToken(final String beginToken) {
this.beginToken = beginToken;
}
@@ -198,7 +189,7 @@ public final class ReplaceTokens
*
* @return the character used to denote the beginning of a token
*/
private char getBeginToken() {
private String getBeginToken() {
return beginToken;
}
@@ -207,7 +198,7 @@ public final class ReplaceTokens
*
* @param endToken the character used to denote the end of a token
*/
public void setEndToken(final char endToken) {
public void setEndToken(final String endToken) {
this.endToken = endToken;
}
@@ -216,7 +207,7 @@ public final class ReplaceTokens
*
* @return the character used to denote the end of a token
*/
private char getEndToken() {
private String getEndToken() {
return endToken;
}
@@ -238,18 +229,19 @@ public final class ReplaceTokens
*/
public void addConfiguredToken(final Token token) {
hash.put(token.getKey(), token.getValue());
resolvedTokensBuilt = false; // invalidate to build them again if they have been built already.
}
/**
* Returns properties from a specified properties file.
*
* @param fileName The fil e to load properties from.
* @param resource The resourc e to load properties from.
*/
private Properties getProperties(Resource r) {
private Properties getProperties(Resource resource ) {
InputStream in = null;
Properties props = new Properties();
try {
in = r.getInputStream();
in = resource .getInputStream();
props.load(in);
} catch (IOException ioe) {
ioe.printStackTrace();
@@ -305,32 +297,23 @@ public final class ReplaceTokens
private void initialize() {
Parameter[] params = getParameters();
if (params != null) {
for (int i = 0; i < params.length; i++ ) {
if (params[i] != null) {
final String type = params[i] .getType();
for (Parameter param : params ) {
if (param != null) {
final String type = param.getType();
if ("tokenchar".equals(type)) {
final String name = params[i].getName();
String value = params[i].getValue();
final String name = param.getName();
if ("begintoken".equals(name)) {
if (value.length() == 0) {
throw new BuildException("Begin token cannot "
+ "be empty");
}
beginToken = params[i].getValue().charAt(0);
beginToken = param.getValue();
} else if ("endtoken".equals(name)) {
if (value.length() == 0) {
throw new BuildException("End token cannot "
+ "be empty");
}
endToken = params[i].getValue().charAt(0);
endToken = param.getValue();
}
} else if ("token".equals(type)) {
final String name = params[i] .getName();
final String value = params[i] .getValue();
final String name = param.getName();
final String value = param.getValue();
hash.put(name, value);
} else if ("propertiesfile".equals(type)) {
makeTokensFromProperties(
new FileResource(new File(params[i] .getValue())));
new FileResource(new File(param.getValue())));
}
}
}