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); | |||
} | |||
} | |||
} | |||