Allows deferred execution to work - for example ant script in macro def. Bugzilla report : 23029 from Yannick Menager git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275209 13f79535-47bb-0310-9956-ffa450edef68master
@@ -0,0 +1,10 @@ | |||
<?xml version="1.0"?> | |||
<antlib xmlns:c="ant:current"> | |||
<typedef name="echo2" classname="org.apache.tools.ant.taskdefs.Echo"/> | |||
<c:echo2>Echo2 called</c:echo2> | |||
<macrodef name="useecho2"> | |||
<sequential> | |||
<c:echo2>Echo2 inside a macro</c:echo2> | |||
</sequential> | |||
</macrodef> | |||
</antlib> |
@@ -14,4 +14,8 @@ | |||
<mytask/> | |||
</target> | |||
<target name="ns.current"> | |||
<typedef file="antlib.current-test.xml" uri="abc"/> | |||
<x:useecho2 xmlns:x="abc"/> | |||
</target> | |||
</project> |
@@ -111,8 +111,8 @@ public class ComponentHelper { | |||
* processing antlib | |||
*/ | |||
private Stack antLibStack = new Stack(); | |||
/** current antlib context */ | |||
private AntTypeTable antLibCurrentTypeTable = null; | |||
/** current antlib uri */ | |||
private String antLibCurrentUri = null; | |||
/** | |||
* Map from task names to vectors of created tasks | |||
@@ -268,14 +268,7 @@ public class ComponentHelper { | |||
public AntTypeDefinition getDefinition(String componentName) { | |||
checkNamespace(componentName); | |||
AntTypeDefinition ret = null; | |||
if (antLibCurrentTypeTable != null | |||
&& ProjectHelper.ANT_CURRENT_URI.equals( | |||
ProjectHelper.extractUriFromComponentName(componentName))) { | |||
ret = antLibCurrentTypeTable.getDefinition(componentName); | |||
} | |||
if (ret == null) { | |||
ret = antTypeTable.getDefinition(componentName); | |||
} | |||
ret = antTypeTable.getDefinition(componentName); | |||
return ret; | |||
} | |||
@@ -690,22 +683,23 @@ public class ComponentHelper { | |||
project.log(" +Datatype " + name + " " + def.getClassName(), | |||
Project.MSG_DEBUG); | |||
antTypeTable.put(name, def); | |||
if (antLibCurrentTypeTable != null && name.lastIndexOf(':') != -1) { | |||
String baseName = name.substring(name.lastIndexOf(':') + 1); | |||
antLibCurrentTypeTable.put( | |||
ProjectHelper.genComponentName( | |||
ProjectHelper.ANT_CURRENT_URI, baseName), def); | |||
} | |||
} | |||
} | |||
/** | |||
* Called at the start of processing an antlib | |||
* @param uri the uri that is associated with this antlib | |||
*/ | |||
public void enterAntLib(String uri) { | |||
antLibCurrentUri = uri; | |||
antLibStack.push(uri); | |||
} | |||
/** | |||
* @return the current antlib uri | |||
*/ | |||
public void enterAntLib() { | |||
antLibCurrentTypeTable = new AntTypeTable(project); | |||
antLibStack.push(antLibCurrentTypeTable); | |||
public String getCurrentAntlibUri() { | |||
return antLibCurrentUri; | |||
} | |||
/** | |||
@@ -714,9 +708,9 @@ public class ComponentHelper { | |||
public void exitAntLib() { | |||
antLibStack.pop(); | |||
if (antLibStack.size() != 0) { | |||
antLibCurrentTypeTable = (AntTypeTable) antLibStack.peek(); | |||
antLibCurrentUri = (String) antLibStack.peek(); | |||
} else { | |||
antLibCurrentTypeTable = null; | |||
antLibCurrentUri = null; | |||
} | |||
} | |||
@@ -125,12 +125,20 @@ public class UnknownElement extends Task { | |||
return namespace; | |||
} | |||
/** Set the namespace of the XML element associated with this component. | |||
/** | |||
* Set the namespace of the XML element associated with this component. | |||
* This method is typically called by the XML processor. | |||
* If the namespace is "ant:current", the component helper | |||
* is used to get the current antlib uri. | |||
* | |||
* @param namespace URI used in the xmlns declaration. | |||
*/ | |||
public void setNamespace(String namespace) { | |||
if (namespace.equals(ProjectHelper.ANT_CURRENT_URI)) { | |||
ComponentHelper helper = ComponentHelper.getComponentHelper( | |||
getProject()); | |||
namespace = helper.getCurrentAntlibUri(); | |||
} | |||
this.namespace = namespace; | |||
} | |||
@@ -926,8 +926,8 @@ public class ProjectHelper2 extends ProjectHelper { | |||
/* UnknownElement is used for tasks and data types - with | |||
delayed eval */ | |||
UnknownElement task = new UnknownElement(tag); | |||
task.setNamespace(uri); | |||
task.setProject(context.getProject()); | |||
task.setNamespace(uri); | |||
//XXX task.setTaskType(qname); | |||
task.setQName(qname); | |||
task.setTaskName(qname); | |||
@@ -90,9 +90,11 @@ public class Antlib extends Task implements TaskContainer { | |||
* | |||
* @param project the current project | |||
* @param antlibUrl the url to read the definitions from | |||
* @param uri the uri that the antlib is to be placed in | |||
* @return the ant lib task | |||
*/ | |||
public static Antlib createAntlib(Project project, URL antlibUrl) { | |||
public static Antlib createAntlib(Project project, URL antlibUrl, | |||
String uri) { | |||
// Check if we can contact the URL | |||
try { | |||
antlibUrl.openConnection().connect(); | |||
@@ -100,22 +102,29 @@ public class Antlib extends Task implements TaskContainer { | |||
throw new BuildException( | |||
"Unable to find " + antlibUrl, ex); | |||
} | |||
// Should be safe to parse | |||
ProjectHelper2 parser = new ProjectHelper2(); | |||
UnknownElement ue = | |||
parser.parseUnknownElement(project, antlibUrl); | |||
// Check name is "antlib" | |||
if (!(ue.getTag().equals(TAG))) { | |||
throw new BuildException( | |||
"Unexpected tag " + ue.getTag() + " expecting " | |||
+ TAG, ue.getLocation()); | |||
ComponentHelper helper = | |||
ComponentHelper.getComponentHelper(project); | |||
helper.enterAntLib(uri); | |||
try { | |||
// Should be safe to parse | |||
ProjectHelper2 parser = new ProjectHelper2(); | |||
UnknownElement ue = | |||
parser.parseUnknownElement(project, antlibUrl); | |||
// Check name is "antlib" | |||
if (!(ue.getTag().equals(TAG))) { | |||
throw new BuildException( | |||
"Unexpected tag " + ue.getTag() + " expecting " | |||
+ TAG, ue.getLocation()); | |||
} | |||
Antlib antlib = new Antlib(); | |||
antlib.setProject(project); | |||
antlib.setLocation(ue.getLocation()); | |||
antlib.init(); | |||
ue.configure(antlib); | |||
return antlib; | |||
} finally { | |||
helper.exitAntLib(); | |||
} | |||
Antlib antlib = new Antlib(); | |||
antlib.setProject(project); | |||
antlib.setLocation(ue.getLocation()); | |||
antlib.init(); | |||
ue.configure(antlib); | |||
return antlib; | |||
} | |||
@@ -166,28 +175,21 @@ public class Antlib extends Task implements TaskContainer { | |||
* any tasks that derive from Definer. | |||
*/ | |||
public void execute() { | |||
ComponentHelper helper = | |||
ComponentHelper.getComponentHelper(getProject()); | |||
helper.enterAntLib(); | |||
try { | |||
for (Iterator i = tasks.iterator(); i.hasNext();) { | |||
UnknownElement ue = (UnknownElement) i.next(); | |||
ue.maybeConfigure(); | |||
setLocation(ue.getLocation()); | |||
Task t = ue.getTask(); | |||
if (t == null) { | |||
continue; | |||
} | |||
if (t instanceof AntlibInterface) { | |||
AntlibInterface d = (AntlibInterface) t; | |||
d.setURI(uri); | |||
d.setAntlibClassLoader(getClassLoader()); | |||
} | |||
t.init(); | |||
t.execute(); | |||
for (Iterator i = tasks.iterator(); i.hasNext();) { | |||
UnknownElement ue = (UnknownElement) i.next(); | |||
ue.maybeConfigure(); | |||
setLocation(ue.getLocation()); | |||
Task t = ue.getTask(); | |||
if (t == null) { | |||
continue; | |||
} | |||
} finally { | |||
helper.exitAntLib(); | |||
if (t instanceof AntlibInterface) { | |||
AntlibInterface d = (AntlibInterface) t; | |||
d.setURI(uri); | |||
d.setAntlibClassLoader(getClassLoader()); | |||
} | |||
t.init(); | |||
t.execute(); | |||
} | |||
} | |||
@@ -315,7 +315,7 @@ public abstract class Definer extends DefBase { | |||
*/ | |||
private void loadAntlib(ClassLoader classLoader, URL url) { | |||
try { | |||
Antlib antlib = Antlib.createAntlib(getProject(), url); | |||
Antlib antlib = Antlib.createAntlib(getProject(), url, getUri()); | |||
antlib.setClassLoader(classLoader); | |||
antlib.setURI(getUri()); | |||
antlib.perform(); | |||
@@ -74,6 +74,10 @@ public class AntlibTest extends BuildFileTest { | |||
expectLog("antlib.file", "MyTask called"); | |||
} | |||
public void testNsCurrent() { | |||
expectLog("ns.current", "Echo2 calledEcho2 inside a macro"); | |||
} | |||
public static class MyTask extends Task { | |||
public void execute() { | |||
log("MyTask called"); | |||