You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by Martin van den Bemt <ml...@mvdb.net> on 2002/05/20 18:30:45 UTC
[PATCH[ Allowing FilterSet to have nested tokens.
Hi everyone,
I made a patch, so FilterSet allows nested tokens. A short example.
If you currently have these token/value pairs =
@root@=/usr/local
@test-path@=@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
@root@=@path@
@path@=@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
Re: [PATCH[ Allowing FilterSet to have nested tokens.
Posted by Martin van den Bemt <ma...@mvdb.net>.
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 =
> @root@=/usr/local
> @test-path@=@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
> @root@=@path@
> @path@=@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 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.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:martin@mvdb.net">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:gholam@xtra.co.nz"> Michael McCallum </A>
> + * @author <A href="mailto:martin@mvdb.net"> 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: <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>