ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Martin van den Bemt <mar...@mvdb.net>
Subject Re: [PATCH[ Allowing FilterSet to have nested tokens.
Date Wed, 22 May 2002 20:11:52 GMT
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>&lt;copy&gt;</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:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
> For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>



--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message