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"); | ||||