diff --git a/WHATSNEW b/WHATSNEW index 6f80387dd..34738058d 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -118,9 +118,9 @@ Other changes: * has a new attribute relative that allows users to pass the filenames as relative instead of absolute paths on the command line. -* References will now be copied into the child build by and - unless a reference of the same name already exists in the - subbuild or inheritall has been set to false. +* References can now be copied into the child build by and + using nested elements or the new inheritRefs + attribute. * no supports builds to fail based on conditions via if and unless attributes. diff --git a/docs/manual/CoreTasks/ant.html b/docs/manual/CoreTasks/ant.html index 7a9ed2685..78d007914 100644 --- a/docs/manual/CoreTasks/ant.html +++ b/docs/manual/CoreTasks/ant.html @@ -25,14 +25,16 @@ are set in the new project (See also the property taskinheritAll. This allows you to parameterize your subprojects.

-

References to data types will also be passed to the new project by -default, but they will not override references defined in the new -project. You can limit the references you want to copy by setting the -inheritall attribute to false and using nested -reference elements. The nested elements can also be used to copy -references from the calling project to the new project under a -different id. References taken from nested elements will override -existing references in the new project.

+

References to data types can also be passed to the new project, but +by default they are not. If you set the inheritrefs attribute to +true, all references will be copied, but they will not override +references defined in the new project.

+ +

Nested <reference> elements +can also be used to copy references from the calling project to the +new project, optionally under a different id. References taken from +nested elements will override existing references in the new +project.

Parameters

@@ -70,10 +72,15 @@ existing references in the new project.

- + + + + + + +
No
inheritAll If - true, pass all properties and references to the new - Ant project. Defaults to true. - inheritAllIf true, pass all properties to the + new Ant project. Defaults to true.No
inheritRefsIf true, pass all references to the + new Ant project. Defaults to false. No
@@ -82,7 +89,7 @@ existing references in the new project.

property

See the description of the property task.

-

reference

+

reference

Used to chose references that shall be copied into the new project, optionally changing their id.

@@ -173,26 +180,28 @@ a <path> with the id path1, but path2 is not defined:

-  <ant antfile="subbuild.xml" />
+  <ant antfile="subbuild.xml" inheritrefs="true" />
 

will not override subbuild's definition of path1, but make the parent's definition of -path2 available in the subbuild. As does:

+path2 available in the subbuild.

-  <ant antfile="subbuild.xml" inheritall="true" />
+  <ant antfile="subbuild.xml" />
 
+

as well as

+
-  <ant antfile="subbuild.xml" inheritall="false" />
+  <ant antfile="subbuild.xml" inheritrefs="false" />
 

will neither override path1 nor copy path2.

-  <ant antfile="subbuild.xml" inheritall="false" >
+  <ant antfile="subbuild.xml" inheritrefs="false" >
     <reference refid="path1" />
   </ant>
 
@@ -201,7 +210,7 @@ a <path> with the id path1, but path1.

-  <ant antfile="subbuild.xml" inheritall="false" >
+  <ant antfile="subbuild.xml" inheritrefs="false" >
     <reference refid="path1" torefid="path2" />
   </ant>
 
diff --git a/docs/manual/CoreTasks/antcall.html b/docs/manual/CoreTasks/antcall.html index f08072996..43efd4c08 100644 --- a/docs/manual/CoreTasks/antcall.html +++ b/docs/manual/CoreTasks/antcall.html @@ -21,6 +21,13 @@ are set in the new project (See also the property taskYou can also set properties in the new project from the old project by using nested param tags. These properties are always passed regardless of the setting of inheritAll. This allows you to parameterize your subprojects.

+ +

Nested <reference> elements can +be used to copy references from the calling project to the new +project, optionally under a different id. References taken from +nested elements will override existing references in the new +project.

+

When a target is invoked by antcall, all of its dependent targets will also be called within the context of any new parameters. For example. if @@ -53,6 +60,29 @@ will be fixed and not overridable in the init task -or indeed in the "doSom

param

Specifies the properties to set before running the specified target. See property for usage guidelines.

+ +

reference

+

Used to chose references that shall be copied into the new project, +optionally changing their id.

+ + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
refidThe id of the reference in the calling project.Yes
toidThe id of the reference in the new project.No, defaults to the value of refid.
+

Examples

   <target name="default">
@@ -66,6 +96,16 @@ href="property.html">property for usage guidelines.

</target>

Will run the target 'doSomethingElse' and echo 'param1=value'.

+ +
+  <antcall ... >
+    <reference refid="path1" torefid="path2" />
+  </antcall>
+
+ +

will copy the parent's definition of path1 into the +new project using the id path2.

+

Copyright © 2000,2001 Apache Software Foundation. All rights Reserved.

diff --git a/src/etc/testcases/taskdefs/ant.xml b/src/etc/testcases/taskdefs/ant.xml index 19e86f618..3a0262d88 100644 --- a/src/etc/testcases/taskdefs/ant.xml +++ b/src/etc/testcases/taskdefs/ant.xml @@ -54,15 +54,15 @@ - + - + - + diff --git a/src/main/org/apache/tools/ant/taskdefs/Ant.java b/src/main/org/apache/tools/ant/taskdefs/Ant.java index bf28b09ec..574762c5a 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Ant.java +++ b/src/main/org/apache/tools/ant/taskdefs/Ant.java @@ -56,6 +56,7 @@ package org.apache.tools.ant.taskdefs; import org.apache.tools.ant.Task; import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectComponent; import org.apache.tools.ant.BuildListener; import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.BuildException; @@ -65,6 +66,7 @@ import java.io.File; import java.io.PrintStream; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.reflect.Method; import java.util.Vector; import java.util.Hashtable; import java.util.Enumeration; @@ -105,6 +107,9 @@ public class Ant extends Task { /** should we inherit properties from the parent ? */ private boolean inheritAll = true; + /** should we inherit references from the parent ? */ + private boolean inheritRefs = false; + /** the properties to pass to the new project */ private Vector properties = new Vector(); @@ -123,6 +128,15 @@ public class Ant extends Task { inheritAll = value; } + /** + * If true, inherit all references from parent Project + * If false, inherit only those defined + * inside the ant call itself + */ + public void setInheritRefs(boolean value) { + inheritRefs = value; + } + public void init() { newProject = new Project(); newProject.setJavaVersionProperty(); @@ -335,21 +349,64 @@ public class Ant extends Task { if (toRefid == null) { toRefid = refid; } - newProject.addReference(toRefid, o); + copyReference(refid, toRefid); } } // Now add all references that are not defined in the - // subproject, if inheritAll is true - if (inheritAll) { + // subproject, if inheritRefs is true + if (inheritRefs) { for(e = thisReferences.keys(); e.hasMoreElements();) { String key = (String)e.nextElement(); if (newReferences.containsKey(key)) { continue; } - newProject.addReference(key, thisReferences.get(key)); + copyReference(key, key); + } + } + } + + /** + * Try to clone and reconfigure the object referenced by oldkey in + * the parent project and add it to the new project with the key + * newkey. + * + *

If we cannot clone it, copy the referenced object itself and + * keep our fingers crossed.

+ */ + private void copyReference(String oldKey, String newKey) { + Object orig = project.getReference(oldKey); + Class c = orig.getClass(); + Object copy = orig; + try { + Method cloneM = c.getMethod("clone", new Class[0]); + if (cloneM != null) { + copy = cloneM.invoke(orig, new Object[0]); + } + } catch (Exception e) { + // not Clonable + } + + + if (copy instanceof ProjectComponent) { + ((ProjectComponent) copy).setProject(newProject); + } else { + try { + Method setProjectM = + c.getMethod( "setProject", new Class[] {Project.class}); + if(setProjectM != null) { + setProjectM.invoke(copy, new Object[] {newProject}); + } + } catch (NoSuchMethodException e) { + // ignore this if the class being referenced does not have + // a set project method. + } catch(Exception e2) { + String msg = "Error setting new project instance for reference with id " + + oldKey; + throw new BuildException(msg, e2, location); } } + newProject.addReference(newKey, copy); } /** diff --git a/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java b/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java index 08db39e92..13b42df7e 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java @@ -158,7 +158,8 @@ public class AntTest extends BuildFileTest { } public void testReferenceInheritance() { - Path p = new Path(project); + Path p = Path.systemClasspath; + p.setProject(project); project.addReference("path", p); project.addReference("no-override", p); testReference("testInherit", new String[] {"path", "path"}, @@ -172,7 +173,8 @@ public class AntTest extends BuildFileTest { } public void testReferenceNoInheritance() { - Path p = new Path(project); + Path p = Path.systemClasspath; + p.setProject(project); project.addReference("path", p); project.addReference("no-override", p); testReference("testNoInherit", new String[] {"path", "path"}, @@ -188,7 +190,8 @@ public class AntTest extends BuildFileTest { } public void testReferenceRename() { - Path p = new Path(project); + Path p = Path.systemClasspath; + p.setProject(project); project.addReference("path", p); testReference("testRename", new String[] {"path", "path"}, new boolean[] {true, false}, p); @@ -266,9 +269,37 @@ public class AntTest extends BuildFileTest { public void targetStarted(BuildEvent event) { if (error == null) { try { - assertEquals("Call "+calls+" refid=\'"+keys[calls]+"\'", - expectSame[calls], - event.getProject().getReferences().get(keys[calls++]) == value); + String msg = + "Call " + calls + " refid=\'" + keys[calls] + "\'"; + if (value == null) { + Object o = event.getProject().getReference(keys[calls]); + if (expectSame[calls++]) { + assertNull(msg, o); + } else { + assertNotNull(msg, o); + } + } else { + // a rather convoluted equals() test + Path expect = (Path) value; + Path received = (Path) event.getProject().getReference(keys[calls]); + boolean shouldBeEqual = expectSame[calls++]; + if (received == null) { + assertTrue(msg, !shouldBeEqual); + } else { + String[] l1 = expect.list(); + String[] l2 = received.list(); + if (l1.length == l2.length) { + for (int i=0; i