Index: src/main/org/apache/tools/ant/PropertyHelper.java =================================================================== --- src/main/org/apache/tools/ant/PropertyHelper.java (revision 426814) +++ src/main/org/apache/tools/ant/PropertyHelper.java (working copy) @@ -44,7 +44,7 @@ * * @since Ant 1.6 */ -public class PropertyHelper { +public class PropertyHelper implements Cloneable { private Project project; private PropertyHelper next; @@ -76,7 +76,35 @@ //override facility for subclasses to put custom hashtables in + /** + * Clones an instance of this class. + *

This method doesn't clone properties. + * They might be added separately through the project.

+ *

Hooks are all cloned. + * If one fails to clone the entire cloning fails.

+ */ + public Object clone() throws CloneNotSupportedException { + PropertyHelper clone = (PropertyHelper)super.clone(); + // since properties are set separately + // just reset as if newly constructed + clone.properties = new Hashtable(); + clone.userProperties = new Hashtable(); + clone.inheritedProperties = new Hashtable(); + + // clone hooks + PropertyHelper curCloneHookPrec = clone; + PropertyHelper curHook = getNext(); + while (curHook != null) { + PropertyHelper clonedHook = (PropertyHelper)curHook.clone(); + curCloneHookPrec.setNext(clonedHook); + curCloneHookPrec = clonedHook; + + curHook = curHook.getNext(); + } + return clone; + } + // -------------------- Hook management -------------------- /** @@ -135,6 +163,214 @@ return helper; } + /** + * Clones the property helper of a project (and its hooks) and + * installs the clone (with its clone hooks) into a new project. + * + *

Properties of the main property helper are not copied. + * The caller might do it separately. + * The properties of the hooks are copied to their clones + * depending on the inheritAll parameter.

+ * + *

If the new project already has a property helper, + * its hooks are attached to the new one (the clone) and + * its properties are passed to the clone as well.

+ * + *

If the main property helper (or one of its hooks) + * couldn't be cloned, an exception is thrown.

+ * + * @param fromProject The project the helper of which has + * to be cloned. Must not be null. + * @param newProject The project where the clone is installed. + * Must not be null. + * @param inheritAll If true the properties of the + * cloned hooks are copied to their clones. + * @throws CloneNotSupportedException + */ + public static synchronized void clonePropertyHelper( + Project fromProject, Project newProject, boolean inheritAll) + throws CloneNotSupportedException { + if (fromProject == newProject) { + return; + } + PropertyHelper srcHelper = getPropertyHelper(fromProject); + + PropertyHelper newHelper = (PropertyHelper)srcHelper.clone(); + + if (inheritAll) { + PropertyHelper srcHook = srcHelper.getNext(); + PropertyHelper newHook = newHelper.getNext(); + while (srcHook != null) { + // copy all the properties + newHook.getInternalInheritedProperties().putAll( + srcHook.getInternalInheritedProperties()); + newHook.getInternalUserProperties().putAll( + srcHook.getInternalUserProperties()); + newHook.getInternalProperties().putAll( + srcHook.getInternalProperties()); + + srcHook = srcHook.getNext(); + newHook = newHook.getNext(); + } + } + installPropertyHelper(newProject, newHelper); + } + + /** + * Installs a property helper into a project. + * + *

If the new project already has a property helper, + * its hooks are attached to the new one + * and its properties are copied to the new helper as well.

+ * + * @param project The project the helper has to + * handle properties for. + * Must not be null. + * @param newHelper The new property helper of the project. + * Must not be null. + */ + public static synchronized void installPropertyHelper( + Project project, PropertyHelper newHelper) { + + PropertyHelper oldHelper = getPropertyHelper(project); + if (oldHelper == newHelper) { + return; + } + if (!oldHelper.areYouOverridableBy(newHelper)) { + project.log( + "The current property handler prevented the installation" + + " of the new one." + , Project.MSG_VERBOSE); + return; + } + + // sets the project of the property helper and its hooks + newHelper.setProject(project); + PropertyHelper curHook = newHelper.getNext(); + while (curHook != null) { + curHook.setProject(project); + curHook = curHook.getNext(); + } + + synchronized (oldHelper) { + // do not want other threads to + // write to the old helper while it is used + // to initialize the new one + project.addReference(MagicNames.REFID_PROPERTY_HELPER + , newHelper); + + // copy all the properties + Hashtable props = oldHelper.getInternalInheritedProperties(); + Enumeration e = props.keys(); + while (e.hasMoreElements()) { + String name = e.nextElement().toString(); + Object value = props.get(name); + if (value == null) { + value = ""; + } + project.setInheritedProperty(name, value.toString()); + } + props = oldHelper.getInternalUserProperties(); + e = props.keys(); + while (e.hasMoreElements()) { + String name = e.nextElement().toString(); + Object value = props.get(name); + if (value == null) { + value = ""; + } + project.setUserProperty(name, value.toString()); + } + props = oldHelper.getInternalProperties(); + e = props.keys(); + while (e.hasMoreElements()) { + String name = e.nextElement().toString(); + Object value = props.get(name); + if (value == null) { + value = ""; + } + project.setNewProperty(name, value.toString()); + } + + // insert old's hooks at the beginning, which + // is lowest priority if hooks follow the rule + // of "asking the next first" + if (oldHelper.getNext() != null) { + // get last in list + PropertyHelper lastHelper = oldHelper.getNext(); + while (lastHelper.getNext() != null) { + lastHelper = lastHelper.getNext(); + } + lastHelper.setNext(newHelper.getNext()); + newHelper.setNext(oldHelper.getNext()); + // reset old helper + oldHelper.setNext(null); + } + } + } + + /** + * Tells whether this property helper can be overridden + * by another property helper. + * + *

The bare PropertyHelper class is always overridable. + * Subclasses may return false if they do + * not want to give up control to a particular property helper.

+ * + *

Ex. a PropertyHelper might not want to be displaced + * by another instance of the same class.

+ * + * @param name The new instance that wants to override + * this instance as the main project's PropertyHelper. + * Must not be null. + * @return

true

iff this property helper is + * overridable. + */ + protected boolean areYouOverridableBy(PropertyHelper newPH) { + return true; + } + + /** + * Installs a property helper hook into the project. + * + *

If the hook is already installed, this method + * has no effect and a message warning is written to the log.

+ * + * @param project The project the hook is installed into. + * Must not be null. + * @param newHook The property helper hook to be installed. + * Must not be null. + */ + public static synchronized void installPropertyHelperHook( + Project project, PropertyHelper newHook) { + + PropertyHelper mainHelper = getPropertyHelper(project); + + PropertyHelper curHelper = mainHelper; + while (curHelper != null) { + if (curHelper == newHook) { + project.log( + "The property helper hook is already installed" + , Project.MSG_WARN); + return; + } + curHelper = curHelper.getNext(); + } + //Check is pointless since there are too many ways + //to screw things up (because of public getNext, setNext) + if (newHook.getNext() != null) { + project.log( + "The property helper hook already is in a chain (next not null)." + , Project.MSG_WARN); + return; + } + + newHook.setProject(project); + + // insert in the chain (lowest priority) + newHook.setNext(mainHelper.getNext()); + mainHelper.setNext(newHook); + } + // -------------------- Methods to override -------------------- /** Index: src/main/org/apache/tools/ant/taskdefs/SubAnt.java =================================================================== --- src/main/org/apache/tools/ant/taskdefs/SubAnt.java (revision 426814) +++ src/main/org/apache/tools/ant/taskdefs/SubAnt.java (working copy) @@ -71,6 +71,7 @@ private boolean verbose = false; private boolean inheritAll = false; private boolean inheritRefs = false; + private boolean inheritPH = false; private boolean failOnError = true; private String output = null; @@ -408,6 +409,16 @@ /** * Corresponds to <ant>'s + * inheritph attribute. + * + * @param b the new value for this boolean flag. + */ + public void setInheritPH(boolean b) { + this.inheritPH = b; + } + + /** + * Corresponds to <ant>'s * nested <property> element. * * @param p the property to pass on explicitly to the sub-build. @@ -570,6 +581,8 @@ antTask.addReference((Ant.Reference) i.nextElement()); } + antTask.setInheritPH(inheritPH); + return antTask; } Index: src/main/org/apache/tools/ant/taskdefs/CallTarget.java =================================================================== --- src/main/org/apache/tools/ant/taskdefs/CallTarget.java (revision 426814) +++ src/main/org/apache/tools/ant/taskdefs/CallTarget.java (working copy) @@ -54,6 +54,8 @@ private boolean inheritAll = true; // must match the default value of Ant#inheritRefs private boolean inheritRefs = false; + // must match the default value of Ant#inheritPH + private boolean inheritPH = false; private boolean targetSet = false; @@ -76,6 +78,15 @@ } /** + * If true, pass a clone of the current property helper and its + * hooks to the new Ant project. Defaults to false. + * @param value if true, pass property helpers to the new Ant project + */ + public void setInheritPH(boolean value) { + inheritPH = value; + } + + /** * Initialize this task by creating new instance of the ant task and * configuring it by calling its own init method. */ @@ -101,6 +112,7 @@ callee.setAntfile(getProject().getProperty("ant.file")); callee.setInheritAll(inheritAll); callee.setInheritRefs(inheritRefs); + callee.setInheritPH(inheritPH); callee.execute(); } Index: src/main/org/apache/tools/ant/taskdefs/Ant.java =================================================================== --- src/main/org/apache/tools/ant/taskdefs/Ant.java (revision 426814) +++ src/main/org/apache/tools/ant/taskdefs/Ant.java (working copy) @@ -1,5 +1,5 @@ /* - * Copyright 2000-2005 The Apache Software Foundation + * Copyright 2000-2006 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +34,7 @@ import org.apache.tools.ant.Project; import org.apache.tools.ant.ProjectComponent; import org.apache.tools.ant.ProjectHelper; +import org.apache.tools.ant.PropertyHelper; import org.apache.tools.ant.Target; import org.apache.tools.ant.Task; import org.apache.tools.ant.MagicNames; @@ -84,6 +85,9 @@ /** should we inherit references from the parent ? */ private boolean inheritRefs = false; + /** should we inherit cloned property helpers from the parent ? */ + private boolean inheritPH = false; + /** the properties to pass to the new project */ private Vector properties = new Vector(); @@ -140,6 +144,28 @@ } /** + * If true, pass a clone of the current property helper and its + * hooks to the new Ant project. Defaults to false. + * @param value if true, pass property helpers to the new Ant project + */ + public void setInheritPH(boolean value) { + inheritPH = value; + } + + /** + * Creates a clone of the main property helper and its hooks + * iff inheritPH is true. + */ + private void clonePropertyHelpers() { + try { + PropertyHelper.clonePropertyHelper( + getProject(), newProject, inheritAll); + } catch (CloneNotSupportedException cnse) { + log("Couln't clone PropertyHelper(s)", Project.MSG_VERBOSE); + } + } + + /** * Creates a Project instance for the project to call. */ public void init() { @@ -286,6 +312,9 @@ if (newProject == null) { reinit(); } + if (inheritPH) { + clonePropertyHelpers(); + } if ((dir == null) && (inheritAll)) { dir = getProject().getBaseDir(); Index: src/etc/testcases/taskdefs/calltarget.xml =================================================================== --- src/etc/testcases/taskdefs/calltarget.xml (revision 426814) +++ src/etc/testcases/taskdefs/calltarget.xml (working copy) @@ -80,4 +80,62 @@ db dc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: src/etc/testcases/taskdefs/subant.xml =================================================================== --- src/etc/testcases/taskdefs/subant.xml (revision 426814) +++ src/etc/testcases/taskdefs/subant.xml (working copy) @@ -43,6 +43,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Index: src/etc/testcases/taskdefs/ant.xml =================================================================== --- src/etc/testcases/taskdefs/ant.xml (revision 426814) +++ src/etc/testcases/taskdefs/ant.xml (working copy) @@ -235,4 +235,115 @@ db dc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: src/etc/testcases/taskdefs/ant/antph.xml =================================================================== --- src/etc/testcases/taskdefs/ant/antph.xml (revision 0) +++ src/etc/testcases/taskdefs/ant/antph.xml (revision 0) @@ -0,0 +1,190 @@ + + + + This build file should only be run from within the testcase + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file Index: src/etc/testcases/core/propertyhelper.xml =================================================================== --- src/etc/testcases/core/propertyhelper.xml (revision 0) +++ src/etc/testcases/core/propertyhelper.xml (revision 0) @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: src/testcases/org/apache/tools/ant/PropertyHelperTest.java =================================================================== --- src/testcases/org/apache/tools/ant/PropertyHelperTest.java (revision 0) +++ src/testcases/org/apache/tools/ant/PropertyHelperTest.java (revision 0) @@ -0,0 +1,297 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.tools.ant; + +import java.util.Hashtable; + +/** + * JUnit 3 testcases for org.apache.tools.ant.PropertyHelper + * + * NOTE: the classes defined here are not only used + * in the propertyhelper.xml test build, but also to test + * ant.xml, calltarget.xml and subant.xml. + * They have to stay in synch. + */ +public class PropertyHelperTest extends BuildFileTest { + + public PropertyHelperTest(String name) {super(name);} + + public void setUp() { + configureProject("src/etc/testcases/core/propertyhelper.xml"); + getProject().executeTarget("setup"); + } + + public void tearDown() { + getProject().executeTarget("cleanup"); + } + + public void testInstall() { + executeTarget("testInstall"); + } + + public void testInstallTwice() { + executeTarget("testInstallTwice"); + } + + public void testInstallOther() { + executeTarget("testInstallOther"); + } + + public void testInstallOtherNot() { + executeTarget("testInstallOtherNot"); + } + + public void testInstallHook() { + executeTarget("testInstallHook"); + } + + public void testInstallTwoHooks() { + executeTarget("testInstallTwoHooks"); + } + + public void testInstallMainAndTwoHooks() { + executeTarget("testInstallMainAndTwoHooks"); + } + + + private static final String ERROR_PROJECT_NOT_SET = + "Project not set"; + + /** + * Installs the main property helper. + */ + public static class UseCustomPH extends Task { + + private String phid = null; + public void setPHId(String phid) { + this.phid = phid; + } + + public void execute() throws BuildException { + Project prj = getProject(); + if (prj == null) { + throw new BuildException( + "PropertyHelperTest$UseCustomPH " + ERROR_PROJECT_NOT_SET); + } + + PropertyHelper helper = null; + if (phid != null) { + if ("A".equals(phid)) { + helper = new CustomPHA(); + } else if ("B".equals(phid)) { + helper = new CustomPHB(); + } + } + + if (helper == null) { + // default + helper = new CustomPHA(); + } + PropertyHelper.installPropertyHelper(this.getProject(), helper); + } + } + + /** + * Attaches a hook to the main property helper. + */ + public static class InstallHookPH extends Task { + + private String hookprefix = null; + public void setHookPrefix(String hookprefix) { + this.hookprefix = hookprefix; + } + + public void execute() throws BuildException { + Project prj = getProject(); + if (prj == null) { + throw new BuildException( + "PropertyHelperTest$InstallHookPH " + ERROR_PROJECT_NOT_SET); + } + + PropertyHelper hookPH1 = new HookPH1(hookprefix); + + PropertyHelper.installPropertyHelperHook(prj, hookPH1); + } + } + + /** + * Custom PropertyHelper PHA. + * Holds state (calledXXX) to test properly cloned. + */ + public static class CustomPHA extends PropertyHelper { + + int calledXXX = 0; + + private Project project; + public void setProject(Project p) { + super.setProject(p); + this.project = p; + } + + /** + * Clone this instance. + * All the fields of this class are reset. + */ + public Object clone() throws CloneNotSupportedException { + CustomPHA clone = (CustomPHA)super.clone(); + return clone; + } + + protected boolean areYouOverridableBy(PropertyHelper newPH) { + if (newPH instanceof CustomPHA) { + return false; + } + return true; + } + + public String replaceProperties(String ns, String value, Hashtable keys) + throws BuildException { + if (project == null) { + throw new BuildException( + "PropertyHelperTest$CustomPHA " + ERROR_PROJECT_NOT_SET); + } + if ("XXX".equals(value)) { + calledXXX++; + return "Your custom PropertyHelper A (" + calledXXX + ")"; + } + return super.replaceProperties(ns, value, keys); + } + } + + /** + * Custom PropertyHelper PHB. + * Holds state (calledYYY) to test properly cloned. + */ + public static class CustomPHB extends PropertyHelper { + + int calledYYY = 0; + + private Project project; + public void setProject(Project p) { + super.setProject(p); + this.project = p; + } + + /** + * Clone this instance. + * All the fields of this class are reset. + */ + public Object clone() throws CloneNotSupportedException { + CustomPHB clone = (CustomPHB)super.clone(); + return clone; + } + + protected boolean areYouOverridableBy(PropertyHelper newPH) { + return false; + } + + public String replaceProperties(String ns, String value, Hashtable keys) + throws BuildException { + if (project == null) { + throw new BuildException( + "PropertyHelperTest$CustomPHB " + ERROR_PROJECT_NOT_SET); + } + if ("YYY".equals(value)) { + calledYYY++; + return "Your custom PropertyHelper B (" + calledYYY + ")"; + } + return super.replaceProperties(ns, value, keys); + } + } + + /** + * Custom PropertyHelper HookPH1. + * Holds state (count) to test properly cloned. + */ + public static class HookPH1 extends PropertyHelper { + + private String prefix = ""; + private int count = 0; + + private Project project; + public void setProject(Project p) { + super.setProject(p); + this.project = p; + } + + public HookPH1(String prefix) { + if (prefix == null) { + prefix = ""; + } + this.prefix = prefix; + } + public Object clone() throws CloneNotSupportedException { + HookPH1 clone = (HookPH1)super.clone(); + return clone; + } + + public boolean setPropertyHook(String ns, String name, + Object value, + boolean inherited, boolean user, + boolean isNew) { + if (project == null) { + throw new BuildException( + "PropertyHelperTest$HookPH1 " + ERROR_PROJECT_NOT_SET); + } + if (getNext() != null) { + boolean subst = getNext().setPropertyHook(ns, name, value, + inherited, user, isNew); + // If next has handled the property + if (subst) { + return true; + } + } + if (!user && !inherited) { + if (name.startsWith(prefix)) { + Hashtable props = getInternalInheritedProperties(); + if (((props.get(name) == null) || !isNew)) { + count++; + String newValue = value.toString() + "_" + + new Integer(count).toString(); + props.put(name,newValue); + } else { + // already defined + } + return true; + } + } + return false; + } + + public Object getPropertyHook(String ns, String name, boolean user) { + if (project == null) { + throw new BuildException( + "PropertyHelperTest$HookPH1 " + ERROR_PROJECT_NOT_SET); + } + if (getNext() != null) { + Object o = getNext().getPropertyHook(ns, name, user); + if (o != null) { + return o; + } + } + if (!user) { + if (name.startsWith(prefix)) { + Hashtable props = getInternalInheritedProperties(); + return props.get(name); + } + } + return null; + } + } + +} Index: src/testcases/org/apache/tools/ant/taskdefs/CallTargetTest.java =================================================================== --- src/testcases/org/apache/tools/ant/taskdefs/CallTargetTest.java (revision 426814) +++ src/testcases/org/apache/tools/ant/taskdefs/CallTargetTest.java (working copy) @@ -65,6 +65,14 @@ expectLog("multiple-targets-2", "dadctb"); } + public void testCallInheritPHTrue() { + project.executeTarget("call-inheritph-t"); + } + + public void testCallInheritPHFalse() { + project.executeTarget("call-inheritph-f"); + } + public void tearDown() { project.executeTarget("cleanup"); } Index: src/testcases/org/apache/tools/ant/taskdefs/AntTest.java =================================================================== --- src/testcases/org/apache/tools/ant/taskdefs/AntTest.java (revision 426814) +++ src/testcases/org/apache/tools/ant/taskdefs/AntTest.java (working copy) @@ -508,4 +508,43 @@ } + /* ---------------------------------------------------------------- */ + /* --------------- PropertyHelper inheritance tests --------------- */ + /* ---------------------------------------------------------------- */ + + public void testInheritPHTrueSingle() { + executeTarget("inheritph-true-single"); + } + + public void testInheritPHFalseSingle() { + executeTarget("inheritph-false-single"); + } + + public void testInheritPHTrueSingleHooks() { + executeTarget("inheritph-true-single-hooks"); + } + + public void testInheritPHTrueSingleHooksAll() { + executeTarget("inheritph-true-single-hooks-all"); + } + + public void testInheritPHTrueSingleHooksAllOther() { + executeTarget("inheritph-true-single-hooks-all-other"); + } + + public void testInheritPHTrueSingleHooksAllOtherParam() { + executeTarget("inheritph-true-single-hooks-all-other-param"); + } + + public void testInheritPHTrueMulti() { + executeTarget("inheritph-true-multi"); + } + + public void testInheritPHFalseMulti() { + executeTarget("inheritph-false-multi"); + } + + public void testInheritPHTrueMultiHooksAllOtherParam() { + executeTarget("inheritph-true-multi-hooks-all-other-param"); + } } Index: src/testcases/org/apache/tools/ant/taskdefs/SubAntTest.java =================================================================== --- src/testcases/org/apache/tools/ant/taskdefs/SubAntTest.java (revision 426814) +++ src/testcases/org/apache/tools/ant/taskdefs/SubAntTest.java (working copy) @@ -139,5 +139,14 @@ } + /* --------------- PropertyHelper inheritance tests --------------- */ + public void testInheritPHTrueSingle() { + executeTarget("inheritph-true-single"); + } + + public void testInheritPHFalseSingle() { + executeTarget("inheritph-false-single"); + } + } \ No newline at end of file Index: docs/manual/CoreTasks/antcall.html =================================================================== --- docs/manual/CoreTasks/antcall.html (revision 426814) +++ docs/manual/CoreTasks/antcall.html (working copy) @@ -45,6 +45,11 @@ will be fixed and not overridable in the init task--or indeed in the "doSomethingElse" task.

+

A property handler (or helper) is a hidden object that evaluates and stores +properties. The Ant API allows custom tasks to install custom property handlers. +If you want custom property handlers to be passed to a child project you have to +set the inheritPH attribute to true.

+

If the build file changes after you've started the build, the behavior of this task is undefined.

@@ -73,6 +78,13 @@ new Ant project. Defaults to false. No + + inheritPH + If true, pass a copy of the current + property handler and its hooks to the new Ant project. + Defaults to false. + No +

Note on inheritRefs

Index: docs/manual/CoreTasks/ant.html =================================================================== --- docs/manual/CoreTasks/ant.html (revision 426814) +++ docs/manual/CoreTasks/ant.html (working copy) @@ -48,6 +48,11 @@ defined outside of targets in the new project - but not those defined inside of targets.

+

A property handler (or helper) is a hidden object that evaluates and stores +properties. The Ant API allows custom tasks to install custom property handlers. +If you want custom property handlers to be passed to a child project you have to +set the inheritPH attribute to true.

+

Parameters

@@ -97,6 +102,13 @@ new Ant project. Defaults to false. + + + + +
No
inheritPHIf true, pass a copy of the current + property handler and its hooks to the new Ant project. + Defaults to false.No

Parameters specified as nested elements

Index: docs/manual/CoreTasks/subant.html =================================================================== --- docs/manual/CoreTasks/subant.html (revision 426814) +++ docs/manual/CoreTasks/subant.html (working copy) @@ -212,6 +212,18 @@ + inheritph + + + Corresponds to <ant>'s inheritph attribute. + + + boolean + + + + + output