diff --git a/src/etc/testcases/core/executor.xml b/src/etc/testcases/core/executor.xml
new file mode 100644
index 000000000..1e960349f
--- /dev/null
+++ b/src/etc/testcases/core/executor.xml
@@ -0,0 +1,12 @@
+
+
+ foo
+
+
+
+ a
+
+
+ b
+
+
diff --git a/src/main/org/apache/tools/ant/Executor.java b/src/main/org/apache/tools/ant/Executor.java
index fff002dc7..49ea495dd 100755
--- a/src/main/org/apache/tools/ant/Executor.java
+++ b/src/main/org/apache/tools/ant/Executor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 The Apache Software Foundation
+ * Copyright 2004-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,4 +31,11 @@ public interface Executor {
*/
void executeTargets(Project project, String[] targetNames)
throws BuildException;
+
+ /**
+ * Get the appropriate subproject Executor instance.
+ * @return an Executor instance.
+ */
+ Executor getSubProjectExecutor();
+
}
diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java
index d9eae6387..5b510102a 100644
--- a/src/main/org/apache/tools/ant/Project.java
+++ b/src/main/org/apache/tools/ant/Project.java
@@ -37,7 +37,6 @@ import java.util.WeakHashMap;
import org.apache.tools.ant.input.DefaultInputHandler;
import org.apache.tools.ant.input.InputHandler;
import org.apache.tools.ant.helper.DefaultExecutor;
-import org.apache.tools.ant.helper.KeepGoingExecutor;
import org.apache.tools.ant.types.FilterSet;
import org.apache.tools.ant.types.FilterSetCollection;
import org.apache.tools.ant.types.Description;
@@ -243,6 +242,7 @@ public class Project {
ComponentHelper.getComponentHelper(subProject)
.initSubProject(ComponentHelper.getComponentHelper(this));
subProject.setKeepGoingMode(this.isKeepGoingMode());
+ subProject.setExecutor(getExecutor().getSubProjectExecutor());
}
/**
@@ -1015,23 +1015,23 @@ public class Project {
}
/**
- * Execute the specified sequence of targets, and the targets
- * they depend on.
- *
- * @param targetNames A vector of target name strings to execute.
- * Must not be null
.
- *
- * @exception BuildException if the build failed.
+ * Set the Executor instance for this Project.
+ * @param e the Executor to use.
*/
- public void executeTargets(Vector targetNames) throws BuildException {
+ public void setExecutor(Executor e) {
+ addReference("ant.executor", e);
+ }
+ /**
+ * Get this Project's Executor (setting it if necessary).
+ * @return an Executor instance.
+ */
+ public Executor getExecutor() {
Object o = getReference("ant.executor");
if (o == null) {
String classname = getProperty("ant.executor.class");
if (classname == null) {
- classname = (keepGoingMode)
- ? KeepGoingExecutor.class.getName()
- : DefaultExecutor.class.getName();
+ classname = DefaultExecutor.class.getName();
}
log("Attempting to create object of type " + classname, MSG_DEBUG);
try {
@@ -1046,17 +1046,27 @@ public class Project {
} catch (Exception ex) {
log(ex.toString(), MSG_ERR);
}
- if (o != null) {
- addReference("ant.executor", o);
+ if (o == null) {
+ throw new BuildException(
+ "Unable to obtain a Target Executor instance.");
}
+ setExecutor((Executor) o);
}
- if (o == null) {
- throw new BuildException("Unable to obtain a Target Executor instance.");
- } else {
- String[] targetNameArray = (String[]) (targetNames.toArray(
- new String[targetNames.size()]));
- ((Executor) o).executeTargets(this, targetNameArray);
- }
+ return (Executor) o;
+ }
+
+ /**
+ * Execute the specified sequence of targets, and the targets
+ * they depend on.
+ *
+ * @param names A vector of target name strings to execute.
+ * Must not be null
.
+ *
+ * @exception BuildException if the build failed.
+ */
+ public void executeTargets(Vector names) throws BuildException {
+ getExecutor().executeTargets(this,
+ (String[]) (names.toArray(new String[names.size()])));
}
/**
diff --git a/src/main/org/apache/tools/ant/helper/DefaultExecutor.java b/src/main/org/apache/tools/ant/helper/DefaultExecutor.java
index 73f906c0b..0166c2b48 100755
--- a/src/main/org/apache/tools/ant/helper/DefaultExecutor.java
+++ b/src/main/org/apache/tools/ant/helper/DefaultExecutor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 The Apache Software Foundation
+ * Copyright 2004-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,25 +17,43 @@
package org.apache.tools.ant.helper;
-
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Executor;
import org.apache.tools.ant.BuildException;
-
/**
* Default Target executor implementation. Runs each target individually
- * (including all of its dependencies), halting immediately upon error.
+ * (including all of its dependencies). If an error occurs, behavior is
+ * determined by the Project's "keep-going" mode.
* @since Ant 1.6.3
*/
public class DefaultExecutor implements Executor {
+ private static final SingleCheckExecutor SUB_EXECUTOR = new SingleCheckExecutor();
+
//inherit doc
public void executeTargets(Project project, String[] targetNames)
throws BuildException {
+ BuildException thrownException = null;
for (int i = 0; i < targetNames.length; i++) {
- project.executeTarget(targetNames[i]);
+ try {
+ project.executeTarget(targetNames[i]);
+ } catch (BuildException ex) {
+ if (project.isKeepGoingMode()) {
+ thrownException = ex;
+ } else {
+ throw ex;
+ }
+ }
+ }
+ if (thrownException != null) {
+ throw thrownException;
}
}
+ //inherit doc
+ public Executor getSubProjectExecutor() {
+ return SUB_EXECUTOR;
+ }
+
}
diff --git a/src/main/org/apache/tools/ant/helper/SingleCheckExecutor.java b/src/main/org/apache/tools/ant/helper/SingleCheckExecutor.java
index d5301f640..b055304ed 100755
--- a/src/main/org/apache/tools/ant/helper/SingleCheckExecutor.java
+++ b/src/main/org/apache/tools/ant/helper/SingleCheckExecutor.java
@@ -38,4 +38,9 @@ public class SingleCheckExecutor implements Executor {
project.topoSort(targetNames, project.getTargets(), false));
}
+ //inherit doc
+ public Executor getSubProjectExecutor() {
+ return this;
+ }
+
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/Ant.java b/src/main/org/apache/tools/ant/taskdefs/Ant.java
index 00f3353ea..f7d2ca35b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Ant.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Ant.java
@@ -64,9 +64,6 @@ import org.apache.tools.ant.util.FileUtils;
*/
public class Ant extends Task {
- /** Target Executor */
- private static final Executor EXECUTOR = new SingleCheckExecutor();
-
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
/** the basedir where is executed the build file */
@@ -396,9 +393,7 @@ public class Ant extends Task {
try {
log("Entering " + antFile + "...", Project.MSG_VERBOSE);
newProject.fireSubBuildStarted();
- EXECUTOR.executeTargets(newProject,
- (String[]) (locals.toArray(new String[locals.size()])));
-
+ newProject.executeTargets(locals);
} catch (BuildException ex) {
t = ProjectHelper
.addLocationToBuildException(ex, getLocation());
@@ -755,4 +750,4 @@ public class Ant extends Task {
return name;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/testcases/org/apache/tools/ant/ExecutorTest.java b/src/testcases/org/apache/tools/ant/ExecutorTest.java
new file mode 100755
index 000000000..22298edd1
--- /dev/null
+++ b/src/testcases/org/apache/tools/ant/ExecutorTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant;
+
+import java.util.Vector;
+
+import org.apache.tools.ant.taskdefs.Exit;
+
+/**
+ * Executor tests
+ */
+public class ExecutorTest extends BuildFileTest implements BuildListener {
+ private static final String SINGLE_CHECK
+ = "org.apache.tools.ant.helper.SingleCheckExecutor";
+ private static final Vector targetNames;
+ static {
+ targetNames = new Vector();
+ targetNames.add("a");
+ targetNames.add("b");
+ }
+
+ private int targetCount;
+
+ /* BuildListener stuff */
+ public void targetStarted(BuildEvent event) {
+ targetCount++;
+ }
+ public void buildStarted(BuildEvent event) {}
+ public void buildFinished(BuildEvent event) {}
+ public void targetFinished(BuildEvent event) {}
+ public void taskStarted(BuildEvent event) {}
+ public void taskFinished(BuildEvent event) {}
+ public void messageLogged(BuildEvent event) {}
+
+ public ExecutorTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("src/etc/testcases/core/executor.xml");
+ targetCount = 0;
+ getProject().addBuildListener(this);
+ }
+
+ private Project getProject(String e) {
+ return getProject(e, false);
+ }
+
+ private Project getProject(String e, boolean f) {
+ return getProject(e, f, false);
+ }
+
+ private Project getProject(String e, boolean f, boolean k) {
+ Project p = getProject();
+ p.setNewProperty("ant.executor.class", e);
+ p.setKeepGoingMode(k);
+ if (f) {
+ p.setNewProperty("failfoo", "foo");
+ }
+ return p;
+ }
+
+ public void testDefaultExecutor() {
+ getProject().executeTargets(targetNames);
+ assertEquals(targetCount, 4);
+ }
+
+ public void testSingleCheckExecutor() {
+ getProject(SINGLE_CHECK).executeTargets(targetNames);
+ assertEquals(targetCount, 3);
+ }
+
+ public void testDefaultFailure() {
+ try {
+ getProject(null, true).executeTargets(targetNames);
+ fail("should fail");
+ } catch (BuildException e) {
+ assertTrue(e.getMessage().equals("failfoo"));
+ assertEquals(targetCount, 1);
+ }
+ }
+
+ public void testSingleCheckFailure() {
+ try {
+ getProject(SINGLE_CHECK, true).executeTargets(targetNames);
+ fail("should fail");
+ } catch (BuildException e) {
+ assertTrue(e.getMessage().equals("failfoo"));
+ assertEquals(targetCount, 1);
+ }
+ }
+
+ public void testKeepGoingDefault() {
+ try {
+ getProject(null, true, true).executeTargets(targetNames);
+ fail("should fail");
+ } catch (BuildException e) {
+ assertTrue(e.getMessage().equals("failfoo"));
+ assertEquals(targetCount, 2);
+ }
+ }
+
+ public void testKeepGoingSingleCheck() {
+ try {
+ getProject(SINGLE_CHECK, true, true).executeTargets(targetNames);
+ fail("should fail");
+ } catch (BuildException e) {
+ assertTrue(e.getMessage().equals("failfoo"));
+ assertEquals(targetCount, 1);
+ }
+ }
+
+}
+