git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275705 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -27,4 +27,31 @@ | |||||
| <property name="foo" value="bar"/> | <property name="foo" value="bar"/> | ||||
| </msbuild> | </msbuild> | ||||
| </target> | </target> | ||||
| <target name="nested-file"> | |||||
| <property name="foo" value="bar"/> | |||||
| <msbuild | |||||
| xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet" | |||||
| > | |||||
| <build> | |||||
| <Project DefaultTargets="echo"> | |||||
| <Target Name="echo"> | |||||
| <Task Name="Echo" Message="foo is ${foo}"/> | |||||
| </Target> | |||||
| </Project> | |||||
| </build> | |||||
| </msbuild> | |||||
| </target> | |||||
| <target name="nested-task"> | |||||
| <property name="foo" value="bar"/> | |||||
| <msbuild | |||||
| xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet" | |||||
| > | |||||
| <build> | |||||
| <Task Name="Echo" Message="foo is ${foo}"/> | |||||
| </build> | |||||
| </msbuild> | |||||
| </target> | |||||
| </project> | </project> | ||||
| @@ -27,4 +27,30 @@ | |||||
| <property name="foo" value="bar"/> | <property name="foo" value="bar"/> | ||||
| </nant> | </nant> | ||||
| </target> | </target> | ||||
| <target name="nested-file"> | |||||
| <property name="foo" value="bar"/> | |||||
| <nant | |||||
| xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet" | |||||
| > | |||||
| <build> | |||||
| <project basedir="." default="echo"> | |||||
| <target name="echo"> | |||||
| <echo message="foo is ${foo}"/> | |||||
| </target> | |||||
| </project> | |||||
| </build> | |||||
| </nant> | |||||
| </target> | |||||
| <target name="nested-task"> | |||||
| <property name="foo" value="bar"/> | |||||
| <nant | |||||
| xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet" | |||||
| > | |||||
| <build> | |||||
| <echo message="foo is ${foo}"/> | |||||
| </build> | |||||
| </nant> | |||||
| </target> | |||||
| </project> | </project> | ||||
| @@ -54,9 +54,18 @@ | |||||
| package org.apache.tools.ant.taskdefs.optional.dotnet; | package org.apache.tools.ant.taskdefs.optional.dotnet; | ||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
| import org.apache.tools.ant.util.DOMElementWriter; | |||||
| import org.apache.tools.ant.util.FileUtils; | |||||
| import org.apache.tools.ant.util.XMLFragment; | |||||
| import org.w3c.dom.DocumentFragment; | |||||
| import org.w3c.dom.Element; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.FileOutputStream; | |||||
| import java.io.IOException; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.List; | import java.util.List; | ||||
| @@ -80,6 +89,11 @@ public abstract class AbstractBuildTask extends Task { | |||||
| */ | */ | ||||
| private List properties = new ArrayList(1); | private List properties = new ArrayList(1); | ||||
| /** | |||||
| * Nested build file fragment. | |||||
| */ | |||||
| private XMLFragment buildSnippet; | |||||
| /** | /** | ||||
| * Empty constructor. | * Empty constructor. | ||||
| */ | */ | ||||
| @@ -93,6 +107,18 @@ public abstract class AbstractBuildTask extends Task { | |||||
| buildFile = f; | buildFile = f; | ||||
| } | } | ||||
| /** | |||||
| * Adds a build file fragment. | |||||
| */ | |||||
| public void addBuild(XMLFragment f) { | |||||
| if (buildSnippet == null) { | |||||
| buildSnippet = f; | |||||
| } else { | |||||
| throw new BuildException("You must not specify more than one " | |||||
| + "build element"); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * A target. | * A target. | ||||
| */ | */ | ||||
| @@ -180,10 +206,25 @@ public abstract class AbstractBuildTask extends Task { | |||||
| */ | */ | ||||
| protected abstract String[] getPropertyArguments(List properties); | protected abstract String[] getPropertyArguments(List properties); | ||||
| /** | |||||
| * Turn the DoucmentFragment into a DOM tree suitable as a build | |||||
| * file when serialized. | |||||
| * | |||||
| * <p>Must throw a BuildException if the snippet can not be turned | |||||
| * into a build file.</p> | |||||
| */ | |||||
| protected abstract Element makeTree(DocumentFragment f); | |||||
| /** | /** | ||||
| * Perform the build. | * Perform the build. | ||||
| */ | */ | ||||
| public void execute() { | public void execute() { | ||||
| if (buildFile != null && buildSnippet != null) { | |||||
| throw new BuildException("You must not specify the build file" | |||||
| + " attribute and a nested build at the" | |||||
| + " same time"); | |||||
| } | |||||
| DotNetExecTask exec = new DotNetExecTask(); | DotNetExecTask exec = new DotNetExecTask(); | ||||
| exec.setProject(getProject()); | exec.setProject(getProject()); | ||||
| exec.setExecutable(getExecutable()); | exec.setExecutable(getExecutable()); | ||||
| @@ -196,10 +237,48 @@ public abstract class AbstractBuildTask extends Task { | |||||
| for (int i = 0; i < args.length; i++) { | for (int i = 0; i < args.length; i++) { | ||||
| exec.createArg().setValue(args[i]); | exec.createArg().setValue(args[i]); | ||||
| } | } | ||||
| args = getBuildfileArguments(buildFile); | |||||
| File generatedFile = null; | |||||
| if (buildSnippet != null) { | |||||
| try { | |||||
| generatedFile = getBuildFile(); | |||||
| } catch (IOException e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| args = getBuildfileArguments(generatedFile); | |||||
| } else { | |||||
| args = getBuildfileArguments(buildFile); | |||||
| } | |||||
| for (int i = 0; i < args.length; i++) { | for (int i = 0; i < args.length; i++) { | ||||
| exec.createArg().setValue(args[i]); | exec.createArg().setValue(args[i]); | ||||
| } | } | ||||
| exec.execute(); | |||||
| try { | |||||
| exec.execute(); | |||||
| } finally { | |||||
| if (generatedFile != null) { | |||||
| generatedFile.delete(); | |||||
| } | |||||
| } | |||||
| } | |||||
| private File getBuildFile() throws IOException { | |||||
| File f = null; | |||||
| if (buildSnippet != null) { | |||||
| Element e = makeTree(buildSnippet.getFragment()); | |||||
| f = FileUtils.newFileUtils().createTempFile("build", ".xml", null); | |||||
| f.deleteOnExit(); | |||||
| FileOutputStream out = null; | |||||
| try { | |||||
| out = new FileOutputStream(f); | |||||
| (new DOMElementWriter()).write(e, out); | |||||
| } finally { | |||||
| if (out != null) { | |||||
| out.close(); | |||||
| } | |||||
| } | |||||
| } | |||||
| return f; | |||||
| } | } | ||||
| } | } | ||||
| @@ -59,11 +59,18 @@ import java.util.Iterator; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.List; | import java.util.List; | ||||
| import org.w3c.dom.DocumentFragment; | |||||
| import org.w3c.dom.Element; | |||||
| import org.w3c.dom.Node; | |||||
| import org.w3c.dom.NodeList; | |||||
| /** | /** | ||||
| * Runs a MSBuild build process. | * Runs a MSBuild build process. | ||||
| */ | */ | ||||
| public class MSBuildTask extends AbstractBuildTask { | public class MSBuildTask extends AbstractBuildTask { | ||||
| private static final String TARGET = "generated-by-ant"; | |||||
| public MSBuildTask() { | public MSBuildTask() { | ||||
| super(); | super(); | ||||
| } | } | ||||
| @@ -119,4 +126,32 @@ public class MSBuildTask extends AbstractBuildTask { | |||||
| return new String[0]; | return new String[0]; | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Turn the DocumentFragment into a DOM tree suitable as a build | |||||
| * file when serialized. | |||||
| * | |||||
| * <p>If we have exactly one <Project> child, return that. | |||||
| * Otherwise if we have only <Task> children, wrap them into a | |||||
| * <Target> which in turn gets wrapped into a <Project>. | |||||
| * Otherwise, fail.</p> | |||||
| */ | |||||
| protected Element makeTree(DocumentFragment f) { | |||||
| NodeList nl = f.getChildNodes(); | |||||
| if (nl.getLength() == 1 | |||||
| && nl.item(0).getNodeType() == Node.ELEMENT_NODE | |||||
| && nl.item(0).getNodeName().equals("Project")) { | |||||
| return (Element) nl.item(0); | |||||
| } else { | |||||
| Element p = f.getOwnerDocument().createElement("Project"); | |||||
| p.setAttribute("DefaultTargets", TARGET); | |||||
| Element t = f.getOwnerDocument().createElement("Target"); | |||||
| t.setAttribute("Name", TARGET); | |||||
| p.appendChild(t); | |||||
| t.appendChild(f); | |||||
| return p; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -59,6 +59,11 @@ import java.util.Iterator; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.List; | import java.util.List; | ||||
| import org.w3c.dom.DocumentFragment; | |||||
| import org.w3c.dom.Element; | |||||
| import org.w3c.dom.Node; | |||||
| import org.w3c.dom.NodeList; | |||||
| /** | /** | ||||
| * Runs a NAnt build process. | * Runs a NAnt build process. | ||||
| */ | */ | ||||
| @@ -102,4 +107,25 @@ public class NAntTask extends AbstractBuildTask { | |||||
| } | } | ||||
| return (String[]) al.toArray(new String[al.size()]); | return (String[]) al.toArray(new String[al.size()]); | ||||
| } | } | ||||
| /** | |||||
| * Turn the DocumentFragment into a DOM tree suitable as a build | |||||
| * file when serialized. | |||||
| * | |||||
| * <p>If we have exactly one <project> child, return that. | |||||
| * Otherwise assume that this is a valid build file snippet that | |||||
| * just needs an empty project wrapped around it.</p> | |||||
| */ | |||||
| protected Element makeTree(DocumentFragment f) { | |||||
| NodeList nl = f.getChildNodes(); | |||||
| if (nl.getLength() == 1 | |||||
| && nl.item(0).getNodeType() == Node.ELEMENT_NODE | |||||
| && nl.item(0).getNodeName().equals("project")) { | |||||
| return (Element) nl.item(0); | |||||
| } else { | |||||
| Element e = f.getOwnerDocument().createElement("project"); | |||||
| e.appendChild(f); | |||||
| return e; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -86,4 +86,16 @@ public class MSBuildTaskTest extends BuildFileTest { | |||||
| expectLogContaining("echo", "foo is bar"); | expectLogContaining("echo", "foo is bar"); | ||||
| } | } | ||||
| } | } | ||||
| public void testNestedFile() throws Exception { | |||||
| if (getProject().getProperty("msbuild.found") != null) { | |||||
| expectLogContaining("nested-file", "foo is bar"); | |||||
| } | |||||
| } | |||||
| public void testNestedTask() throws Exception { | |||||
| if (getProject().getProperty("msbuild.found") != null) { | |||||
| expectLogContaining("nested-task", "foo is bar"); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -86,4 +86,16 @@ public class NAntTaskTest extends BuildFileTest { | |||||
| expectLogContaining("echo", "foo is bar"); | expectLogContaining("echo", "foo is bar"); | ||||
| } | } | ||||
| } | } | ||||
| public void testNestedFile() throws Exception { | |||||
| if (getProject().getProperty("nant.found") != null) { | |||||
| expectLogContaining("nested-file", "foo is bar"); | |||||
| } | |||||
| } | |||||
| public void testNestedTask() throws Exception { | |||||
| if (getProject().getProperty("nant.found") != null) { | |||||
| expectLogContaining("nested-task", "foo is bar"); | |||||
| } | |||||
| } | |||||
| } | } | ||||