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"/> | |||
| </msbuild> | |||
| </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> | |||
| @@ -27,4 +27,30 @@ | |||
| <property name="foo" value="bar"/> | |||
| </nant> | |||
| </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> | |||
| @@ -54,9 +54,18 @@ | |||
| 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.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.FileOutputStream; | |||
| import java.io.IOException; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| @@ -80,6 +89,11 @@ public abstract class AbstractBuildTask extends Task { | |||
| */ | |||
| private List properties = new ArrayList(1); | |||
| /** | |||
| * Nested build file fragment. | |||
| */ | |||
| private XMLFragment buildSnippet; | |||
| /** | |||
| * Empty constructor. | |||
| */ | |||
| @@ -93,6 +107,18 @@ public abstract class AbstractBuildTask extends Task { | |||
| 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. | |||
| */ | |||
| @@ -180,10 +206,25 @@ public abstract class AbstractBuildTask extends Task { | |||
| */ | |||
| 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. | |||
| */ | |||
| 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(); | |||
| exec.setProject(getProject()); | |||
| exec.setExecutable(getExecutable()); | |||
| @@ -196,10 +237,48 @@ public abstract class AbstractBuildTask extends Task { | |||
| for (int i = 0; i < args.length; 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++) { | |||
| 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.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. | |||
| */ | |||
| public class MSBuildTask extends AbstractBuildTask { | |||
| private static final String TARGET = "generated-by-ant"; | |||
| public MSBuildTask() { | |||
| super(); | |||
| } | |||
| @@ -119,4 +126,32 @@ public class MSBuildTask extends AbstractBuildTask { | |||
| 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.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. | |||
| */ | |||
| @@ -102,4 +107,25 @@ public class NAntTask extends AbstractBuildTask { | |||
| } | |||
| 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"); | |||
| } | |||
| } | |||
| 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"); | |||
| } | |||
| } | |||
| 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"); | |||
| } | |||
| } | |||
| } | |||