git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@938315 13f79535-47bb-0310-9956-ffa450edef68master
@@ -38,6 +38,7 @@ Brant Langer Gurganus | |||||
Brian Curnow | Brian Curnow | ||||
Brian Deitte | Brian Deitte | ||||
Brian Felder | Brian Felder | ||||
Brian Repko | |||||
Bruce Atherton | Bruce Atherton | ||||
Cedomir Igaly | Cedomir Igaly | ||||
Charles Hudak | Charles Hudak | ||||
@@ -177,6 +177,10 @@ | |||||
<first>Brian</first> | <first>Brian</first> | ||||
<last>Felder</last> | <last>Felder</last> | ||||
</name> | </name> | ||||
<name> | |||||
<first>Brian</first> | |||||
<last>Repko</last> | |||||
</name> | |||||
<name> | <name> | ||||
<first>Bruce</first> | <first>Bruce</first> | ||||
<last>Atherton</last> | <last>Atherton</last> | ||||
@@ -431,6 +431,11 @@ | |||||
Ant runs into an infinite loop/throws an OutOfMemoryError | Ant runs into an infinite loop/throws an OutOfMemoryError | ||||
when I compile my project under Mac OS X. | when I compile my project under Mac OS X. | ||||
</a></li> | |||||
<li><a href="#extension-point-and-import"> | |||||
<code>extension-point</code> doesn't work | |||||
with <code>import</code> like the documentation | |||||
states. | |||||
</a></li> | </a></li> | ||||
</ul> | </ul> | ||||
@@ -2184,6 +2189,49 @@ mv /tmp/foo $ANT_HOME/bin/antRun | |||||
there is another symlink <code>bundle</code> that points to | there is another symlink <code>bundle</code> that points to | ||||
the <code>Home</code> directory and will cause infite | the <code>Home</code> directory and will cause infite | ||||
recursions as well.</p> | recursions as well.</p> | ||||
<p class="faq"> | |||||
<a name="extension-point-and-import"></a> | |||||
<code>extension-point</code> doesn't work | |||||
with <code>import</code> like the documentation | |||||
states. | |||||
</p> | |||||
<p>Yes, there is | |||||
a <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=48804">bug | |||||
in Ant 1.8.0</a>.</p> | |||||
<p>When using two build files like</p> | |||||
<pre class="code"> | |||||
importing.xml: | |||||
<project> | |||||
... | |||||
<import file="imported.xml"/> | |||||
<target name="bar" extensionOf="foo"/> | |||||
</project> | |||||
imported.xml: | |||||
<project> | |||||
<extension-point name="foo"/> | |||||
</project> | |||||
</pre> | |||||
<p>Ant 1.8.0 will fail, claiming there was no extension point | |||||
named "foo".</p> | |||||
<p>This bug has been fixed for Ant 1.8.1. For Ant 1.8.0 there | |||||
is | |||||
a <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=48804#c9">work-around</a>: | |||||
add an additional layer of importing like in</p> | |||||
<pre class="code"> | |||||
importing.xml: | |||||
<project> | |||||
<target name="bar" extensionOf="foo"/> | |||||
</project> | |||||
imported.xml: | |||||
<project> | |||||
<extension-point name="foo"/> | |||||
</project> | |||||
build.xml: | |||||
<project> | |||||
<import file="imported.xml"/> | |||||
<import file="importing.xml"/> | |||||
</project> | |||||
</pre> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -19,6 +19,8 @@ package org.apache.tools.ant; | |||||
import java.io.File; | import java.io.File; | ||||
import java.util.Hashtable; | import java.util.Hashtable; | ||||
import java.util.LinkedList; | |||||
import java.util.List; | |||||
import java.util.Locale; | import java.util.Locale; | ||||
import java.util.Vector; | import java.util.Vector; | ||||
@@ -89,6 +91,7 @@ public class ProjectHelper { | |||||
// that read build files using ProjectHelper ). | // that read build files using ProjectHelper ). | ||||
private Vector importStack = new Vector(); | private Vector importStack = new Vector(); | ||||
private List extensionStack = new LinkedList(); | |||||
/** | /** | ||||
* Import stack. | * Import stack. | ||||
@@ -101,6 +104,18 @@ public class ProjectHelper { | |||||
return importStack; | return importStack; | ||||
} | } | ||||
/** | |||||
* Extension stack. | |||||
* Used to keep track of targets that extend extension points. | |||||
* | |||||
* @return a list of two element string arrays where the first | |||||
* element is the name of the extensionpoint and the second the | |||||
* name of the target | |||||
*/ | |||||
public List getExtensionStack() { | |||||
return extensionStack; | |||||
} | |||||
private final static ThreadLocal targetPrefix = new ThreadLocal() { | private final static ThreadLocal targetPrefix = new ThreadLocal() { | ||||
protected Object initialValue() { | protected Object initialValue() { | ||||
return (String) null; | return (String) null; | ||||
@@ -177,6 +177,28 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
parse(project, source, new RootHandler(context, mainHandler)); | parse(project, source, new RootHandler(context, mainHandler)); | ||||
// Execute the top-level target | // Execute the top-level target | ||||
context.getImplicitTarget().execute(); | context.getImplicitTarget().execute(); | ||||
// resolve extensionOf attributes | |||||
for (Iterator i = getExtensionStack().iterator(); i.hasNext(); ) { | |||||
String[] extensionInfo = (String[]) i.next(); | |||||
String tgName = extensionInfo[0]; | |||||
String name = extensionInfo[1]; | |||||
Hashtable projectTargets = project.getTargets(); | |||||
if (!projectTargets.containsKey(tgName)) { | |||||
throw new BuildException("can't add target " | |||||
+ name + " to extension-point " | |||||
+ tgName | |||||
+ " because the extension-point" | |||||
+ " is unknown."); | |||||
} | |||||
Target t = (Target) projectTargets.get(tgName); | |||||
if (!(t instanceof ExtensionPoint)) { | |||||
throw new BuildException("referenced target " | |||||
+ tgName | |||||
+ " is not an extension-point"); | |||||
} | |||||
t.addDependency(name); | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -987,6 +1009,9 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
project.addOrReplaceTarget(newName, newTarget); | project.addOrReplaceTarget(newName, newTarget); | ||||
} | } | ||||
if (extensionPoint != null) { | if (extensionPoint != null) { | ||||
ProjectHelper helper = | |||||
(ProjectHelper) context.getProject(). | |||||
getReference(ProjectHelper.PROJECTHELPER_REFERENCE); | |||||
for (Iterator iter = | for (Iterator iter = | ||||
Target.parseDepends(extensionPoint, name, "extensionOf") | Target.parseDepends(extensionPoint, name, "extensionOf") | ||||
.iterator(); | .iterator(); | ||||
@@ -995,20 +1020,12 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
if (isInIncludeMode()) { | if (isInIncludeMode()) { | ||||
tgName = prefix + sep + tgName; | tgName = prefix + sep + tgName; | ||||
} | } | ||||
if (!projectTargets.containsKey(tgName)) { | |||||
throw new BuildException("can't add target " | |||||
+ name + " to extension-point " | |||||
+ tgName | |||||
+ " because the extension-point" | |||||
+ " is unknown."); | |||||
} | |||||
Target t = (Target) projectTargets.get(tgName); | |||||
if (!(t instanceof ExtensionPoint)) { | |||||
throw new BuildException("referenced target " | |||||
+ tgName | |||||
+ " is not an extension-point"); | |||||
} | |||||
t.addDependency(name); | |||||
// defer extensionpoint resolution until the full | |||||
// import stack has been processed | |||||
helper.getExtensionStack().add(new String[] { | |||||
tgName, name | |||||
}); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -57,30 +57,35 @@ | |||||
<au:assertLogContains text="In target bar"/> | <au:assertLogContains text="In target bar"/> | ||||
</target> | </target> | ||||
<target name="testExtensionPointMustBeKnown"> | |||||
<target name="testCantAddToPlainTarget"> | |||||
<mkdir dir="${output}"/> | <mkdir dir="${output}"/> | ||||
<echo file="${output}/build.xml"><![CDATA[ | <echo file="${output}/build.xml"><![CDATA[ | ||||
<project default="foo"> | <project default="foo"> | ||||
<extension-point name="bar" extensionOf="foo"/> | |||||
<extension-point name="foo"/> | |||||
<target name="foo"/> | |||||
<target name="bar" extensionOf="foo"/> | |||||
</project>]]></echo> | </project>]]></echo> | ||||
<au:expectfailure | <au:expectfailure | ||||
expectedMessage="can't add target bar to extension-point foo because the extension-point is unknown"> | |||||
expectedMessage="referenced target foo is not an extension-point"> | |||||
<ant dir="${output}"/> | <ant dir="${output}"/> | ||||
</au:expectfailure> | </au:expectfailure> | ||||
</target> | </target> | ||||
<target name="testCantAddToPlainTarget"> | |||||
<target name="testExtensionPointInImportedBuildfile" description="Bug 48804"> | |||||
<mkdir dir="${output}"/> | <mkdir dir="${output}"/> | ||||
<echo file="${output}/master.xml"><![CDATA[ | |||||
<project default="bar"> | |||||
<extension-point name="foo"/> | |||||
<target name="bar" depends="foo"/> | |||||
</project>]]></echo> | |||||
<echo file="${output}/build.xml"><![CDATA[ | <echo file="${output}/build.xml"><![CDATA[ | ||||
<project default="foo"> | |||||
<target name="foo"/> | |||||
<target name="bar" extensionOf="foo"/> | |||||
<project> | |||||
<import file="master.xml"/> | |||||
<target name="prepare" extensionOf="foo"> | |||||
<echo>in target prepare</echo> | |||||
</target> | |||||
</project>]]></echo> | </project>]]></echo> | ||||
<au:expectfailure | |||||
expectedMessage="referenced target foo is not an extension-point"> | |||||
<ant dir="${output}"/> | |||||
</au:expectfailure> | |||||
<ant dir="${output}" target="bar"/> | |||||
<au:assertLogContains text="in target prepare"/> | |||||
</target> | </target> | ||||
</project> | </project> |
@@ -1912,6 +1912,54 @@ mv /tmp/foo $ANT_HOME/bin/antRun | |||||
recursions as well.</p> | recursions as well.</p> | ||||
</answer> | </answer> | ||||
</faq> | </faq> | ||||
<faq id="extension-point-and-import"> | |||||
<question><code>extension-point</code> doesn't work | |||||
with <code>import</code> like the documentation | |||||
states.</question> | |||||
<answer> | |||||
<p>Yes, there is | |||||
a <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=48804">bug | |||||
in Ant 1.8.0</a>.</p> | |||||
<p>When using two build files like</p> | |||||
<source><![CDATA[ | |||||
importing.xml: | |||||
<project> | |||||
... | |||||
<import file="imported.xml"/> | |||||
<target name="bar" extensionOf="foo"/> | |||||
</project> | |||||
imported.xml: | |||||
<project> | |||||
<extension-point name="foo"/> | |||||
</project> | |||||
]]></source> | |||||
<p>Ant 1.8.0 will fail, claiming there was no extension point | |||||
named "foo".</p> | |||||
<p>This bug has been fixed for Ant 1.8.1. For Ant 1.8.0 there | |||||
is | |||||
a <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=48804#c9">work-around</a>: | |||||
add an additional layer of importing like in</p> | |||||
<source><![CDATA[ | |||||
importing.xml: | |||||
<project> | |||||
<target name="bar" extensionOf="foo"/> | |||||
</project> | |||||
imported.xml: | |||||
<project> | |||||
<extension-point name="foo"/> | |||||
</project> | |||||
build.xml: | |||||
<project> | |||||
<import file="imported.xml"/> | |||||
<import file="importing.xml"/> | |||||
</project> | |||||
]]></source> | |||||
</answer> | |||||
</faq> | |||||
</faqsection> | </faqsection> | ||||
</document> | </document> |