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