| /* |
| * 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 |
| * <http://www.apache.org/>. |
| */ |
| package org.apache.ant.antcore.execution; |
| import java.io.File; |
| import java.net.URL; |
| import java.net.MalformedURLException; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| import java.util.List; |
| import java.util.ArrayList; |
| import org.apache.ant.antcore.config.AntConfig; |
| import org.apache.ant.common.antlib.Task; |
| import org.apache.ant.common.event.BuildListener; |
| import org.apache.ant.common.event.MessageLevel; |
| import org.apache.ant.common.model.BuildElement; |
| import org.apache.ant.common.model.Project; |
| import org.apache.ant.common.model.Target; |
| import org.apache.ant.common.service.ComponentService; |
| import org.apache.ant.common.service.DataService; |
| import org.apache.ant.common.service.EventService; |
| import org.apache.ant.common.service.ExecService; |
| import org.apache.ant.common.service.FileService; |
| import org.apache.ant.common.service.InputService; |
| import org.apache.ant.common.service.MagicProperties; |
| import org.apache.ant.common.util.DemuxOutputReceiver; |
| import org.apache.ant.common.util.ExecutionException; |
| import org.apache.ant.common.util.FileUtils; |
| import org.apache.ant.init.InitConfig; |
| |
| /** |
| * An Frame maintains the state of a project during an execution. The Frame |
| * 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 |
| */ |
| public class Frame implements DemuxOutputReceiver { |
| /** the base dir of the project */ |
| private File baseDir; |
| |
| /** The Project that this execution frame is processing */ |
| private Project project = null; |
| |
| /** The referenced frames corresponding to the referenced projects */ |
| private Map referencedFrames = new HashMap(); |
| |
| /** |
| * The property overrides for the referenced frames. This map is indexed |
| * by the reference names of the frame. Each entry is another Map of |
| * property values indexed by their relative name. |
| */ |
| private Map overrides = new HashMap(); |
| |
| /** |
| * The context of this execution. This contains all data object's created |
| * by tasks that have been executed |
| */ |
| private Map dataValues = new HashMap(); |
| |
| /** |
| * Ant's initialization configuration with information on the location of |
| * Ant and its libraries. |
| */ |
| private InitConfig initConfig; |
| |
| /** BuildEvent support used to fire events and manage listeners */ |
| private BuildEventSupport eventSupport = new BuildEventSupport(); |
| |
| /** |
| * The services map is a map of service interface classes to instances |
| * which provide the service. |
| */ |
| private Map services = new HashMap(); |
| |
| /** |
| * The configuration to be used in this execution of Ant. It is formed |
| * from the system, user and any runtime configs. |
| */ |
| private AntConfig config; |
| |
| /** |
| * The Data Service instance used by the frame for data management |
| */ |
| private DataService dataService; |
| |
| /** The execution file service instance */ |
| private FileService fileService; |
| |
| /** |
| * the Component Manager used to manage the importing of library |
| * components from the Ant libraries |
| */ |
| private ComponentManager componentManager; |
| |
| /** The core's execution Service */ |
| private CoreExecService execService; |
| |
| |
| /** |
| * Create an Execution Frame for the given project |
| * |
| * @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(InitConfig initConfig, |
| AntConfig config) throws ExecutionException { |
| this.config = config; |
| this.initConfig = initConfig; |
| } |
| |
| |
| /** |
| * 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 |
| */ |
| protected String replacePropertyRefs(String value) |
| throws ExecutionException { |
| return dataService.replacePropertyRefs(value); |
| } |
| |
| |
| /** |
| * Sets the Project of the Frame |
| * |
| * @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.clear(); |
| } |
| |
| |
| /** |
| * get the name of the project associated with this frame. |
| * |
| * @return the project's name |
| */ |
| protected String getProjectName() { |
| if (project != null) { |
| return project.getName(); |
| } |
| return null; |
| } |
| |
| |
| /** |
| * 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 |
| */ |
| protected void setDataValue(String name, Object value, boolean mutable) |
| throws ExecutionException { |
| Frame frame = getContainingFrame(name); |
| |
| if (frame == null) { |
| setOverrideProperty(name, value, mutable); |
| return; |
| } |
| |
| if (frame == this) { |
| if (dataValues.containsKey(name) && !mutable) { |
| log("Ignoring oveeride for data value " + name, |
| MessageLevel.MSG_VERBOSE); |
| } else { |
| dataValues.put(name, value); |
| } |
| } else { |
| frame.setDataValue(getNameInFrame(name), value, mutable); |
| } |
| } |
| |
| /** |
| * When a frame has not yet been referenced, this method is used |
| * to set the initial properties for the frame when it is introduced. |
| * |
| * @param name the name of the value |
| * @param value the actual value |
| * @param mutable if true, existing values can be changed |
| * @exception ExecutionException if attempting to override a property in |
| * the current frame. |
| */ |
| private void setOverrideProperty(String name, Object value, |
| boolean mutable) |
| throws ExecutionException { |
| int refIndex = name.indexOf(Project.REF_DELIMITER); |
| if (refIndex == -1) { |
| throw new ExecutionException("Property overrides can only be set" |
| + " for properties in referenced projects - not " |
| + name); |
| } |
| |
| String firstFrameName = name.substring(0, refIndex); |
| |
| String relativeName |
| = name.substring(refIndex + Project.REF_DELIMITER.length()); |
| |
| Map frameOverrides = (Map) overrides.get(firstFrameName); |
| if (frameOverrides == null) { |
| frameOverrides = new HashMap(); |
| overrides.put(firstFrameName, frameOverrides); |
| } |
| |
| if (mutable || !frameOverrides.containsKey(relativeName)) { |
| frameOverrides.put(relativeName, value); |
| } |
| } |
| |
| /** |
| * Get a value which exists in the frame property overrides awaiting |
| * the frame to be introduced. |
| * |
| * @param name the name of the value |
| * @return the value of the property or null if the property does not |
| * exist. |
| * @exception ExecutionException if attempting to get an override in |
| * the current frame. |
| */ |
| private Object getOverrideProperty(String name) throws ExecutionException { |
| int refIndex = name.indexOf(Project.REF_DELIMITER); |
| if (refIndex == -1) { |
| throw new ExecutionException("Property overrides can only be" |
| + " returned for properties in referenced projects - not " |
| + name); |
| } |
| |
| String firstFrameName = name.substring(0, refIndex); |
| |
| String relativeName |
| = name.substring(refIndex + Project.REF_DELIMITER.length()); |
| |
| Map frameOverrides = (Map) overrides.get(firstFrameName); |
| if (frameOverrides == null) { |
| return null; |
| } |
| |
| return frameOverrides.get(relativeName); |
| } |
| |
| /** |
| * Get a value which exists in the frame property overrides awaiting |
| * the frame to be introduced. |
| * |
| * @param name the name of the value |
| * @return the value of the property or null if the property does not |
| * exist. |
| * @exception ExecutionException if attempting to check an override in |
| * the current frame. |
| */ |
| private boolean isOverrideSet(String name) throws ExecutionException { |
| int refIndex = name.indexOf(Project.REF_DELIMITER); |
| if (refIndex == -1) { |
| throw new ExecutionException("Property overrides can only be" |
| + " returned for properties in referenced projects - not " |
| + name); |
| } |
| |
| String firstFrameName = name.substring(0, refIndex); |
| |
| String relativeName |
| = name.substring(refIndex + Project.REF_DELIMITER.length()); |
| |
| Map frameOverrides = (Map) overrides.get(firstFrameName); |
| if (frameOverrides == null) { |
| return false; |
| } |
| |
| return frameOverrides.containsKey(relativeName); |
| } |
| |
| |
| /** |
| * 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 |
| */ |
| protected void setInitialProperties(Map properties) |
| throws ExecutionException { |
| if (properties != null) { |
| addProperties(properties); |
| } |
| |
| // add in system properties |
| addProperties(System.getProperties()); |
| } |
| |
| |
| /** |
| * Set the values of various magic properties |
| * |
| * @exception ExecutionException if the properties cannot be set |
| */ |
| protected void setMagicProperties() throws ExecutionException { |
| URL antHomeURL = initConfig.getAntHome(); |
| String antHomeString = null; |
| |
| if (antHomeURL.getProtocol().equals("file")) { |
| File antHome = new File(antHomeURL.getFile()); |
| |
| antHomeString = antHome.getAbsolutePath(); |
| } else { |
| antHomeString = antHomeURL.toString(); |
| } |
| setDataValue(MagicProperties.ANT_HOME, antHomeString, true); |
| } |
| |
| |
| /** |
| * 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 |
| * found |
| */ |
| protected ImportInfo getReferencedDefinition(String definitionName) |
| throws ExecutionException { |
| Frame containingFrame = getContainingFrame(definitionName); |
| String localName = getNameInFrame(definitionName); |
| |
| if (containingFrame == null) { |
| throw new ExecutionException("There is no project corresponding " |
| + "to the name \"" + definitionName + "\""); |
| } |
| if (containingFrame == this) { |
| return componentManager.getDefinition(localName); |
| } else { |
| return containingFrame.getReferencedDefinition(localName); |
| } |
| } |
| |
| |
| /** |
| * Gets the project model this frame is working with |
| * |
| * @return the project model |
| */ |
| protected Project getProject() { |
| return project; |
| } |
| |
| |
| /** |
| * Get all the properties from the frame and any references frames. This |
| * 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 |
| * name. |
| */ |
| protected Map getAllProperties() { |
| Map allProperties = new HashMap(dataValues); |
| Iterator i = referencedFrames.keySet().iterator(); |
| |
| while (i.hasNext()) { |
| String refName = (String) i.next(); |
| Frame refFrame = getReferencedFrame(refName); |
| Map refProperties = refFrame.getAllProperties(); |
| Iterator j = refProperties.keySet().iterator(); |
| |
| while (j.hasNext()) { |
| String name = (String) j.next(); |
| Object value = refProperties.get(name); |
| |
| allProperties.put(refName + Project.REF_DELIMITER + name, |
| value); |
| } |
| } |
| |
| return allProperties; |
| } |
| |
| |
| /** |
| * Get the Ant initialization configuration for this frame. |
| * |
| * @return Ant's initialization configuration |
| */ |
| protected InitConfig getInitConfig() { |
| return initConfig; |
| } |
| |
| |
| /** |
| * Get the config instance being used by this frame. |
| * |
| * @return the config associated with this frame. |
| */ |
| protected AntConfig getConfig() { |
| return config; |
| } |
| |
| |
| /** |
| * Get the core's implementation of the given service interface. |
| * |
| * @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 |
| * implementatin of the requested interface |
| */ |
| protected Object getCoreService(Class serviceInterfaceClass) |
| throws ExecutionException { |
| Object service = services.get(serviceInterfaceClass); |
| |
| if (service == null) { |
| throw new ExecutionException("No service of interface class " |
| + serviceInterfaceClass); |
| } |
| return service; |
| } |
| |
| |
| /** |
| * Get the EventSupport instance for this frame. This tracks the build |
| * listeners on this frame |
| * |
| * @return the EventSupport instance |
| */ |
| protected BuildEventSupport getEventSupport() { |
| return eventSupport; |
| } |
| |
| |
| /** |
| * Gets the baseDir of the Frame |
| * |
| * @return the baseDir value |
| */ |
| protected File getBaseDir() { |
| return baseDir; |
| } |
| |
| |
| /** |
| * 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. |
| */ |
| protected Frame getReferencedFrame(String referenceName) { |
| return (Frame) referencedFrames.get(referenceName); |
| } |
| |
| |
| /** |
| * Get the frames representing referenced projects. |
| * |
| * @return an iterator which returns the referenced ExeuctionFrames.. |
| */ |
| protected Iterator getReferencedFrames() { |
| return referencedFrames.values().iterator(); |
| } |
| |
| |
| /** |
| * 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 |
| */ |
| protected String getNameInFrame(String fullname) { |
| int index = fullname.lastIndexOf(Project.REF_DELIMITER); |
| |
| if (index == -1) { |
| return fullname; |
| } |
| return fullname.substring(index + Project.REF_DELIMITER.length()); |
| } |
| |
| |
| /** |
| * 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 |
| */ |
| protected Object getDataValue(String name) throws ExecutionException { |
| Frame frame = getContainingFrame(name); |
| |
| if (frame == null) { |
| return getOverrideProperty(name); |
| } |
| if (frame == this) { |
| return dataValues.get(name); |
| } else { |
| return frame.getDataValue(getNameInFrame(name)); |
| } |
| } |
| |
| |
| /** |
| * 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 |
| * does not exist |
| */ |
| protected boolean isDataValueSet(String name) throws ExecutionException { |
| Frame frame = getContainingFrame(name); |
| |
| if (frame == null) { |
| return isOverrideSet(name); |
| } |
| if (frame == this) { |
| return dataValues.containsKey(name); |
| } else { |
| return frame.isDataValueSet(getNameInFrame(name)); |
| } |
| } |
| |
| |
| /** |
| * 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 |
| */ |
| protected Frame getContainingFrame(String elementName) { |
| int index = elementName.lastIndexOf(Project.REF_DELIMITER); |
| |
| if (index == -1) { |
| return this; |
| } |
| |
| Frame currentFrame = this; |
| String relativeName = elementName.substring(0, index); |
| StringTokenizer tokenizer |
| = new StringTokenizer(relativeName, Project.REF_DELIMITER); |
| |
| while (tokenizer.hasMoreTokens()) { |
| String refName = tokenizer.nextToken(); |
| |
| currentFrame = currentFrame.getReferencedFrame(refName); |
| if (currentFrame == null) { |
| return null; |
| } |
| } |
| |
| return currentFrame; |
| } |
| |
| |
| /** |
| * 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. |
| */ |
| protected void addProperties(Map properties) throws ExecutionException { |
| for (Iterator i = properties.keySet().iterator(); i.hasNext();) { |
| String name = (String) i.next(); |
| Object value = properties.get(name); |
| |
| setDataValue(name, value, false); |
| } |
| } |
| |
| /** |
| * Create a project reference. |
| * |
| * @param name the name under which the project will be |
| * referenced. |
| * @param project the project model. |
| * @param initialData the project's initial data load. |
| * @exception ExecutionException if the project cannot be referenced. |
| */ |
| protected void createProjectReference(String name, Project project, |
| Map initialData) |
| throws ExecutionException { |
| Frame referencedFrame = createFrame(project); |
| |
| if (initialData != null) { |
| referencedFrame.setInitialProperties(initialData); |
| } |
| |
| // does the frame have any overrides? |
| Map initialProperties = (Map) overrides.get(name); |
| if (initialProperties != null) { |
| referencedFrame.setInitialProperties(initialProperties); |
| overrides.remove(name); |
| } |
| |
| |
| |
| referencedFrames.put(name, referencedFrame); |
| referencedFrame.initialize(); |
| } |
| |
| /** |
| * 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. |
| */ |
| protected Frame createFrame(Project project) |
| throws ExecutionException { |
| Frame newFrame |
| = new Frame(initConfig, config); |
| |
| newFrame.setProject(project); |
| for (Iterator j = eventSupport.getListeners(); j.hasNext();) { |
| BuildListener listener = (BuildListener) j.next(); |
| |
| newFrame.addBuildListener(listener); |
| } |
| |
| return newFrame; |
| } |
| |
| |
| /** |
| * Log a message as a build event |
| * |
| * @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); |
| } |
| |
| |
| /** |
| * Add a build listener to this execution frame |
| * |
| * @param listener the listener to be added to the frame |
| */ |
| protected void addBuildListener(BuildListener listener) { |
| for (Iterator i = getReferencedFrames(); i.hasNext();) { |
| Frame referencedFrame = (Frame) i.next(); |
| |
| referencedFrame.addBuildListener(listener); |
| } |
| eventSupport.addBuildListener(listener); |
| } |
| |
| |
| /** |
| * Remove a build listener from the execution |
| * |
| * @param listener the listener to be removed |
| */ |
| protected void removeBuildListener(BuildListener listener) { |
| for (Iterator i = getReferencedFrames(); i.hasNext();) { |
| Frame subFrame = (Frame) i.next(); |
| |
| subFrame.removeBuildListener(listener); |
| } |
| eventSupport.removeBuildListener(listener); |
| } |
| |
| |
| /** |
| * 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 |
| */ |
| protected void runBuild(List targets) throws ExecutionException { |
| initialize(); |
| if (targets.isEmpty()) { |
| // we just execute the default target if any |
| String defaultTarget = project.getDefaultTarget(); |
| |
| if (defaultTarget != null) { |
| log("Executing default target: " + defaultTarget, |
| MessageLevel.MSG_DEBUG); |
| executeTarget(defaultTarget); |
| } |
| } else { |
| for (Iterator i = targets.iterator(); i.hasNext();) { |
| String targetName = (String) i.next(); |
| |
| log("Executing target: " + targetName, MessageLevel.MSG_DEBUG); |
| executeTarget(targetName); |
| } |
| } |
| } |
| |
| |
| |
| /** |
| * Given a fully qualified target name, this method returns the fully |
| * qualified name of the project |
| * |
| * @param fullTargetName the full qualified target name |
| * @return the full name of the containing project |
| */ |
| private String getFullProjectName(String fullTargetName) { |
| int index = fullTargetName.lastIndexOf(Project.REF_DELIMITER); |
| if (index == -1) { |
| return null; |
| } |
| |
| return fullTargetName.substring(0, index); |
| } |
| |
| /** |
| * Flatten the dependencies to the given target |
| * |
| * @param flattenedList the List of targets that must be executed before |
| * the given target |
| * @param fullTargetName the fully qualified name of the target |
| * @exception ExecutionException if the given target does not exist in the |
| * project hierarchy |
| */ |
| private void flattenDependency(List flattenedList, String fullTargetName) |
| throws ExecutionException { |
| if (flattenedList.contains(fullTargetName)) { |
| return; |
| } |
| String fullProjectName = getFullProjectName(fullTargetName); |
| Frame frame = getContainingFrame(fullTargetName); |
| String localTargetName = getNameInFrame(fullTargetName); |
| Target target = frame.getProject().getTarget(localTargetName); |
| if (target == null) { |
| throw new ExecutionException("Target " + fullTargetName |
| + " does not exist"); |
| } |
| for (Iterator i = target.getDependencies(); i.hasNext();) { |
| String localDependencyName = (String) i.next(); |
| String fullDependencyName = localDependencyName; |
| if (fullProjectName != null) { |
| fullDependencyName = fullProjectName + Project.REF_DELIMITER |
| + localDependencyName; |
| } |
| flattenDependency(flattenedList, fullDependencyName); |
| if (!flattenedList.contains(fullDependencyName)) { |
| flattenedList.add(fullDependencyName); |
| } |
| } |
| } |
| |
| /** |
| * get the list of dependent targets which must be evaluated for the |
| * given target. |
| * |
| * @param fullTargetName the full name (in reference space) of the |
| * target |
| * @return the flattened list of targets |
| * @exception ExecutionException if the given target could not be found |
| */ |
| protected List getTargetDependencies(String fullTargetName) |
| throws ExecutionException { |
| List flattenedList = new ArrayList(); |
| flattenDependency(flattenedList, fullTargetName); |
| flattenedList.add(fullTargetName); |
| return flattenedList; |
| } |
| |
| |
| /** |
| * 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 |
| */ |
| protected void executeTarget(String targetName) throws ExecutionException { |
| |
| // to execute a target we must determine its dependencies and |
| // execute them in order. |
| |
| // firstly build a list of fully qualified target names to execute. |
| List dependencyOrder = getTargetDependencies(targetName); |
| |
| for (Iterator i = dependencyOrder.iterator(); i.hasNext();) { |
| String fullTargetName = (String) i.next(); |
| Frame frame = getContainingFrame(fullTargetName); |
| String localTargetName = getNameInFrame(fullTargetName); |
| |
| frame.executeTargetTasks(localTargetName); |
| } |
| } |
| |
| |
| /** |
| * 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 |
| * executing tasks |
| */ |
| protected void executeTasks(Iterator taskIterator) |
| throws ExecutionException { |
| while (taskIterator.hasNext()) { |
| BuildElement model = (BuildElement) taskIterator.next(); |
| |
| // what sort of element is this. |
| try { |
| Object component = componentManager.createComponent(model); |
| |
| if (component instanceof Task) { |
| execService.executeTask((Task) component); |
| } else { |
| String typeId |
| = model.getAspectValue(Constants.ANT_ASPECT, "id"); |
| |
| if (typeId != null) { |
| setDataValue(typeId, component, true); |
| } |
| } |
| } catch (ExecutionException e) { |
| e.setLocation(model.getLocation(), false); |
| throw e; |
| } catch (RuntimeException e) { |
| ExecutionException ee = |
| new ExecutionException(e, model.getLocation()); |
| |
| throw ee; |
| } |
| } |
| |
| } |
| |
| |
| /** |
| * 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 |
| */ |
| protected void executeTargetTasks(String targetName) |
| throws ExecutionException { |
| Throwable failureCause = null; |
| Target target = project.getTarget(targetName); |
| String ifCondition = target.getIfCondition(); |
| String unlessCondition = target.getUnlessCondition(); |
| |
| if (ifCondition != null) { |
| ifCondition = dataService.replacePropertyRefs(ifCondition.trim()); |
| if (!isDataValueSet(ifCondition)) { |
| return; |
| } |
| } |
| |
| if (unlessCondition != null) { |
| unlessCondition |
| = dataService.replacePropertyRefs(unlessCondition.trim()); |
| if (isDataValueSet(unlessCondition)) { |
| return; |
| } |
| } |
| |
| try { |
| Iterator taskIterator = target.getTasks(); |
| |
| eventSupport.fireTargetStarted(target); |
| executeTasks(taskIterator); |
| } catch (ExecutionException e) { |
| e.setLocation(target.getLocation(), false); |
| failureCause = e; |
| throw e; |
| } catch (RuntimeException e) { |
| ExecutionException ee = |
| new ExecutionException(e, target.getLocation()); |
| |
| failureCause = ee; |
| throw ee; |
| } finally { |
| eventSupport.fireTargetFinished(target, failureCause); |
| } |
| } |
| |
| |
| /** |
| * Initialize the frame by executing the project level tasks if any |
| * |
| * @exception ExecutionException if the top level tasks of the frame |
| * failed |
| */ |
| protected void initialize() throws ExecutionException { |
| configureServices(); |
| setMagicProperties(); |
| determineBaseDir(); |
| |
| try { |
| // load system ant lib |
| URL systemLibs |
| = new URL(initConfig.getLibraryURL(), "syslibs/"); |
| componentManager.loadLib(systemLibs.toString(), true, true); |
| |
| // execute any config tasks |
| executeTasks(config.getTasks()); |
| |
| // now load other system libraries |
| URL antLibs = new URL(initConfig.getLibraryURL(), "antlibs/"); |
| componentManager.loadLib(antLibs.toString(), false, true); |
| |
| executeTasks(project.getTasks()); |
| } catch (MalformedURLException e) { |
| throw new ExecutionException("Unable to initialize antlibs", e); |
| } |
| } |
| |
| |
| /** |
| * Determine the base directory for each frame in the frame hierarchy |
| * |
| * @exception ExecutionException if the base directories cannot be |
| * determined |
| */ |
| private void determineBaseDir() throws ExecutionException { |
| if (isDataValueSet(MagicProperties.BASEDIR)) { |
| baseDir |
| = new File(getDataValue(MagicProperties.BASEDIR).toString()); |
| } else { |
| URL projectURL = project.getSourceURL(); |
| |
| if (projectURL.getProtocol().equals("file")) { |
| File projectFile = new File(projectURL.getFile()); |
| File projectFileParent = projectFile.getParentFile(); |
| String base = project.getBase(); |
| |
| if (base == null) { |
| baseDir = projectFileParent; |
| } else { |
| FileUtils fileUtils = FileUtils.newFileUtils(); |
| |
| baseDir = fileUtils.resolveFile(projectFileParent, base); |
| } |
| } else { |
| baseDir = new File("."); |
| } |
| } |
| setDataValue(MagicProperties.BASEDIR, baseDir.getAbsolutePath(), true); |
| } |
| |
| |
| /** |
| * Configure the services that the frame makes available to its library |
| * components |
| */ |
| private void configureServices() { |
| // create services and make them available in our services map |
| fileService = new CoreFileService(this); |
| componentManager = new ComponentManager(this); |
| dataService = new CoreDataService(this, |
| config.isUnsetPropertiesAllowed()); |
| execService = new CoreExecService(this); |
| |
| services.put(FileService.class, fileService); |
| services.put(ComponentService.class, componentManager); |
| services.put(DataService.class, dataService); |
| services.put(EventService.class, new CoreEventService(this)); |
| services.put(ExecService.class, execService); |
| services.put(InputService.class, new CoreInputService(this)); |
| } |
| |
| |
| /** |
| * Handle the content from a single thread. This method will be called by |
| * 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. |
| */ |
| public void threadOutput(String line, boolean isErr) { |
| eventSupport.threadOutput(line, isErr); |
| } |
| } |
| |
| |