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/> | <mytask/> | ||||
</target> | </target> | ||||
<target name="ns.current"> | |||||
<typedef file="antlib.current-test.xml" uri="abc"/> | |||||
<x:useecho2 xmlns:x="abc"/> | |||||
</target> | |||||
</project> | </project> |
@@ -111,8 +111,8 @@ public class ComponentHelper { | |||||
* processing antlib | * processing antlib | ||||
*/ | */ | ||||
private Stack antLibStack = new Stack(); | 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 | * Map from task names to vectors of created tasks | ||||
@@ -268,14 +268,7 @@ public class ComponentHelper { | |||||
public AntTypeDefinition getDefinition(String componentName) { | public AntTypeDefinition getDefinition(String componentName) { | ||||
checkNamespace(componentName); | checkNamespace(componentName); | ||||
AntTypeDefinition ret = null; | 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; | return ret; | ||||
} | } | ||||
@@ -690,22 +683,23 @@ public class ComponentHelper { | |||||
project.log(" +Datatype " + name + " " + def.getClassName(), | project.log(" +Datatype " + name + " " + def.getClassName(), | ||||
Project.MSG_DEBUG); | Project.MSG_DEBUG); | ||||
antTypeTable.put(name, def); | 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 | * 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() { | public void exitAntLib() { | ||||
antLibStack.pop(); | antLibStack.pop(); | ||||
if (antLibStack.size() != 0) { | if (antLibStack.size() != 0) { | ||||
antLibCurrentTypeTable = (AntTypeTable) antLibStack.peek(); | |||||
antLibCurrentUri = (String) antLibStack.peek(); | |||||
} else { | } else { | ||||
antLibCurrentTypeTable = null; | |||||
antLibCurrentUri = null; | |||||
} | } | ||||
} | } | ||||
@@ -125,12 +125,20 @@ public class UnknownElement extends Task { | |||||
return namespace; | 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. | * 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. | * @param namespace URI used in the xmlns declaration. | ||||
*/ | */ | ||||
public void setNamespace(String namespace) { | public void setNamespace(String namespace) { | ||||
if (namespace.equals(ProjectHelper.ANT_CURRENT_URI)) { | |||||
ComponentHelper helper = ComponentHelper.getComponentHelper( | |||||
getProject()); | |||||
namespace = helper.getCurrentAntlibUri(); | |||||
} | |||||
this.namespace = namespace; | this.namespace = namespace; | ||||
} | } | ||||
@@ -926,8 +926,8 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
/* UnknownElement is used for tasks and data types - with | /* UnknownElement is used for tasks and data types - with | ||||
delayed eval */ | delayed eval */ | ||||
UnknownElement task = new UnknownElement(tag); | UnknownElement task = new UnknownElement(tag); | ||||
task.setNamespace(uri); | |||||
task.setProject(context.getProject()); | task.setProject(context.getProject()); | ||||
task.setNamespace(uri); | |||||
//XXX task.setTaskType(qname); | //XXX task.setTaskType(qname); | ||||
task.setQName(qname); | task.setQName(qname); | ||||
task.setTaskName(qname); | task.setTaskName(qname); | ||||
@@ -90,9 +90,11 @@ public class Antlib extends Task implements TaskContainer { | |||||
* | * | ||||
* @param project the current project | * @param project the current project | ||||
* @param antlibUrl the url to read the definitions from | * @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 | * @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 | // Check if we can contact the URL | ||||
try { | try { | ||||
antlibUrl.openConnection().connect(); | antlibUrl.openConnection().connect(); | ||||
@@ -100,22 +102,29 @@ public class Antlib extends Task implements TaskContainer { | |||||
throw new BuildException( | throw new BuildException( | ||||
"Unable to find " + antlibUrl, ex); | "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. | * any tasks that derive from Definer. | ||||
*/ | */ | ||||
public void execute() { | 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) { | private void loadAntlib(ClassLoader classLoader, URL url) { | ||||
try { | try { | ||||
Antlib antlib = Antlib.createAntlib(getProject(), url); | |||||
Antlib antlib = Antlib.createAntlib(getProject(), url, getUri()); | |||||
antlib.setClassLoader(classLoader); | antlib.setClassLoader(classLoader); | ||||
antlib.setURI(getUri()); | antlib.setURI(getUri()); | ||||
antlib.perform(); | antlib.perform(); | ||||
@@ -74,6 +74,10 @@ public class AntlibTest extends BuildFileTest { | |||||
expectLog("antlib.file", "MyTask called"); | expectLog("antlib.file", "MyTask called"); | ||||
} | } | ||||
public void testNsCurrent() { | |||||
expectLog("ns.current", "Echo2 calledEcho2 inside a macro"); | |||||
} | |||||
public static class MyTask extends Task { | public static class MyTask extends Task { | ||||
public void execute() { | public void execute() { | ||||
log("MyTask called"); | log("MyTask called"); | ||||