diff --git a/proposal/sandbox/dotnet/src/etc/testcases/msbuild.xml b/proposal/sandbox/dotnet/src/etc/testcases/msbuild.xml
index 08f92c753..914d17ab0 100644
--- a/proposal/sandbox/dotnet/src/etc/testcases/msbuild.xml
+++ b/proposal/sandbox/dotnet/src/etc/testcases/msbuild.xml
@@ -27,4 +27,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/proposal/sandbox/dotnet/src/etc/testcases/nant.xml b/proposal/sandbox/dotnet/src/etc/testcases/nant.xml
index a0f4c775b..f659994f2 100644
--- a/proposal/sandbox/dotnet/src/etc/testcases/nant.xml
+++ b/proposal/sandbox/dotnet/src/etc/testcases/nant.xml
@@ -27,4 +27,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/AbstractBuildTask.java b/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/AbstractBuildTask.java
index a3fa5d91a..d6ac81008 100644
--- a/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/AbstractBuildTask.java
+++ b/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/AbstractBuildTask.java
@@ -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.
+ *
+ *
Must throw a BuildException if the snippet can not be turned
+ * into a build file.
+ */
+ 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;
}
}
diff --git a/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTask.java b/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTask.java
index f830ec2d1..c87fd1c5e 100644
--- a/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTask.java
+++ b/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTask.java
@@ -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.
+ *
+ * If we have exactly one child, return that.
+ * Otherwise if we have only children, wrap them into a
+ * which in turn gets wrapped into a .
+ * Otherwise, fail.
+ */
+ 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;
+ }
+ }
}
diff --git a/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTask.java b/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTask.java
index bd228e9fa..95ae7c93a 100644
--- a/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTask.java
+++ b/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTask.java
@@ -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.
+ *
+ * If we have exactly one child, return that.
+ * Otherwise assume that this is a valid build file snippet that
+ * just needs an empty project wrapped around it.
+ */
+ 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;
+ }
+ }
}
diff --git a/proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTaskTest.java b/proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTaskTest.java
index 65bc3cb35..efe7797cc 100644
--- a/proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTaskTest.java
+++ b/proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTaskTest.java
@@ -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");
+ }
+ }
}
diff --git a/proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTaskTest.java b/proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTaskTest.java
index 95d505234..e2f8cd442 100644
--- a/proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTaskTest.java
+++ b/proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTaskTest.java
@@ -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");
+ }
+ }
}