Can anyone of the committers please comment on this. I would really love to have this in CVS, since I am using it heavily already and I think this functionality should have been in there to begin with.. (at least it was the first thing I tried when using filters, I guess I am not the only one.....)
Mvgr, Martin On Mon, 2002-05-20 at 18:30, Martin van den Bemt wrote: > Hi everyone, > > I made a patch, so FilterSet allows nested tokens. A short example. > If you currently have these token/value pairs = > @[EMAIL PROTECTED]/usr/local > @[EMAIL PROTECTED]@root@/test.txt > > If you call @test-path@ from your file, it will not resolve the @root@ > anymore, which can be very annoying .. > > Since you can also get into an infinite loop, by using the eg the values > @[EMAIL PROTECTED]@path@ > @[EMAIL PROTECTED]@root@ > I made some extra code to handle this, so it will just parse in the > @path@ (if you called that from the file to be filtered) and I will > write a message to System.out with the reason it could parse it (log > doesn't seem to get passed back to console, so I used this). > > There is only one problem : it is not backward compatible, since the old > way is to ignore the nested ifs and just put the value there. Since I > don't know any use cases myself where you want the token to be > unresolved if you put a value there, I will leave the decision to put > this in to the committers ;)) > > Attached is the change in documtation and FilterSet.java (in one diff, > from the root of the jakarta-ant module) and a seperate testcase called > FilterSetRecursiveTest.java. Don't know if the name is correct (nested > could be better), but it is easy to rename ;). > I ran the FilterSetTest separately and it passes.. > > Have fun with it ;) > > Mvgr, > Martin > > > > > > > > > ---- > > /* > * The Apache Software License, Version 1.1 > * > * Copyright (c) 2000-2001 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 "The Jakarta Project", "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 [EMAIL PROTECTED] > * > * 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.types; > > import junit.framework.TestCase; > > /** > * This will test the recursive FilterSet. > * Which means that if the filter value @test@ contains another filter > * value, it will actually resolve. > * It also contains test to see what happens when the resolving occurs > * in an infinite loop. > * > * @author <a href="mailto:[EMAIL PROTECTED]">Martin van den Bemt</a> > */ > public class FilterSetRecursiveTest extends TestCase { > > /** > * Constructor for FilterSetRecursiveTest. > * @param arg0 > */ > public FilterSetRecursiveTest(String arg0) { > super(arg0); > } > > public static void main(String[] args) { > junit.textui.TestRunner.run(FilterSetRecursiveTest.class); > } > > /** > * The actual recursive test > * The endresult should be it works > */ > public void testRecursive() { > System.out.println("testRecursive"); > String result = "it works line"; > String line="@test@ line"; > FilterSet fs = new FilterSet(); > fs.addFilter("test", "@test1@"); > fs.addFilter("test1","@test2@"); > fs.addFilter("test2", "it works"); > fs.setBeginToken("@"); > fs.setEndToken("@"); > assertEquals(result, fs.replaceTokens(line)); > } > > /** > * Tests having a inifinite loop > */ > public void testInfinite() { > System.out.println("testInfinite"); > String result = "@test@ line testvalue"; > String line = "@test@ line @test3@"; > FilterSet fs = new FilterSet(); > fs.addFilter("test", "@test1@"); > fs.addFilter("test1","@test2@"); > fs.addFilter("test2", "@test@"); > fs.addFilter("test3", "testvalue"); > fs.setBeginToken("@"); > fs.setEndToken("@"); > assertEquals(result, fs.replaceTokens(line)); > } > } > ---- > > Index: docs/manual/CoreTypes/filterset.html > =================================================================== > RCS file: /home/cvspublic/jakarta-ant/docs/manual/CoreTypes/filterset.html,v > retrieving revision 1.6 > diff -u -r1.6 filterset.html > --- docs/manual/CoreTypes/filterset.html 25 Mar 2002 20:21:11 -0000 > 1.6 > +++ docs/manual/CoreTypes/filterset.html 20 May 2002 15:18:49 -0000 > @@ -19,6 +19,7 @@ > <code>endtoken</code> attributes to define what to match.</p> > <p>Filtersets are used for doing > replacements in tasks such as <code><copy></code>, etc.</p> > +<p>Nested filters are possible and a message will be given in case a value > in a filter chain is called for a second time and thus causing an infinite > loop. The originating token will be passed back when an infinite loop occurs. > > <H2>Filterset</H2> > > Index: src/main/org/apache/tools/ant/types/FilterSet.java > =================================================================== > RCS file: > /home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/types/FilterSet.java,v > retrieving revision 1.13 > diff -u -r1.13 FilterSet.java > --- src/main/org/apache/tools/ant/types/FilterSet.java 15 Apr 2002 > 14:56:34 -0000 1.13 > +++ src/main/org/apache/tools/ant/types/FilterSet.java 20 May 2002 > 15:20:38 -0000 > @@ -75,6 +75,7 @@ > * A filter set may have begintoken and endtokens defined. > * > * @author <A href="mailto:[EMAIL PROTECTED]"> Michael McCallum </A> > + * @author <A href="mailto:[EMAIL PROTECTED]"> Martin van den Bemt </A> > */ > public class FilterSet extends DataType implements Cloneable { > > @@ -356,6 +357,10 @@ > value = (String) tokens.get(token); > log("Replacing: " + beginToken + token + endToken > + " -> " + value, Project.MSG_VERBOSE); > + if (!value.equals(token)) { > + // we have another token, let's parse it. > + value = replaceTokens(value, token); > + } > b.append(value); > i = index + beginToken.length() + token.length() > + endToken.length(); > @@ -374,6 +379,54 @@ > } else { > return line; > } > + } > + > + /** Contains a list of parsed tokens */ > + private Vector passedTokens; > + /** if a ducplicate token is found, this is set to true */ > + private boolean duplicateToken = false; > + > + /** > + * This parses tokens which point to tokens. > + * It also maintains a list of currently used tokens, so we cannot > + * get into an infinite loop > + * @param value the value / token to parse > + * @param parent the parant token (= the token it was parsed from) > + */ > + private String replaceTokens(String line, String parent) > + throws BuildException > + { > + if (passedTokens == null) { > + passedTokens = new Vector(); > + } > + if (passedTokens.contains(parent) && !duplicateToken) { > + duplicateToken = true; > + StringBuffer sb = new StringBuffer(); > + sb.append("Inifinite loop in tokens. Currently known tokens : "); > + sb.append(passedTokens); > + sb.append("\nProblem token : > "+getBeginToken()+parent+getEndToken()); > + sb.append(" called from > "+getBeginToken()+passedTokens.lastElement()); > + sb.append(getEndToken()); > + System.out.println(sb.toString()); > + return parent; > + } > + passedTokens.addElement(parent); > + String value = this.replaceTokens(line); > + if (value.indexOf(getBeginToken()) == -1 && !duplicateToken) { > + duplicateToken = false; > + passedTokens = null; > + }else if(duplicateToken) { > + // should always be the case... > + if (passedTokens.size() > 0) { > + value = (String) passedTokens.lastElement(); > + passedTokens.removeElementAt(passedTokens.size()-1); > + if (passedTokens.size() == 0) { > + value = getBeginToken()+value+getEndToken(); > + duplicateToken = false; > + } > + } > + } > + return value; > } > > /** > > ---- > > -- > To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> > For additional commands, e-mail: <mailto:[EMAIL PROTECTED]> -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
