Browse Source

Allow <ant> and <antcall> to pass references to the subbuilds.

Submitted by:	Matthieu Bentot <mbentot@arantech.com>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270105 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 23 years ago
parent
commit
05b5cb8f3d
7 changed files with 311 additions and 13 deletions
  1. +4
    -0
      WHATSNEW
  2. +94
    -4
      docs/manual/CoreTasks/ant.html
  3. +14
    -0
      src/etc/testcases/taskdefs/ant.xml
  4. +10
    -0
      src/etc/testcases/taskdefs/ant/references.xml
  5. +88
    -8
      src/main/org/apache/tools/ant/taskdefs/Ant.java
  6. +8
    -0
      src/main/org/apache/tools/ant/taskdefs/CallTarget.java
  7. +93
    -1
      src/testcases/org/apache/tools/ant/taskdefs/AntTest.java

+ 4
- 0
WHATSNEW View File

@@ -117,6 +117,10 @@ Other changes:
* <apply> 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 <ant> and
<antcall> unless a reference of the same name already exists in the
subbuild or inheritall has been set to false.

Changes from Ant 1.4 to Ant 1.4.1
===========================================



+ 94
- 4
docs/manual/CoreTasks/ant.html View File

@@ -24,6 +24,16 @@ are set in the new project (See also the <a href="property.html">property task</
<p>You can also set properties in the new project from the old project by
using nested property tags. These properties are always passed regardless of the
setting of <i>inheritAll</i>. This allows you to parameterize your subprojects.</p>

<p>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
<i>inheritall</i> attribute to <code>false</code> 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.</p>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -60,15 +70,41 @@ setting of <i>inheritAll</i>. This allows you to parameterize your subprojects.
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">inheritAll</td>
<td valign="top">If <code>true</code>, pass all properties to the new Ant
project. Defaults to <code>true</code>.
<td valign="top">inheritAll</td> <td valign="top">If
<code>true</code>, pass all properties and references to the new
Ant project. Defaults to <code>true</code>.
</td>
<td align="center" valign="top">No</td>
</tr>
</table>

<h4>Basedir of the new project</h4>
<h3>Parameters specified as nested elements</h3>
<h4>property</h4>
<p>See the description of the <a href="property.html">property task</a>.</p>

<h4>reference</h4>
<p>Used to chose references that shall be copied into the new project,
optionally changing their id.</p>

<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">refid</td>
<td valign="top">The id of the reference in the calling project.</td>
<td valign="top" align="center">Yes</td>
</tr>
<tr>
<td valign="top">toid</td>
<td valign="top">The id of the reference in the new project.</td>
<td valign="top" align="center">No, defaults to the value of refid.</td>
</tr>
</table>

<h3>Basedir of the new project</h3>

<p>The basedir value of the new project is affected by the two
attributes dir and inheritall, see the following table for
@@ -119,6 +155,60 @@ details:</p>
&lt;property name=&quot;output.type&quot; value=&quot;html&quot;/&gt;
&lt;/ant&gt;
</pre>

<p>The build file of the calling project defines some
<code>&lt;path&gt;</code> elements like this:</p>

<pre>
&lt;path id="path1"&gt;
...
&lt;/&gt;
&lt;path id="path2"&gt;
...
&lt;/&gt;
</pre>

<p>and the called build file (<code>subbuild.xml</code>) also defines
a <code>&lt;path&gt;</code> with the id <code>path1</code>, but
<code>path2</code> is not defined:</p>

<pre>
&lt;ant antfile=&quot;subbuild.xml&quot; /&gt;
</pre>

<p>will not override <code>subbuild</code>'s definition of
<code>path1</code>, but make the parent's definition of
<code>path2</code> available in the subbuild. As does:</p>

<pre>
&lt;ant antfile=&quot;subbuild.xml&quot; inheritall=&quot;true&quot; /&gt;
</pre>

<pre>
&lt;ant antfile=&quot;subbuild.xml&quot; inheritall=&quot;false&quot; /&gt;
</pre>

<p>will neither override <code>path1</code> nor copy
<code>path2</code>.</p>

<pre>
&lt;ant antfile=&quot;subbuild.xml&quot; inheritall=&quot;false&quot; &gt;
&lt;reference refid=&quot;path1&quot; /&gt;
&lt;/ant&gt;
</pre>

<p>will override <code>subbuild</code>'s definition of
<code>path1</code>.</p>

<pre>
&lt;ant antfile=&quot;subbuild.xml&quot; inheritall=&quot;false&quot; &gt;
&lt;reference refid=&quot;path1&quot; torefid=&quot;path2&quot; /&gt;
&lt;/ant&gt;
</pre>

<p>will copy the parent's definition of <code>path1</code> into the
new project using the id <code>path2</code>.</p>

<hr>
<p align="center">Copyright &copy; 2000,2001 Apache Software Foundation. All rights
Reserved.</p>


+ 14
- 0
src/etc/testcases/taskdefs/ant.xml View File

@@ -53,4 +53,18 @@
<ant antfile="ant/ant.xml" target="callback" inheritAll="false" />
</target>

<target name="testInherit">
<ant antfile="ant/references.xml" inheritAll="true" target="dummy" />
</target>

<target name="testNoInherit">
<ant antfile="ant/references.xml" inheritAll="false" target="dummy" />
</target>

<target name="testRename">
<ant antfile="ant/references.xml" inheritAll="false" target="dummy">
<reference refid="path" torefid="newpath" />
</ant>
</target>

</project>

+ 10
- 0
src/etc/testcases/taskdefs/ant/references.xml View File

@@ -0,0 +1,10 @@
<project name="test" default="def" basedir=".">

<path id="no-override" />

<target name="def">
<fail>This build file should only be run from within the testcase</fail>
</target>

<target name="dummy" />
</project>

+ 88
- 8
src/main/org/apache/tools/ant/taskdefs/Ant.java View File

@@ -108,6 +108,9 @@ public class Ant extends Task {
/** the properties to pass to the new project */
private Vector properties = new Vector();
/** the references to pass to the new project */
private Vector references = new Vector();

/** the temporary project created to run the build file */
private Project newProject;

@@ -256,14 +259,8 @@ public class Ant extends Task {
dir = project.getBaseDir();
}

// Override with local-defined properties
Enumeration e = properties.elements();
while (e.hasMoreElements()) {
Property p=(Property) e.nextElement();
p.setProject(newProject);
p.execute();
}
overrideProperties();

if (antFile == null) {
antFile = "build.xml";
}
@@ -278,6 +275,8 @@ public class Ant extends Task {
target = newProject.getDefaultTarget();
}

addReferences();

// Are we trying to call the target in which we are defined?
if (newProject.getBaseDir().equals(project.getBaseDir()) &&
newProject.getProperty("ant.file").equals(project.getProperty("ant.file")) &&
@@ -294,6 +293,65 @@ public class Ant extends Task {
}
}

/**
* Override the properties in the new project with the one
* explicitly defined as nested elements here.
*/
private void overrideProperties() throws BuildException {
Enumeration e = properties.elements();
while (e.hasMoreElements()) {
Property p = (Property) e.nextElement();
p.setProject(newProject);
p.execute();
}
}

/**
* Add the references explicitly defined as nested elements to the
* new project. Also copy over all references that don't override
* existing references in the new project if inheritall has been
* requested.
*/
private void addReferences() throws BuildException {
Hashtable thisReferences = (Hashtable) project.getReferences().clone();
Hashtable newReferences = newProject.getReferences();
Enumeration e;
if (references.size() > 0) {
for(e = references.elements(); e.hasMoreElements();) {
Reference ref = (Reference)e.nextElement();
String refid = ref.getRefId();
if (refid == null) {
throw new BuildException("the refid attribute is required for reference elements");
}
if (!thisReferences.containsKey(refid)) {
log("Parent project doesn't contain any reference '"
+ refid + "'",
Project.MSG_WARN);
continue;
}

Object o = thisReferences.remove(refid);
String toRefid = ref.getToRefid();
if (toRefid == null) {
toRefid = refid;
}
newProject.addReference(toRefid, o);
}
}

// Now add all references that are not defined in the
// subproject, if inheritAll is true
if (inheritAll) {
for(e = thisReferences.keys(); e.hasMoreElements();) {
String key = (String)e.nextElement();
if (newReferences.containsKey(key)) {
continue;
}
newProject.addReference(key, thisReferences.get(key));
}
}
}

/**
* ...
*/
@@ -336,4 +394,26 @@ public class Ant extends Task {
properties.addElement( p );
return p;
}

/**
* create a reference element that identifies a data type that
* should be carried over to the new project.
*/
public void addReference(Reference r) {
references.addElement(r);
}

/**
* Helper class that implements the nested &lt;reference&gt;
* element of &lt;ant&gt; and &lt;antcall&gt;.
*/
public static class Reference
extends org.apache.tools.ant.types.Reference {

public Reference() {super();}
private String targetid=null;
public void setToRefid(String targetid) { this.targetid=targetid; }
public String getToRefid() { return targetid; }
}
}

+ 8
- 0
src/main/org/apache/tools/ant/taskdefs/CallTarget.java View File

@@ -125,6 +125,14 @@ public class CallTarget extends Task {
return callee.createProperty();
}

/**
* create a reference element that identifies a data type that
* should be carried over to the new project.
*/
public void addReference(Ant.Reference r) {
callee.addReference(r);
}

public void setTarget(String target) {
subTarget = target;
}


+ 93
- 1
src/testcases/org/apache/tools/ant/taskdefs/AntTest.java View File

@@ -59,9 +59,10 @@ import java.io.File;
import junit.framework.AssertionFailedError;

import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildFileTest;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.types.Path;

import org.apache.tools.ant.BuildFileTest;
/**
* @author Nico Seessle <nico@seessle.de>
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
@@ -156,6 +157,59 @@ public class AntTest extends BuildFileTest {
}
}

public void testReferenceInheritance() {
Path p = new Path(project);
project.addReference("path", p);
project.addReference("no-override", p);
testReference("testInherit", new String[] {"path", "path"},
new boolean[] {true, true}, p);
testReference("testInherit",
new String[] {"no-override", "no-override"},
new boolean[] {true, false}, p);
testReference("testInherit",
new String[] {"no-override", "no-override"},
new boolean[] {false, false}, null);
}

public void testReferenceNoInheritance() {
Path p = new Path(project);
project.addReference("path", p);
project.addReference("no-override", p);
testReference("testNoInherit", new String[] {"path", "path"},
new boolean[] {true, false}, p);
testReference("testNoInherit", new String[] {"path", "path"},
new boolean[] {false, true}, null);
testReference("testInherit",
new String[] {"no-override", "no-override"},
new boolean[] {true, false}, p);
testReference("testInherit",
new String[] {"no-override", "no-override"},
new boolean[] {false, false}, null);
}

public void testReferenceRename() {
Path p = new Path(project);
project.addReference("path", p);
testReference("testRename", new String[] {"path", "path"},
new boolean[] {true, false}, p);
testReference("testRename", new String[] {"path", "path"},
new boolean[] {false, true}, null);
testReference("testRename", new String[] {"newpath", "newpath"},
new boolean[] {false, true}, p);
}

protected void testReference(String target, String[] keys,
boolean[] expect, Object value) {
ReferenceChecker rc = new ReferenceChecker(keys, expect, value);
project.addBuildListener(rc);
executeTarget(target);
AssertionFailedError ae = rc.getError();
if (ae != null) {
throw ae;
}
project.removeBuildListener(rc);
}

private class BasedirChecker implements BuildListener {
private String[] expectedBasedirs;
private int calls = 0;
@@ -189,4 +243,42 @@ public class AntTest extends BuildFileTest {

}

private class ReferenceChecker implements BuildListener {
private String[] keys;
private boolean[] expectSame;
private Object value;
private int calls = 0;
private AssertionFailedError error;

ReferenceChecker(String[] keys, boolean[] expectSame, Object value) {
this.keys = keys;
this.expectSame = expectSame;
this.value = value;
}

public void buildStarted(BuildEvent event) {}
public void buildFinished(BuildEvent event) {}
public void targetFinished(BuildEvent event){}
public void taskStarted(BuildEvent event) {}
public void taskFinished(BuildEvent event) {}
public void messageLogged(BuildEvent event) {}

public void targetStarted(BuildEvent event) {
if (error == null) {
try {
assertEquals("Call "+calls+" refid=\'"+keys[calls]+"\'",
expectSame[calls],
event.getProject().getReferences().get(keys[calls++]) == value);
} catch (AssertionFailedError e) {
error = e;
}
}
}

AssertionFailedError getError() {
return error;
}

}

}

Loading…
Cancel
Save