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-ffa450edef68master
| @@ -0,0 +1,12 @@ | |||
| <project> | |||
| <target name="foo"> | |||
| <echo>foo</echo> | |||
| <fail if="failfoo" message="failfoo" /> | |||
| </target> | |||
| <target name="a" depends="foo"> | |||
| <echo>a</echo> | |||
| </target> | |||
| <target name="b" depends="foo"> | |||
| <echo>b</echo> | |||
| </target> | |||
| </project> | |||
| @@ -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(); | |||
| } | |||
| @@ -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 <code>null</code>. | |||
| * | |||
| * @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 <code>null</code>. | |||
| * | |||
| * @exception BuildException if the build failed. | |||
| */ | |||
| public void executeTargets(Vector names) throws BuildException { | |||
| getExecutor().executeTargets(this, | |||
| (String[]) (names.toArray(new String[names.size()]))); | |||
| } | |||
| /** | |||
| @@ -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; | |||
| } | |||
| } | |||
| @@ -38,4 +38,9 @@ public class SingleCheckExecutor implements Executor { | |||
| project.topoSort(targetNames, project.getTargets(), false)); | |||
| } | |||
| //inherit doc | |||
| public Executor getSubProjectExecutor() { | |||
| return this; | |||
| } | |||
| } | |||
| @@ -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; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -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); | |||
| } | |||
| } | |||
| } | |||