diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/CoreExecService.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/CoreExecService.java index 9d0c206de..a94f957b8 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/CoreExecService.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/CoreExecService.java @@ -1,59 +1,60 @@ /* - * The Apache Software License, Version 1.1 + * The Apache Software License, Version 1.1 * - * Copyright (c) 2002 The Apache Software Foundation. All rights - * reserved. + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. * - * 3. The end-user documentation included with the redistribution, if - * any, must include the following acknowlegement: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowlegement may appear in the software itself, - * if and wherever such third-party acknowlegements normally appear. + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. * - * 4. The names "The Jakarta Project", "Ant", and "Apache Software - * Foundation" must not be used to endorse or promote products derived - * from this software without prior written permission. For written - * permission, please contact apache@apache.org. + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. * - * 5. Products derived from this software may not be called "Apache" - * nor may "Apache" appear in their names without prior written - * permission of the Apache Group. + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . */ package org.apache.ant.antcore.execution; import java.io.File; import java.net.MalformedURLException; +import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.ant.antcore.modelparser.XMLProjectParser; @@ -73,8 +74,13 @@ import org.apache.ant.init.LoaderUtils; * @created 8 February 2002 */ public class CoreExecService implements ExecService { + /** The Frame this service instance is working for */ private Frame frame; + + /** A map of subbuild keys to the frame of the subbuild. */ + private Map subBuilds = new HashMap(); + /** * Constructor @@ -85,82 +91,38 @@ public class CoreExecService implements ExecService { this.frame = frame; } - /** - * Run a sub-build. - * - * @param antFile the file containing the XML description of the model - * @param targets A list of targets to be run - * @param properties the initiali properties to be used in the build - * @exception ExecutionException if the subbuild cannot be run - */ - public void runBuild(File antFile, Map properties, List targets) - throws ExecutionException { - try { - // Parse the build file into a project - XMLProjectParser parser = new XMLProjectParser(); - Project project - = parser.parseBuildFile(InitUtils.getFileURL(antFile)); - runBuild(project, properties, targets); - } catch (MalformedURLException e) { - throw new ExecutionException(e); - } catch (XMLParseException e) { - throw new ExecutionException(e); - } - } - - /** - * Run a sub-build. - * - * @param model the project model to be used for the build - * @param targets A list of targets to be run - * @param properties the initiali properties to be used in the build - * @exception ExecutionException if the subbuild cannot be run - */ - public void runBuild(Project model, Map properties, List targets) - throws ExecutionException { - Frame newFrame = frame.createFrame(model); - newFrame.setInitialProperties(properties); - newFrame.runBuild(targets); - } - - /** - * Run a sub-build using the current frame's project model - * - * @param targets A list of targets to be run - * @param properties the initiali properties to be used in the build - * @exception ExecutionException if the subbuild cannot be run - */ - public void callTarget(Map properties, List targets) - throws ExecutionException { - runBuild(frame.getProject(), properties, targets); - } /** - * Execute a task. The task should have already been initialised by - * the core. This is checked + * Execute a task. The task should have already been initialised by the + * core. This is checked * * @param task the task to be executed * @exception ExecutionException if there is an execution problem */ public void executeTask(Task task) throws ExecutionException { AntContext context = task.getAntContext(); + if (!(context instanceof ExecutionContext)) { throw new ExecutionException("The Task was not configured with an" + " appropriate context"); } ExecutionContext execContext = (ExecutionContext) context; - + frame.getEventSupport().fireTaskStarted(task); + Throwable failureCause = null; + try { - ClassLoader currentLoader - = LoaderUtils.setContextLoader(execContext.getClassLoader()); + ClassLoader currentLoader + = LoaderUtils.setContextLoader(execContext.getClassLoader()); + task.execute(); LoaderUtils.setContextLoader(currentLoader); } catch (Throwable e) { ExecutionException ee = new ExecutionException(e.getClass().getName() + ": " + e.getMessage(), e); + failureCause = ee; throw ee; } finally { @@ -168,6 +130,17 @@ public class CoreExecService implements ExecService { } } + + /** + * Get the base directory for this execution of this frame + * + * @return the base directory + */ + public File getBaseDir() { + return frame.getBaseDir(); + } + + /** * get the name of the project associated with this execution. * @@ -177,13 +150,99 @@ public class CoreExecService implements ExecService { return frame.getProjectName(); } + /** - * Get the base directory for this execution of this frame + * Handle subbuild output. * - * @return the base directory + * @param subbuildKey the core's key for managing the subbuild. + * @param line the content produce by the current thread. + * @param isErr true if this content is from the thread's error stream. */ - public File getBaseDir() { - return frame.getBaseDir(); + public void handleBuildOutput(Object subbuildKey, String line, + boolean isErr) throws ExecutionException { + getSubbuildFrame(subbuildKey).threadOutput(line, isErr); + } + + + private Frame getSubbuildFrame(Object key) throws ExecutionException { + Frame subFrame = (Frame) subBuilds.get(key); + + if (subFrame == null) { + throw new ExecutionException("Could not find execution frame " + + "for subbuild"); + } + return subFrame; + } + + /** + * Run a build which have been previously setup + * + * @param targets A list of targets to be run + * @param key Description of the Parameter + * @exception ExecutionException if the build cannot be run + */ + public void runBuild(Object key, List targets) throws ExecutionException { + getSubbuildFrame(key).runBuild(targets); + subBuilds.remove(key); + } + + + /** + * Setup a sub-build. + * + * @param antFile the file containing the XML description of the model + * @param properties the initiali properties to be used in the build + * @return Description of the Return Value + * @exception ExecutionException if the subbuild cannot be run + */ + public Object setupBuild(File antFile, Map properties) + throws ExecutionException { + try { + // Parse the build file into a project + XMLProjectParser parser = new XMLProjectParser(); + Project project + = parser.parseBuildFile(InitUtils.getFileURL(antFile)); + + return setupBuild(project, properties); + } catch (MalformedURLException e) { + throw new ExecutionException(e); + } catch (XMLParseException e) { + throw new ExecutionException(e); + } + } + + + /** + * Setup a sub-build. + * + * @param model the project model to be used for the build + * @param properties the initiali properties to be used in the build + * @return Description of the Return Value + * @exception ExecutionException if the subbuild cannot be run + */ + public Object setupBuild(Project model, Map properties) + throws ExecutionException { + Frame newFrame = frame.createFrame(model); + + newFrame.setInitialProperties(properties); + + Object key = new Object(); + + subBuilds.put(key, newFrame); + return key; + } + + + /** + * Setup a sub-build using the current frame's project model + * + * @param properties the initiali properties to be used in the build + * @return Description of the Return Value + * @exception ExecutionException if the subbuild cannot be run + */ + public Object setupBuild(Map properties) + throws ExecutionException { + return setupBuild(frame.getProject(), properties); } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java index 51f11dc1f..1bbf53a09 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java @@ -84,8 +84,8 @@ import org.apache.ant.init.InitConfig; * contains the data values set by Ant tasks as they are executed, including * task definitions, property values, etc. * - * @author Conor MacNeill - * @created 14 January 2002 + * @author Conor MacNeill + * @created 14 January 2002 */ public class Frame implements DemuxOutputReceiver { /** the base dir of the project */ @@ -151,12 +151,11 @@ public class Frame implements DemuxOutputReceiver { /** * Create an Execution Frame for the given project * - * @param standardLibs The libraries of tasks and types - * available to this frame - * @param config the user config to use for this - * execution of Ant - * @param initConfig Ant's initialisation config - * @exception ExecutionException if a component of the library cannot be + * @param standardLibs The libraries of tasks and types available to this + * frame + * @param config the user config to use for this execution of Ant + * @param initConfig Ant's initialisation config + * @exception ExecutionException if a component of the library cannot be * imported */ protected Frame(Map standardLibs, InitConfig initConfig, @@ -171,11 +170,9 @@ public class Frame implements DemuxOutputReceiver { * Replace ${} style constructions in the given value with the string * value of the corresponding data values in the frame * - * @param value the string to be scanned for property - * references. - * @return the string with all property references - * replaced - * @exception ExecutionException if any of the properties do not exist + * @param value the string to be scanned for property references. + * @return the string with all property references replaced + * @exception ExecutionException if any of the properties do not exist */ public String replacePropertyRefs(String value) throws ExecutionException { return dataService.replacePropertyRefs(value); @@ -185,15 +182,15 @@ public class Frame implements DemuxOutputReceiver { /** * Sets the Project of the Frame * - * @param project The new Project value - * @exception ExecutionException if any required sub-frames cannot be + * @param project The new Project value + * @exception ExecutionException if any required sub-frames cannot be * created and configured */ protected void setProject(Project project) throws ExecutionException { this.project = project; referencedFrames = new HashMap(); - for (Iterator i = project.getReferencedProjectNames(); i.hasNext();) { + for (Iterator i = project.getReferencedProjectNames(); i.hasNext(); ) { String referenceName = (String) i.next(); Project referencedProject = project.getReferencedProject(referenceName); @@ -211,7 +208,7 @@ public class Frame implements DemuxOutputReceiver { /** * get the name of the project associated with this frame. * - * @return the project's name + * @return the project's name */ public String getProjectName() { if (project != null) { @@ -224,10 +221,10 @@ public class Frame implements DemuxOutputReceiver { /** * Set a value in this frame or any of its imported frames. * - * @param name the name of the value - * @param value the actual value - * @param mutable if true, existing values can be changed - * @exception ExecutionException if the value name is invalid + * @param name the name of the value + * @param value the actual value + * @param mutable if true, existing values can be changed + * @exception ExecutionException if the value name is invalid */ protected void setDataValue(String name, Object value, boolean mutable) throws ExecutionException { @@ -253,9 +250,9 @@ public class Frame implements DemuxOutputReceiver { /** * Set the initial properties to be used when the frame starts execution * - * @param properties a Map of named properties which may in - * fact be any object - * @exception ExecutionException if the properties cannot be set + * @param properties a Map of named properties which may in fact be any + * object + * @exception ExecutionException if the properties cannot be set */ protected void setInitialProperties(Map properties) throws ExecutionException { @@ -271,7 +268,7 @@ public class Frame implements DemuxOutputReceiver { /** * Set the values of various magic properties * - * @exception ExecutionException if the properties cannot be set + * @exception ExecutionException if the properties cannot be set */ protected void setMagicProperties() throws ExecutionException { URL antHomeURL = initConfig.getAntHome(); @@ -291,11 +288,10 @@ public class Frame implements DemuxOutputReceiver { /** * Get a definition from a referenced frame * - * @param definitionName the name of the definition relative to - * this frame - * @return the appropriate import info object from - * the referenced frame's imports - * @exception ExecutionException if the referenced definition cannot be + * @param definitionName the name of the definition relative to this frame + * @return the appropriate import info object from the referenced frame's + * imports + * @exception ExecutionException if the referenced definition cannot be * found */ protected ImportInfo getReferencedDefinition(String definitionName) @@ -318,7 +314,7 @@ public class Frame implements DemuxOutputReceiver { /** * Gets the project model this frame is working with * - * @return the project model + * @return the project model */ protected Project getProject() { return project; @@ -330,7 +326,7 @@ public class Frame implements DemuxOutputReceiver { * is an expensive operation since it must clone all of the property * stores in all frames * - * @return a Map containing the frames properties indexed by their full + * @return a Map containing the frames properties indexed by their full * name. */ protected Map getAllProperties() { @@ -359,7 +355,7 @@ public class Frame implements DemuxOutputReceiver { /** * Get the Ant initialization configuration for this frame. * - * @return Ant's initialization configuration + * @return Ant's initialization configuration */ protected InitConfig getInitConfig() { return initConfig; @@ -369,7 +365,7 @@ public class Frame implements DemuxOutputReceiver { /** * Get the config instance being used by this frame. * - * @return the config associated with this frame. + * @return the config associated with this frame. */ protected AntConfig getConfig() { return config; @@ -379,11 +375,10 @@ public class Frame implements DemuxOutputReceiver { /** * Get the core's implementation of the given service interface. * - * @param serviceInterfaceClass the service interface for which an + * @param serviceInterfaceClass the service interface for which an * implementation is require - * @return the core's implementation of the service - * interface - * @exception ExecutionException if the core does not provide an + * @return the core's implementation of the service interface + * @exception ExecutionException if the core does not provide an * implementatin of the requested interface */ protected Object getCoreService(Class serviceInterfaceClass) @@ -402,7 +397,7 @@ public class Frame implements DemuxOutputReceiver { * Get the EventSupport instance for this frame. This tracks the build * listeners on this frame * - * @return the EventSupport instance + * @return the EventSupport instance */ protected BuildEventSupport getEventSupport() { return eventSupport; @@ -412,7 +407,7 @@ public class Frame implements DemuxOutputReceiver { /** * Gets the baseDir of the Frame * - * @return the baseDir value + * @return the baseDir value */ protected File getBaseDir() { return baseDir; @@ -422,9 +417,9 @@ public class Frame implements DemuxOutputReceiver { /** * Get a referenced frame by its reference name * - * @param referenceName the name under which the frame was imported. - * @return the Frame asscociated with the given reference - * name or null if there is no such project. + * @param referenceName the name under which the frame was imported. + * @return the Frame asscociated with the given reference name or null if + * there is no such project. */ protected Frame getReferencedFrame(String referenceName) { return (Frame) referencedFrames.get(referenceName); @@ -434,7 +429,7 @@ public class Frame implements DemuxOutputReceiver { /** * Get the frames representing referenced projects. * - * @return an iterator which returns the referenced ExeuctionFrames.. + * @return an iterator which returns the referenced ExeuctionFrames.. */ protected Iterator getReferencedFrames() { return referencedFrames.values().iterator(); @@ -444,8 +439,8 @@ public class Frame implements DemuxOutputReceiver { /** * Get the name of an object in its frame * - * @param fullname The name of the object - * @return the name of the object within its containing frame + * @param fullname The name of the object + * @return the name of the object within its containing frame */ protected String getNameInFrame(String fullname) { int index = fullname.lastIndexOf(Project.REF_DELIMITER); @@ -460,11 +455,10 @@ public class Frame implements DemuxOutputReceiver { /** * Get a value from this frame or any imported frame * - * @param name the name of the data value - may contain - * reference delimiters - * @return the data value fetched from the - * appropriate frame - * @exception ExecutionException if the value is not defined + * @param name the name of the data value - may contain reference + * delimiters + * @return the data value fetched from the appropriate frame + * @exception ExecutionException if the value is not defined */ protected Object getDataValue(String name) throws ExecutionException { Frame frame = getContainingFrame(name); @@ -484,10 +478,10 @@ public class Frame implements DemuxOutputReceiver { /** * Indicate if a data value has been set * - * @param name the name of the data value - may contain - * reference delimiters - * @return true if the value exists - * @exception ExecutionException if the containing frame for the value + * @param name the name of the data value - may contain reference + * delimiters + * @return true if the value exists + * @exception ExecutionException if the containing frame for the value * does not exist */ protected boolean isDataValueSet(String name) throws ExecutionException { @@ -509,9 +503,9 @@ public class Frame implements DemuxOutputReceiver { * Get the execution frame which contains, directly, the named element * where the name is relative to this frame * - * @param elementName The name of the element - * @return the execution frame for the project that contains - * the given target + * @param elementName The name of the element + * @return the execution frame for the project that contains the given + * target */ protected Frame getContainingFrame(String elementName) { int index = elementName.lastIndexOf(Project.REF_DELIMITER); @@ -541,12 +535,12 @@ public class Frame implements DemuxOutputReceiver { /** * Add a collection of properties to this frame * - * @param properties the collection of property values, - * indexed by their names - * @exception ExecutionException if the frame cannot be created. + * @param properties the collection of property values, indexed by their + * names + * @exception ExecutionException if the frame cannot be created. */ protected void addProperties(Map properties) throws ExecutionException { - for (Iterator i = properties.keySet().iterator(); i.hasNext();) { + for (Iterator i = properties.keySet().iterator(); i.hasNext(); ) { String name = (String) i.next(); Object value = properties.get(name); @@ -558,10 +552,9 @@ public class Frame implements DemuxOutputReceiver { /** * Create a new frame for a given project * - * @param project the project model the frame will deal - * with - * @return an Frame ready to build the project - * @exception ExecutionException if the frame cannot be created. + * @param project the project model the frame will deal with + * @return an Frame ready to build the project + * @exception ExecutionException if the frame cannot be created. */ protected Frame createFrame(Project project) throws ExecutionException { @@ -569,7 +562,7 @@ public class Frame implements DemuxOutputReceiver { = new Frame(standardLibs, initConfig, config); newFrame.setProject(project); - for (Iterator j = eventSupport.getListeners(); j.hasNext();) { + for (Iterator j = eventSupport.getListeners(); j.hasNext(); ) { BuildListener listener = (BuildListener) j.next(); newFrame.addBuildListener(listener); @@ -581,8 +574,8 @@ public class Frame implements DemuxOutputReceiver { /** * Log a message as a build event * - * @param message the message to be logged - * @param level the priority level of the message + * @param message the message to be logged + * @param level the priority level of the message */ protected void log(String message, int level) { eventSupport.fireMessageLogged(project, message, level); @@ -592,10 +585,10 @@ public class Frame implements DemuxOutputReceiver { /** * Add a build listener to this execution frame * - * @param listener the listener to be added to the frame + * @param listener the listener to be added to the frame */ protected void addBuildListener(BuildListener listener) { - for (Iterator i = getReferencedFrames(); i.hasNext();) { + for (Iterator i = getReferencedFrames(); i.hasNext(); ) { Frame referencedFrame = (Frame) i.next(); referencedFrame.addBuildListener(listener); @@ -607,10 +600,10 @@ public class Frame implements DemuxOutputReceiver { /** * Remove a build listener from the execution * - * @param listener the listener to be removed + * @param listener the listener to be removed */ protected void removeBuildListener(BuildListener listener) { - for (Iterator i = getReferencedFrames(); i.hasNext();) { + for (Iterator i = getReferencedFrames(); i.hasNext(); ) { Frame subFrame = (Frame) i.next(); subFrame.removeBuildListener(listener); @@ -622,9 +615,8 @@ public class Frame implements DemuxOutputReceiver { /** * Run the given list of targets * - * @param targets a list of target names which are to be - * evaluated - * @exception ExecutionException if there is a problem in the build + * @param targets a list of target names which are to be evaluated + * @exception ExecutionException if there is a problem in the build */ protected void runBuild(List targets) throws ExecutionException { determineBaseDirs(); @@ -640,7 +632,7 @@ public class Frame implements DemuxOutputReceiver { executeTarget(defaultTarget); } } else { - for (Iterator i = targets.iterator(); i.hasNext();) { + for (Iterator i = targets.iterator(); i.hasNext(); ) { String targetName = (String) i.next(); log("Executing target: " + targetName, MessageLevel.MSG_DEBUG); @@ -653,10 +645,9 @@ public class Frame implements DemuxOutputReceiver { /** * Execute the tasks of a target in this frame with the given name * - * @param targetName the name of the target whose tasks will - * be evaluated - * @exception ExecutionException if there is a problem executing the - * tasks of the target + * @param targetName the name of the target whose tasks will be evaluated + * @exception ExecutionException if there is a problem executing the tasks + * of the target */ protected void executeTarget(String targetName) throws ExecutionException { // to execute a target we must determine its dependencies and @@ -666,7 +657,7 @@ public class Frame implements DemuxOutputReceiver { // firstly build a list of fully qualified target names to execute. List dependencyOrder = project.getTargetDependencies(targetName); - for (Iterator i = dependencyOrder.iterator(); i.hasNext();) { + for (Iterator i = dependencyOrder.iterator(); i.hasNext(); ) { String fullTargetName = (String) i.next(); Frame frame = getContainingFrame(fullTargetName); String localTargetName = getNameInFrame(fullTargetName); @@ -682,8 +673,8 @@ public class Frame implements DemuxOutputReceiver { /** * Run the tasks returned by the given iterator * - * @param taskIterator the iterator giving the tasks to execute - * @exception ExecutionException if there is execution problem while + * @param taskIterator the iterator giving the tasks to execute + * @exception ExecutionException if there is execution problem while * executing tasks */ protected void executeTasks(Iterator taskIterator) @@ -727,9 +718,9 @@ public class Frame implements DemuxOutputReceiver { * Execute the given target's tasks. The target must be local to this * frame's project * - * @param targetName the name of the target within this frame - * that is to be executed. - * @exception ExecutionException if there is a problem executing tasks + * @param targetName the name of the target within this frame that is to + * be executed. + * @exception ExecutionException if there is a problem executing tasks */ protected void executeTargetTasks(String targetName) throws ExecutionException { @@ -778,11 +769,11 @@ public class Frame implements DemuxOutputReceiver { /** * Initialize the frame by executing the project level tasks if any * - * @exception ExecutionException if the top level tasks of the frame + * @exception ExecutionException if the top level tasks of the frame * failed */ protected void initialize() throws ExecutionException { - for (Iterator i = getReferencedFrames(); i.hasNext();) { + for (Iterator i = getReferencedFrames(); i.hasNext(); ) { Frame referencedFrame = (Frame) i.next(); referencedFrame.initialize(); @@ -797,7 +788,7 @@ public class Frame implements DemuxOutputReceiver { /** * Determine the base directory for each frame in the frame hierarchy * - * @exception ExecutionException if the base directories cannot be + * @exception ExecutionException if the base directories cannot be * determined */ private void determineBaseDirs() throws ExecutionException { @@ -825,7 +816,7 @@ public class Frame implements DemuxOutputReceiver { } setDataValue(MagicProperties.BASEDIR, baseDir.getAbsolutePath(), true); - for (Iterator i = getReferencedFrames(); i.hasNext();) { + for (Iterator i = getReferencedFrames(); i.hasNext(); ) { Frame refFrame = (Frame) i.next(); refFrame.determineBaseDirs(); @@ -859,8 +850,8 @@ public class Frame implements DemuxOutputReceiver { * the thread producing the content. The content is broken up into * separate lines * - * @param line the content produce by the current thread. - * @param isErr true if this content is from the thread's error stream. + * @param line the content produce by the current thread. + * @param isErr true if this content is from the thread's error stream. */ public void threadOutput(String line, boolean isErr) { eventSupport.threadOutput(line, isErr); diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ant.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ant.java index 6d42294fe..64d5b63c5 100644 --- a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ant.java +++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ant.java @@ -105,11 +105,8 @@ public class Ant extends AntBase { * @exception ExecutionException if the build can't be run */ public void execute() throws ExecutionException { - System.out.println("Starting Ant Task"); if (baseDir == null) { - ExecService execService - = (ExecService) getCoreService(ExecService.class); - baseDir = execService.getBaseDir(); + baseDir = getExecService().getBaseDir(); } File antFile = null; @@ -125,11 +122,9 @@ public class Ant extends AntBase { setProperty(MagicProperties.BASEDIR, baseDir.getAbsolutePath()); - ExecService execService - = (ExecService) getCoreService(ExecService.class); - - execService.runBuild(antFile, getProperties(), getTargets()); - System.out.println("Ending Ant Task"); + Object key = getExecService().setupBuild(antFile, getProperties()); + setSubBuildKey(key); + getExecService().runBuild(key, getTargets()); } } diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntBase.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntBase.java index 8731f2f42..7860df2ba 100644 --- a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntBase.java +++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntBase.java @@ -1,55 +1,55 @@ /* - * The Apache Software License, Version 1.1 + * The Apache Software License, Version 1.1 * - * Copyright (c) 2002 The Apache Software Foundation. All rights - * reserved. + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. * - * 3. The end-user documentation included with the redistribution, if - * any, must include the following acknowlegement: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowlegement may appear in the software itself, - * if and wherever such third-party acknowlegements normally appear. + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. * - * 4. The names "The Jakarta Project", "Ant", and "Apache Software - * Foundation" must not be used to endorse or promote products derived - * from this software without prior written permission. For written - * permission, please contact apache@apache.org. + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. * - * 5. Products derived from this software may not be called "Apache" - * nor may "Apache" appear in their names without prior written - * permission of the Apache Group. + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . */ package org.apache.ant.antlib.system; import java.util.ArrayList; @@ -60,6 +60,7 @@ import org.apache.ant.common.antlib.AbstractComponent; import org.apache.ant.common.antlib.AbstractTask; import org.apache.ant.common.antlib.AntContext; import org.apache.ant.common.service.DataService; +import org.apache.ant.common.service.ExecService; import org.apache.ant.common.util.ExecutionException; /** @@ -85,46 +86,49 @@ public abstract class AntBase extends AbstractTask { /** - * Sets the name of the Property + * Gets the name of the Property * - * @param name the new name value + * @return the name value */ - public void setName(String name) { - this.name = name; + public String getName() { + return name; } + /** - * Sets the value of the Property + * Gets the value of the Property * - * @param value the new value value + * @return the value value */ - public void setValue(String value) { - this.value = value; + public String getValue() { + return value; } + /** - * Gets the name of the Property + * Sets the name of the Property * - * @return the name value + * @param name the new name value */ - public String getName() { - return name; + public void setName(String name) { + this.name = name; } + /** - * Gets the value of the Property + * Sets the value of the Property * - * @return the value value + * @param value the new value value */ - public String getValue() { - return value; + public void setValue(String value) { + this.value = value; } + /** * Validate this data type instance * - * @exception ExecutionException if either attribute has not been - * set + * @exception ExecutionException if either attribute has not been set */ public void validateComponent() throws ExecutionException { if (name == null) { @@ -138,6 +142,7 @@ public abstract class AntBase extends AbstractTask { } } + /** * A simple class to store information about references being passed * @@ -150,42 +155,47 @@ public abstract class AntBase extends AbstractTask { /** The id to be used in the sub-build for this reference */ private String toId; + /** - * Sets the refId of the Reference + * Gets the refId of the Reference * - * @param refId the new refId value + * @return the refId value */ - public void setRefId(String refId) { - this.refId = refId; + public String getRefId() { + return refId; } + /** - * Sets the toId of the Reference + * Gets the toId of the Reference * - * @param toId the new toId value + * @return the toId value */ - public void setToId(String toId) { - this.toId = toId; + public String getToId() { + return toId; } + /** - * Gets the refId of the Reference + * Sets the refId of the Reference * - * @return the refId value + * @param refId the new refId value */ - public String getRefId() { - return refId; + public void setRefId(String refId) { + this.refId = refId; } + /** - * Gets the toId of the Reference + * Sets the toId of the Reference * - * @return the toId value + * @param toId the new toId value */ - public String getToId() { - return toId; + public void setToId(String toId) { + this.toId = toId; } + /** * Validate this data type instance * @@ -200,68 +210,36 @@ public abstract class AntBase extends AbstractTask { } } - /** The name of the target to be evaluated in the sub-build */ - private String targetName; + /** The core's data service for manipulating the properties */ + private DataService dataService; + + /** The core's ExecutionService for running builds and external programs */ + private ExecService execService; + /** - * flag which indicates if all current properties should be passed to - * the subbuild + * flag which indicates if all current properties should be passed to the + * subbuild */ private boolean inheritAll = true; /** - * flag which indicates if all current references should be passed to - * the subbuild + * flag which indicates if all current references should be passed to the + * subbuild */ private boolean inheritRefs = false; /** The properties which will be passed to the sub-build */ private Map properties = new HashMap(); - /** The core's data service for manipulating the properties */ - private DataService dataService; - /** - * Sets the target to be executed in the subbuild - * - * @param targetName the name of the target to build + * The key to the subbuild with which the Ant task can manage the subbuild */ - public void setTarget(String targetName) { - this.targetName = targetName; - } - - /** - * Indicate if all properties should be passed - * - * @param inheritAll true if all properties should be passed - */ - public void setInheritAll(boolean inheritAll) { - this.inheritAll = inheritAll; - } + private Object subbuildKey; - /** - * Indicate if all references are to be passed to the subbuild - * - * @param inheritRefs true if the sub-build should be given all the - * current references - */ - public void setInheritRefs(boolean inheritRefs) { - this.inheritRefs = inheritRefs; - } + /** The name of the target to be evaluated in the sub-build */ + private String targetName; - /** - * Initialise this task - * - * @param context core's context - * @param componentType the component type of this component (i.e its - * defined name in the build file) - * @exception ExecutionException if we can't access the data service - */ - public void init(AntContext context, String componentType) - throws ExecutionException { - super.init(context, componentType); - dataService = (DataService) getCoreService(DataService.class); - } /** * Add a property to be passed to the subbuild @@ -272,6 +250,7 @@ public abstract class AntBase extends AbstractTask { properties.put(property.getName(), property.getValue()); } + /** * Add a reference to be passed * @@ -281,11 +260,13 @@ public abstract class AntBase extends AbstractTask { */ public void addReference(Reference reference) throws ExecutionException { String refId = reference.getRefId(); + if (!dataService.isDataValueSet(refId)) { throw new ExecutionException("RefId \"" + refId + "\" is not set"); } Object value = dataService.getDataValue(refId); String toId = reference.getToId(); + if (toId == null) { toId = refId; } @@ -293,16 +274,35 @@ public abstract class AntBase extends AbstractTask { properties.put(toId, value); } + /** - * Set a property for the subbuild + * Get the core's execution service * - * @param propertyName the property name - * @param propertyValue the value of the property + * @return the core's execution service. */ - protected void setProperty(String propertyName, Object propertyValue) { - properties.put(propertyName, propertyValue); + protected ExecService getExecService() { + return execService; + } + + + /** + * Get the properties to be used with the sub-build + * + * @return the properties the sub-build will start with + */ + protected Map getProperties() { + if (!inheritAll) { + return properties; + } + + // need to combine existing properties with new ones + Map subBuildProperties = dataService.getAllProperties(); + + subBuildProperties.putAll(properties); + return subBuildProperties; } + /** * Get the list of targets to be executed * @@ -310,27 +310,112 @@ public abstract class AntBase extends AbstractTask { */ protected List getTargets() { List targets = new ArrayList(); + if (targetName != null) { targets.add(targetName); } return targets; } + /** - * Get the properties to be used with the sub-build + * Handle error information produced by the task. When a task prints to + * System.err the container may catch this and redirect the content back + * to the task by invoking this method. This method must NOT call + * System.err, directly or indirectly. * - * @return the properties the sub-build will start with + * @param line The line of error info produce by the task */ - protected Map getProperties() { - if (!inheritAll) { - return properties; + public void handleSystemErr(String line) { + if (subbuildKey == null) { + super.handleSystemErr(line); + } else { } + } - // need to combine existing properties with new ones - Map subBuildProperties = dataService.getAllProperties(); - subBuildProperties.putAll(properties); - return subBuildProperties; + + /** + * Handle Output produced by the task. When a task prints to System.out + * the container may catch this and redirect the content back to the task + * by invoking this method. This method must NOT call System.out, directly + * or indirectly. + * + * @param line The line of content produce by the task + */ + public void handleSystemOut(String line) { + if (subbuildKey == null) { + super.handleSystemOut(line); + } else { + } } + + /** + * Initialise this task + * + * @param context core's context + * @param componentType the component type of this component (i.e its + * defined name in the build file) + * @exception ExecutionException if we can't access the data service + */ + public void init(AntContext context, String componentType) + throws ExecutionException { + super.init(context, componentType); + dataService = (DataService) getCoreService(DataService.class); + execService = (ExecService) getCoreService(ExecService.class); + + } + + + /** + * Indicate if all properties should be passed + * + * @param inheritAll true if all properties should be passed + */ + public void setInheritAll(boolean inheritAll) { + this.inheritAll = inheritAll; + } + + + /** + * Indicate if all references are to be passed to the subbuild + * + * @param inheritRefs true if the sub-build should be given all the + * current references + */ + public void setInheritRefs(boolean inheritRefs) { + this.inheritRefs = inheritRefs; + } + + + /** + * Set a property for the subbuild + * + * @param propertyName the property name + * @param propertyValue the value of the property + */ + protected void setProperty(String propertyName, Object propertyValue) { + properties.put(propertyName, propertyValue); + } + + + /** + * Set the key of the subbuild + * + * @param key the key returned by the Ant core for managing the subbuild + */ + protected void setSubBuildKey(Object key) { + this.subbuildKey = key; + } + + + /** + * Sets the target to be executed in the subbuild + * + * @param targetName the name of the target to build + */ + public void setTarget(String targetName) { + this.targetName = targetName; + } } diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntCall.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntCall.java index f74fb6d03..b118cfdf3 100644 --- a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntCall.java +++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntCall.java @@ -69,12 +69,12 @@ public class AntCall extends AntBase { * @exception ExecutionException if the build fails */ public void execute() throws ExecutionException { - ExecService execService - = (ExecService) getCoreService(ExecService.class); setProperty(MagicProperties.BASEDIR, - execService.getBaseDir().getAbsolutePath()); + getExecService().getBaseDir().getAbsolutePath()); - execService.callTarget(getProperties(), getTargets()); + Object key = getExecService().setupBuild(getProperties()); + setSubBuildKey(key); + getExecService().runBuild(key, getTargets()); } /** diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildListenerAdapter.java b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildListenerAdapter.java new file mode 100644 index 000000000..9702d98ff --- /dev/null +++ b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildListenerAdapter.java @@ -0,0 +1,135 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.common.event; + +/** + * Abstract adapter for build listeners which don't want to implement all of + * the BuildListener methods + * + * @author Conor MacNeill + * @created 9 April 2002 + */ +public abstract class BuildListenerAdapter implements BuildListener { + /** + * Fired before any targets are started. + * + * @param event the build event for this notification + */ + public void buildStarted(BuildEvent event) { + } + + + /** + * Fired after the last target has finished. This event will still be + * thrown if an error occured during the build. + * + * @param event the build event for this notification + */ + public void buildFinished(BuildEvent event) { + } + + + + /** + * Fired when a target is started. + * + * @param event the build event for this notification + */ + public void targetStarted(BuildEvent event) { + } + + + + /** + * Fired when a target has finished. This event will still be thrown if an + * error occured during the build. + * + * @param event the build event for this notification + */ + public void targetFinished(BuildEvent event) { + } + + + + /** + * Fired when a task is started. + * + * @param event the build event for this notification + */ + public void taskStarted(BuildEvent event) { + } + + + + /** + * Fired when a task has finished. This event will still be throw if an + * error occured during the build. + * + * @param event the build event for this notification + */ + public void taskFinished(BuildEvent event) { + } + + + + /** + * Fired whenever a message is logged. + * + * @param event the build event for this notification + */ + public void messageLogged(BuildEvent event) { + } + +} + diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/service/ExecService.java b/proposal/mutant/src/java/common/org/apache/ant/common/service/ExecService.java index 376eaff62..a00b96cd9 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/service/ExecService.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/service/ExecService.java @@ -67,37 +67,46 @@ import org.apache.ant.common.util.ExecutionException; */ public interface ExecService { /** - * Run a sub-build. + * Setup a sub-build. * * @param antFile the file containing the XML description of the model - * @param targets A list of targets to be run * @param properties the initiali properties to be used in the build - * @exception ExecutionException if the subbuild cannot be run + * @exception ExecutionException if the subbuild cannot be setup + * @return a key to the build allowing it to be executed and managed */ - void runBuild(File antFile, Map properties, List targets) + Object setupBuild(File antFile, Map properties) throws ExecutionException; /** - * Run a sub-build. + * Setup a sub-build. * * @param model the project model to be used for the build - * @param targets A list of targets to be run * @param properties the initiali properties to be used in the build - * @exception ExecutionException if the subbuild cannot be run + * @exception ExecutionException if the subbuild cannot be setup + * @return a key to the build allowing it to be executed and managed */ - void runBuild(Project model, Map properties, List targets) + Object setupBuild(Project model, Map properties) throws ExecutionException; /** - * Run a sub-build using the current frame's project model + * Setup a sub-build using the current frame's project model * - * @param targets A list of targets to be run * @param properties the initiali properties to be used in the build - * @exception ExecutionException if the subbuild cannot be run + * @exception ExecutionException if the subbuild cannot be setup */ - void callTarget(Map properties, List targets) + Object setupBuild(Map properties) throws ExecutionException; + /** + * Run a build which have been previously setup + * + * @param buildKey the buildKey returned previously when the build was + * setup + * @param targets A list of targets to be run + * @exception ExecutionException if the build cannot be run + */ + void runBuild(Object buildKey, List targets) throws ExecutionException; + /** * execute a task. The task should have already been initialised by * the core @@ -120,5 +129,15 @@ public interface ExecService { * @return the base directory for this execution of Ant */ File getBaseDir(); + + /** + * Handle subbuild output. + * + * @param subbuildKey the core's key for managing the subbuild. + * @param line the content produce by the current thread. + * @param isErr true if this content is from the thread's error stream. + */ + void handleBuildOutput(Object subbuildKey, String line, boolean isErr) + throws ExecutionException; }