ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Wascally Wabbit <wascallywab...@earthling.net>
Subject Re: recursive expansion of property names
Date Thu, 24 Jun 2004 21:15:26 GMT
Jack,

Your PropertyHelper needs to delegate to the replaced helper to handle
"get"/"set" operations that occured *BEFORE* you were installed!
*That* object has things like "ant.file" and "basedir" stored in its
various maps. For example, using my own class, I've got methods like:

     private Object getProperty0(String ns, String name)
     {
         if (name==null) {
             return null;
         }
         Object o = m_allProperties.get(name);   /// <---- MINE
         if (o==null) {
             o = m_defImpl.getProperty(ns,name); /// <--- THE THING I REPLACED
         }
         return o;
     }

This method is called by my inherited public getProperty() like so:

     public synchronized Object getProperty(String ns, String name)
     {
         Object o = getPropertyHook(ns,name,false);  /// <---- YOU SHOULD 
DO THIS TOO!
         return o==null ? getProperty0(ns,name) : o;
     }

------
The Wabbit


---- [[[ BIG SNIP ]]] -----------

At 03:33 PM 6/24/2004, you wrote:
>will that patch work on Ant's 1.6.1 source code it is it specific to 
>1.7?  I tried implementing Wascally Wabbit's suggestion from the other day 
>and just took the replacePropertiesRecursively from the patch you 
>submitted.  I don't really *understand* how the property helper chaining 
>stuff works but I THINK that either I'm not getting put in the chain or 
>the replacePropertiesRecursively method is not working on regular 
>properties.  ${basedir} does not even get resolved -- though I suspect 
>that something I'm doing is wrong as that should get resolved BEFORE my 
>PropertyHandler is even installed.
>
>FYI. I have attached my various files and below is how I install the 
>property handler in an Ant script:
>
>
><project name="Magmic BlackBerry Build Script"
>          default="help-mini"
>          xmlns:magmic="antlib:com.magmic"
>          xmlns:contrib="antlib:net.sf.antcontrib"
>          xmlns:antenna="http://antenna.sourceforge.net">
>
>   <!-- Install the recursive property handler -->
>   <magmic:recursiveproperties action="install" />
>
>.....
>
>
>OUTPUT:
>
>BUILD FAILED
>java.lang.NullPointerException
>         at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:355)
>         at 
> org.apache.tools.ant.taskdefs.CallTarget.execute(CallTarget.java:107)
>         at org.apache.tools.ant.Task.perform(Task.java:364)
>         at 
> org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:65)
>         at 
> net.sf.antcontrib.logic.ForEach.executeSequential(ForEach.java:178)
>         at net.sf.antcontrib.logic.ForEach.execute(ForEach.java:254)
>         at 
> org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:269)
>         at org.apache.tools.ant.Task.perform(Task.java:364)
>         at org.apache.tools.ant.Target.execute(Target.java:301)
>         at org.apache.tools.ant.Target.performTasks(Target.java:328)
>         at org.apache.tools.ant.Project.executeTarget(Project.java:1215)
>         at org.apache.tools.ant.Project.executeTargets(Project.java:1063)
>         at org.apache.tools.ant.Main.runBuild(Main.java:632)
>         at org.apache.tools.ant.Main.startAnt(Main.java:183)
>         at org.apache.tools.ant.Main.start(Main.java:147)
>         at org.apache.tools.ant.Main.main(Main.java:230)
>
>Total time: 1 second
>java.lang.NullPointerException
>         at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:355)
>         at 
> org.apache.tools.ant.taskdefs.CallTarget.execute(CallTarget.java:107)
>         at org.apache.tools.ant.Task.perform(Task.java:364)
>         at 
> org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:65)
>         at 
> net.sf.antcontrib.logic.ForEach.executeSequential(ForEach.java:178)
>         at net.sf.antcontrib.logic.ForEach.execute(ForEach.java:254)
>         at 
> org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:269)
>         at org.apache.tools.ant.Task.perform(Task.java:364)
>         at org.apache.tools.ant.Target.execute(Target.java:301)
>         at org.apache.tools.ant.Target.performTasks(Target.java:328)
>         at org.apache.tools.ant.Project.executeTarget(Project.java:1215)
>         at org.apache.tools.ant.Project.executeTargets(Project.java:1063)
>         at org.apache.tools.ant.Main.runBuild(Main.java:632)
>         at org.apache.tools.ant.Main.startAnt(Main.java:183)
>         at org.apache.tools.ant.Main.start(Main.java:147)
>         at org.apache.tools.ant.Main.main(Main.java:230)
>--
>Jeffrey Bacon
>jbacon@magmic.com
>Creative Developer
>http://www.magmic.com
>
>
>Jack J. Woehr wrote:
>>Matt Benson wrote:
>>  > About three weeks ago there was a discussion on the
>>  > dev list about how to allow recursive property
>>  > expansion without breaking everything.  So it's on the
>>  > radar, but it's not necessarily easy to do (right).
>>http://issues.apache.org/bugzilla/show_bug.cgi?id=29347
>>I submitted a patch with this that enables recursive property expansion. 
>>Matt, can
>>you explain aspect of Ant that this would break? I sense there's some 
>>"fu" surrounding
>>tasks being able to chain property management, but in my few hours coding 
>>the patch
>>I didn't find any permanent data structures being neglected by the way I 
>>short-circuited
>>and changed parsing.
>>Please excuse me if I missed prior discussion on this or misunderstood it.
>>- Jax
>>-- Jack J. Woehr      # We have gone from the horse and buggy
>>Senior Consultant  # to the moon rocket in one lifetime, but
>>Purematrix, Inc.   # there has not been a corresponding moral
>>www.purematrix.com # growth in mankind. - Dwight D. Eisenhower
>>
>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
>>For additional commands, e-mail: user-help@ant.apache.org
>
>
><?xml version="1.0"?>
><antlib xmlns:current="ant:current">
>    <typedef name="exists" classname="com.magmic.ant.conditions.Exists" />
>
>    <typedef name="application" 
> classname="com.magmic.ant.datatypes.Application" />
>    <typedef name="cod"         classname="com.magmic.ant.datatypes.COD" />
>    <typedef name="midlet"      classname="com.magmic.ant.datatypes.MIDlet" />
>
>    <taskdef name="alx"      classname="com.magmic.ant.tasks.ALX" />
>    <taskdef name="filesize" classname="com.magmic.ant.tasks.FileSize" />
>    <taskdef name="jad"      classname="com.magmic.ant.tasks.JAD" />
>    <taskdef name="jshrink"  classname="com.magmic.ant.tasks.JShrink" />
>    <taskdef name="rapc"     classname="com.magmic.ant.tasks.RAPC" />
>    <taskdef name="version"  classname="com.magmic.ant.tasks.Version" />
>
>    <taskdef name="recursiveproperties" 
> classname="com.magmic.ant.tasks.RecursivePropertyHelperInstaller" />
>
>    <macrodef name="update-version">
>
>      <attribute name="type" default="minor" />
>      <attribute name="oldPrefix" default="old" />
>      <attribute name="newPrefix" default="" />
>
>      <sequential>
>
>        <!-- Read in the old version number  -->
>              <current:version action="read" file="version.number" 
> prefix="@{oldPrefix}" />
>
>              <!-- Print out the old version number -->
>              <echo level="info">Old version: ${@{oldPrefix}.version}</echo>
>
>              <!-- Update the version number -->
>              <current:version action="update" type="@{type}" 
> file="version.number" prefix="@{newPrefix}" />
>
>              <!-- Print the new version number -->
>              <condition property="new_version_name" value="version">
>                <equals arg1="@{newPrefix}" arg2="" />
>              </condition>
>              <property name="new_version_name" 
> value="@{newPrefix}.version" />
>              <echo level="info">New version: ${new_version_name}</echo>
>
>      </sequential>
>    </macrodef>
></antlib>/*
>  * RecursivePropertyParser.java Created on June 2, 2004, 3:29 PM
>  */
>package com.magmic.ant;
>
>/**
>  * Class of static methods to parse property expressions
>  *
>  * @author jax
>  */
>public class RecursivePropertyParser {
>
>   /** No marker found in a string search */
>   public final static int NO_MARKER = -1;
>   public final static String OPENER = "${";
>   public final static String CLOSER = "}";
>   public final static int OPENER_LENGTH = OPENER.length();
>   public final static int CLOSER_LENGTH = CLOSER.length();
>
>   /** Never creates a new instance of RecursivePropertyParser */
>   protected RecursivePropertyParser() {}
>
>   /**
>    * Find the next expression opener
>    *
>    * @param value The source string
>    * @return The index of the start of the opener, NO_MARKER if not found
>    */
>   public static int nextOpener(final String value, int index) {
>     int result = NO_MARKER;
>     if (value != null && !(index > value.length())) {
>       result = value.indexOf(OPENER, index);
>     }
>     return result;
>   }
>
>   /**
>    * Find the next expression closer
>    *
>    * @param index offsetr in the source string from which to start 
> looking for a
>    *          closer
>    * @param value The source string
>    * @return The index of the closer, NO_MARKER if not found
>    */
>   public static int nextCloser(final String value, int index) {
>     int result = NO_MARKER;
>     if (value != null && !(index > value.length())) {
>       result = value.indexOf(CLOSER, index);
>       // /* debug */ System.out.println("nextCloser: result = " + result);
>     }
>     return result;
>   }
>
>   /**
>    * Finds the balancing expression closer.
>    *
>    * @param index offset in the source string from which to start looking 
> for a
>    *          closer
>    * @param value The source string
>    * @return The index of the closer, NO_MARKER if not found
>    */
>   public static int balancingCloser(final String value, int index) {
>     int result = NO_MARKER;
>     int lastOpener = index;
>     if (value != null) {
>       int unbalancedOpeners = 1;
>       int currentOpener = nextOpener(value, lastOpener + 1);
>       int currentCloser = nextCloser(value, lastOpener);
>       while (unbalancedOpeners > 0) {
>         // /* debug */ System.out.println("balancingCloser():
>         // unbalancedOpeners=" + unbalancedOpeners +"currentOpener=" +
>         // currentOpener + " currentCloser=" + currentCloser);
>         // We can't find a matching closing '}'
>         if (currentCloser == NO_MARKER) {
>           break; // doom
>         }
>         // We found another '${' before finding a '}'
>         if (currentOpener != NO_MARKER && currentOpener < currentCloser) {
>           unbalancedOpeners++;
>           lastOpener = currentOpener;
>           currentOpener = nextOpener(value, lastOpener + 1);
>         }
>         // We found a closer '}' before any new openers '${'
>         else {
>           unbalancedOpeners--;
>           if (unbalancedOpeners == 0) { // We're done if we are balanced
>             result = currentCloser;
>           } else { // We have to go round again trying to find closers to
>                    // balance
>             currentCloser = nextCloser(value, currentCloser + 1);
>           }
>         }
>       }
>     }
>     return result;
>   }
>}/**
>  * $Id: $
>  * Copyright 2004 Magmic Inc.
>  */
>package com.magmic.ant;
>
>import java.util.Hashtable;
>import org.apache.tools.ant.BuildException;
>import org.apache.tools.ant.Project;
>import org.apache.tools.ant.PropertyHelper;
>
>
>/**
>  * @author jbacon
>  * @version $Revision: $
>  */
>public class RecursivePropertyHelper extends PropertyHelper {
>
>   private static final String ANT_HELPER_REFID = "ant.PropertyHelper";
>
>   private PropertyHelper defImpl;
>   private Project project;
>
>   /**
>    * @see 
> org.apache.tools.ant.PropertyHelper#setProject(org.apache.tools.ant.Project)
>    */
>   public void setProject(Project p) {
>     super.setProject(p);
>     this.project = p;
>   }
>
>   /**
>    * @see 
> org.apache.tools.ant.PropertyHelper#replaceProperties(java.lang.String, 
> java.lang.String, java.util.Hashtable)
>    */
>   public String replaceProperties(String ns, String value, Hashtable 
> keys) throws BuildException {
>     return replacePropertiesRecursively(ns, value, keys);
>   }
>
>   /**
>    * Replaces <code>${xxx}</code> style constructions RECURSIVELY in the

> given
>    * value with the string value of the corresponding data types. That 
> is, this
>    * function keeps finding the next leftmost outermost expression and 
> expands
>    * it recursively until no instantiable expressions remain.
>    *
>    *
>    * @param value The string to be scanned for property references.
>    *              May be <code>null</code>, in which case this
>    *              method returns immediately with no effect.
>    * @param keys  Mapping (String to String) of property names to their
>    *              values. If <code>null</code>, only project properties will
>    *              be used.
>    *
>    * @exception BuildException if the string contains an opening
>    *                           <code>${</code> without a closing
>    *                           <code>}</code>
>    * @return the original string with the properties replaced, or
>    *         <code>null</code> if the original string is <code>null</code>.
>    */
>   public String replacePropertiesRecursively(String ns, String value, 
> Hashtable keys) throws BuildException {
>     if (value == null) { return null; }
>     StringBuffer sb = new StringBuffer(value);
>     int nextOpenerIndex = RecursivePropertyParser.nextOpener(value, 0);
>
>     while (nextOpenerIndex != RecursivePropertyParser.NO_MARKER) { // 
> More inner expressions, recurse.
>
>       int balancingCloserIndex = 
> RecursivePropertyParser.balancingCloser(sb.toString(),
> 
>nextOpenerIndex);
>       if (balancingCloserIndex == RecursivePropertyParser.NO_MARKER) {
>         throw new BuildException("Unbalanced property expression: " +
>                                  sb.substring(nextOpenerIndex).toString());
>       }
>
>       final String innerExpression = sb.substring(nextOpenerIndex +
> 
>RecursivePropertyParser.OPENER_LENGTH,
>                                                   balancingCloserIndex);
>
>       final String expansion = replacePropertiesRecursively(ns, 
> innerExpression, keys);
>
>       Object replacement = null;
>
>       // try to get it from the project or keys
>       // Backward compatibility
>       if (keys != null) {
>           replacement = keys.get(expansion);
>       }
>       if (replacement == null) {
>           replacement = getProperty(ns, expansion);
>       }
>       if (replacement == null) {
>           project.log("Property ${" + expansion + "} has not been set", 
> Project.MSG_VERBOSE);
>       }
>       final String fragment = (replacement != null)
>                                 ? replacement.toString()
>                                 : "${" + expansion + "}";
>
>       sb.replace(nextOpenerIndex,
>                  balancingCloserIndex +
>                    RecursivePropertyParser.CLOSER_LENGTH,
>                  fragment);
>       nextOpenerIndex = RecursivePropertyParser.nextOpener(sb.toString(),
> 
>balancingCloserIndex+1);
>     }
>     return sb.toString();
>   }
>
>   /**
>    * Installs this helper as the given project's property helper.
>    *
>    * @param project this net's associated project
>    * @return <i>true</i> if helper installed first time
>    */
>   public boolean install(Project project) {
>       PropertyHelper current = PropertyHelper.getPropertyHelper(project);
>       PropertyHelper temp = current;;
>       do {
>         if (temp == this) {
>            project.log("RecursivePropertyHelper already installed.", 
> Project.MSG_WARN);
>            return true;
>         }
>         temp = temp.getNext();
>       } while (temp != null);
>       project.log("Installing RecursivePropertyHelper...", 
> Project.MSG_VERBOSE);
>
>       defImpl = current;
>       project.addReference(ANT_HELPER_REFID, this);
>
>       return true;
>   }
>
>   /**
>    * Uninstalls this helper as its project's property helper.
>    * Will reinstall the helper that was there when this helper
>    * was installed.
>    *
>    * @throws BuildException if this helper is not currently installed
>    */
>   public void uninstall(Project project) {
>     PropertyHelper current = PropertyHelper.getPropertyHelper(project);
>
>     if (current == this) {
>       project.log("Uninstalling RecursivePropertyHelper...", 
> Project.MSG_VERBOSE);
>
>       project.addReference(ANT_HELPER_REFID, defImpl);
>       defImpl = null;
>
>     } else if (current != null) {
>       project.log("RecursivePropertyHelper not installed.", 
> Project.MSG_WARN);
>     }
>   }
>
>}
>/**
>  * $Id: $
>  * Copyright 2004 Magmic Inc.
>  */
>package com.magmic.ant.tasks;
>
>import org.apache.tools.ant.Task;
>import org.apache.tools.ant.types.EnumeratedAttribute;
>import com.magmic.ant.RecursivePropertyHelper;
>
>
>/**
>  * @author jbacon
>  * @version $Revision: $
>  */
>public class RecursivePropertyHelperInstaller extends Task {
>
>   private static final String UNINSTALL = "uninstall";
>   private static final String INSTALL = "install";
>
>   private RecursivePropertyHelper rph;
>
>   String action;
>   public void setAction(Action a) { action = a.getValue(); }
>
>   public void execute() {
>     if (rph == null) {
>       rph = new RecursivePropertyHelper();
>       rph.setProject(getProject());
>     }
>     if (action.equals(UNINSTALL)) {
>       rph.uninstall(getProject());
>     } else {
>       rph.install(getProject());
>     }
>   }
>
>   public static class Action extends EnumeratedAttribute {
>
>     /**
>      * @see org.apache.tools.ant.types.EnumeratedAttribute#getValues()
>      */
>     public String[] getValues() {
>       return new String[] { UNINSTALL, INSTALL };
>     }
>}
>}



---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
For additional commands, e-mail: user-help@ant.apache.org


Mime
View raw message