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"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with 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) | void executeTargets(Project project, String[] targetNames) | ||||
throws BuildException; | 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.DefaultInputHandler; | ||||
import org.apache.tools.ant.input.InputHandler; | import org.apache.tools.ant.input.InputHandler; | ||||
import org.apache.tools.ant.helper.DefaultExecutor; | 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.FilterSet; | ||||
import org.apache.tools.ant.types.FilterSetCollection; | import org.apache.tools.ant.types.FilterSetCollection; | ||||
import org.apache.tools.ant.types.Description; | import org.apache.tools.ant.types.Description; | ||||
@@ -243,6 +242,7 @@ public class Project { | |||||
ComponentHelper.getComponentHelper(subProject) | ComponentHelper.getComponentHelper(subProject) | ||||
.initSubProject(ComponentHelper.getComponentHelper(this)); | .initSubProject(ComponentHelper.getComponentHelper(this)); | ||||
subProject.setKeepGoingMode(this.isKeepGoingMode()); | 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"); | Object o = getReference("ant.executor"); | ||||
if (o == null) { | if (o == null) { | ||||
String classname = getProperty("ant.executor.class"); | String classname = getProperty("ant.executor.class"); | ||||
if (classname == null) { | 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); | log("Attempting to create object of type " + classname, MSG_DEBUG); | ||||
try { | try { | ||||
@@ -1046,17 +1046,27 @@ public class Project { | |||||
} catch (Exception ex) { | } catch (Exception ex) { | ||||
log(ex.toString(), MSG_ERR); | 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"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
@@ -17,25 +17,43 @@ | |||||
package org.apache.tools.ant.helper; | package org.apache.tools.ant.helper; | ||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.Executor; | import org.apache.tools.ant.Executor; | ||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
/** | /** | ||||
* Default Target executor implementation. Runs each target individually | * 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 | * @since Ant 1.6.3 | ||||
*/ | */ | ||||
public class DefaultExecutor implements Executor { | public class DefaultExecutor implements Executor { | ||||
private static final SingleCheckExecutor SUB_EXECUTOR = new SingleCheckExecutor(); | |||||
//inherit doc | //inherit doc | ||||
public void executeTargets(Project project, String[] targetNames) | public void executeTargets(Project project, String[] targetNames) | ||||
throws BuildException { | throws BuildException { | ||||
BuildException thrownException = null; | |||||
for (int i = 0; i < targetNames.length; i++) { | 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)); | 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 { | public class Ant extends Task { | ||||
/** Target Executor */ | |||||
private static final Executor EXECUTOR = new SingleCheckExecutor(); | |||||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | ||||
/** the basedir where is executed the build file */ | /** the basedir where is executed the build file */ | ||||
@@ -396,9 +393,7 @@ public class Ant extends Task { | |||||
try { | try { | ||||
log("Entering " + antFile + "...", Project.MSG_VERBOSE); | log("Entering " + antFile + "...", Project.MSG_VERBOSE); | ||||
newProject.fireSubBuildStarted(); | newProject.fireSubBuildStarted(); | ||||
EXECUTOR.executeTargets(newProject, | |||||
(String[]) (locals.toArray(new String[locals.size()]))); | |||||
newProject.executeTargets(locals); | |||||
} catch (BuildException ex) { | } catch (BuildException ex) { | ||||
t = ProjectHelper | t = ProjectHelper | ||||
.addLocationToBuildException(ex, getLocation()); | .addLocationToBuildException(ex, getLocation()); | ||||
@@ -755,4 +750,4 @@ public class Ant extends Task { | |||||
return name; | 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); | |||||
} | |||||
} | |||||
} | |||||