From 2c68e6ab607fa6a70e414eee76d56afe00c29c31 Mon Sep 17 00:00:00 2001 From: Matthew Jason Benson Date: Thu, 7 Apr 2005 19:31:39 +0000 Subject: [PATCH] Add subproject Executor to Executor interface + its use to Project & Ant task. Move keep-going awareness to Executors. PR: 22901 Submitted by: Alexey Solofnenko Reviewed by: Matt Benson git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278114 13f79535-47bb-0310-9956-ffa450edef68 --- src/etc/testcases/core/executor.xml | 12 ++ src/main/org/apache/tools/ant/Executor.java | 9 +- src/main/org/apache/tools/ant/Project.java | 52 ++++--- .../tools/ant/helper/DefaultExecutor.java | 28 +++- .../tools/ant/helper/SingleCheckExecutor.java | 5 + .../org/apache/tools/ant/taskdefs/Ant.java | 9 +- .../org/apache/tools/ant/ExecutorTest.java | 129 ++++++++++++++++++ 7 files changed, 210 insertions(+), 34 deletions(-) create mode 100644 src/etc/testcases/core/executor.xml create mode 100755 src/testcases/org/apache/tools/ant/ExecutorTest.java 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); + } + } + +} +