diff --git a/src/main/org/apache/tools/ant/taskdefs/SubAnt.java b/src/main/org/apache/tools/ant/taskdefs/SubAnt.java
new file mode 100644
index 000000000..0e17386b0
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/SubAnt.java
@@ -0,0 +1,388 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "Ant" and "Apache Software Foundation"
+ * must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *
+ * Calls a given target for all defined sub-builds. This is an extension
+ * of ant for bulk project execution.
+ *
+ * @since Ant1.6
+ * @author Dominique Devienne
+ * @ant.task name="subant" category="control"
+ */
+public class SubAnt
+ extends Task {
+
+ private Path buildpath;
+
+ private String target = null;
+ private String antfile = "build.xml";
+ private boolean inheritAll = false;
+ private boolean inheritRefs = false;
+ private boolean failOnError = true;
+
+ private Vector properties = new Vector();
+ private Vector references = new Vector();
+
+ /**
+ * Runs the various sub-builds.
+ */
+ public void execute()
+ throws BuildException {
+ if (buildpath == null) {
+ throw new BuildException("No buildpath specified");
+ }
+
+ final String[] filenames = buildpath.list();
+ final int count = filenames.length;
+ if (count < 1) {
+ log("No sub-builds to iterate on", Project.MSG_WARN);
+ return;
+ }
+/*
+ //REVISIT: there must be cleaner way of doing this, if it is merited at all
+ if (target == null) {
+ target = getOwningTarget().getName();
+ }
+*/
+ for (int i=0; i
+ */
+ // REVISIT: Defaults to the target name that contains this task if not specified.
+ public void setTarget(String target) {
+ this.target = target;
+ }
+
+ /**
+ * Corresponds to
+ * Note that the directories will be added to the build path
+ * in no particular order, so if order is significant, one should
+ * use a file list instead!
+ *
+ * @param set the directory set to add.
+ */
+ public void addDirset(DirSet set) {
+ getBuildpath().addDirset(set);
+ }
+
+ /**
+ * Adds a file set to the implicit build path.
+ *
+ * Note that the directories will be added to the build path
+ * in no particular order, so if order is significant, one should
+ * use a file list instead!
+ *
+ * @param set the file set to add.
+ */
+ public void addFileset(FileSet set) {
+ getBuildpath().addFileset(set);
+ }
+
+ /**
+ * Adds an ordered file list to the implicit build path.
+ *
+ * Note that contrary to file and directory sets, file lists
+ * can reference non-existent files or directories!
+ *
+ * @param list the file list to add.
+ */
+ public void addFilelist(FileList list) {
+ getBuildpath().addFilelist(list);
+ }
+
+ /**
+ * Set the buildpath to be used to find sub-projects.
+ *
+ * @param s an Ant Path object containing the buildpath.
+ */
+ public void setBuildpath(Path s) {
+ getBuildpath().append(s);
+ }
+
+ /**
+ * Creates a nested build path, and add it to the implicit build path.
+ *
+ * @return the newly created nested build path.
+ */
+ public Path createBuildpath() {
+ return getBuildpath().createPath();
+ }
+
+ /**
+ * Creates a nested true
. Otherwise,
+ * a warning log message is simply output.
+ */
+ private void execute(File file)
+ throws BuildException {
+ if (!file.exists() || file.isDirectory() || !file.canRead()) {
+ String msg = "Invalid file: "+file;
+ if (failOnError) {
+ throw new BuildException(msg);
+ }
+ log(msg, Project.MSG_WARN);
+ return;
+ }
+
+ Ant ant = createAntTask();
+ String antfilename = null;
+ try {
+ antfilename = file.getCanonicalPath();
+ } catch (IOException e) {
+ throw new BuildException(e);
+ }
+
+ ant.setAntfile(antfilename);
+ try {
+ ant.execute();
+ } catch (BuildException e) {
+ if (failOnError) {
+ throw e;
+ }
+ log("Failure for target '"+target
+ +"' of: "+antfilename+"\n"
+ +e.getMessage(), Project.MSG_WARN);
+ }
+ }
+
+ /**
+ * Sets the default build file name to append to directory
+ * names found in the build path -default "build.xml"
+ *
+ * @param antfile the short build file name. Defaults to "build.xml".
+ */
+ public void setAntfile(String antfile) {
+ this.antfile = antfile;
+ }
+
+ /**
+ * Sets whether to fail with a build exception on error, or go on.
+ *
+ * @param failOnError the new value for this boolean flag.
+ */
+ public void setFailonerror(boolean failOnError) {
+ this.failOnError = failOnError;
+ }
+
+ /**
+ * The target to call on the different sub-builds. Set to "" to execute
+ * the default target.
+ * <ant>
's
+ * inheritall
attribute.
+ *
+ * @param b the new value for this boolean flag.
+ */
+ public void setInheritall(boolean b) {
+ this.inheritAll = b;
+ }
+
+ /**
+ * Corresponds to <ant>
's
+ * inheritrefs
attribute.
+ *
+ * @param b the new value for this boolean flag.
+ */
+ public void setInheritrefs(boolean b) {
+ this.inheritRefs = b;
+ }
+
+ /**
+ * Corresponds to <ant>
's
+ * nested <property>
element.
+ *
+ * @param p the property to pass on explicitly to the sub-build.
+ */
+ public void addProperty(Property p) {
+ properties.addElement(p);
+ }
+
+ /**
+ * Corresponds to <ant>
's
+ * nested <reference>
element.
+ *
+ * @param r the reference to pass on explicitly to the sub-build.
+ */
+ public void addReference(Ant.Reference r) {
+ references.addElement(r);
+ }
+
+ /**
+ * Adds a directory set to the implicit build path.
+ * <buildpathelement>
,
+ * and add it to the implicit build path.
+ *
+ * @return the newly created nested build path element.
+ */
+ public Path.PathElement createBuildpathElement()
+ throws BuildException {
+ return getBuildpath().createPathElement();
+ }
+
+ /**
+ * Gets the implicit build path, creating it if null
.
+ *
+ * @return the implicit build path.
+ */
+ private Path getBuildpath() {
+ if (buildpath == null) {
+ buildpath = new Path(getProject());
+ }
+ return buildpath;
+ }
+
+ /**
+ * Buildpath to use, by reference.
+ *
+ * @param r a reference to an Ant Path object containing the buildpath.
+ */
+ public void setBuildpathRef(Reference r) {
+ createBuildpath().setRefid(r);
+ }
+
+ /**
+ * Creates the <ant> task configured to run a specific target.
+ *
+ * @return the ant task, configured with the explicit properties and
+ * references necessary to run the sub-build.
+ */
+ private Ant createAntTask() {
+ Ant ant = (Ant) getProject().createTask("ant");
+ ant.setOwningTarget(getOwningTarget());
+ ant.init();
+ if(target.length()>0) {
+ ant.setTarget(target);
+ }
+
+ ant.setInheritAll(inheritAll);
+ for (Enumeration i = properties.elements(); i.hasMoreElements();) {
+ copyProperty(ant.createProperty(), (Property) i.nextElement());
+ }
+
+ ant.setInheritRefs(inheritRefs);
+ for (Enumeration i = references.elements(); i.hasMoreElements();) {
+ ant.addReference((Ant.Reference) i.nextElement());
+ }
+
+ return ant;
+ }
+
+ /**
+ * Assigns an Ant property to another.
+ *
+ * @param to the destination property whose content is modified.
+ * @param from the source property whose content is copied.
+ */
+ private static void copyProperty(Property to, Property from) {
+ to.setName(from.getName());
+
+ if (from.getValue() != null) {
+ to.setValue(from.getValue());
+ }
+ if (from.getFile() != null) {
+ to.setFile(from.getFile());
+ }
+ if (from.getResource() != null) {
+ to.setResource(from.getResource());
+ }
+ if (from.getPrefix() != null) {
+ to.setPrefix(from.getPrefix());
+ }
+ if (from.getRefid() != null) {
+ to.setRefid(from.getRefid());
+ }
+ if (from.getEnvironment() != null) {
+ to.setEnvironment(from.getEnvironment());
+ }
+ if (from.getClasspath() != null) {
+ to.setClasspath(from.getClasspath());
+ }
+ }
+
+} // END class SubAnt
diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
index cdc19ceec..b637cfea8 100644
--- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties
+++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
@@ -73,6 +73,7 @@ tempfile=org.apache.tools.ant.taskdefs.TempFile
classloader=org.apache.tools.ant.taskdefs.Classloader
import=org.apache.tools.ant.taskdefs.ImportTask
whichresource=org.apache.tools.ant.taskdefs.WhichResource
+subant=org.apache.tools.ant.taskdefs.SubAnt
# optional tasks
image=org.apache.tools.ant.taskdefs.optional.image.Image
@@ -183,6 +184,7 @@ chown=org.apache.tools.ant.taskdefs.optional.unix.Chown
attrib=org.apache.tools.ant.taskdefs.optional.windows.Attrib
scp=org.apache.tools.ant.taskdefs.optional.ssh.Scp
sshexec=org.apache.tools.ant.taskdefs.optional.ssh.SSHExec
+jsharpc=org.apache.tools.ant.taskdefs.optional.dotnet.JSharp
# deprecated ant tasks (kept for back compatibility)
starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut