git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272494 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -198,14 +198,51 @@ public class CoreExecService implements ExecService { | |||
| } | |||
| /** | |||
| * Parse an XML file into a build model. | |||
| * | |||
| * @param xmlBuildFile The file containing the XML build description. | |||
| * @return A Project model for the build. | |||
| * @exception ExecutionException if the build cannot be parsed | |||
| */ | |||
| public Project parseXMLBuildFile(File xmlBuildFile) | |||
| throws ExecutionException { | |||
| try { | |||
| // Parse the build file into a project | |||
| XMLProjectParser parser = new XMLProjectParser(); | |||
| return parser.parseBuildFile(InitUtils.getFileURL(xmlBuildFile)); | |||
| } catch (MalformedURLException e) { | |||
| throw new ExecutionException(e); | |||
| } catch (XMLParseException e) { | |||
| throw new ExecutionException(e); | |||
| } | |||
| } | |||
| /** | |||
| * Create a project reference. | |||
| * | |||
| * @param referenceName the name under which the project will be | |||
| * referenced. | |||
| * @param model the project model. | |||
| * @exception ExecutionException if the project cannot be referenced. | |||
| */ | |||
| public void createProjectReference(String referenceName, Project model) | |||
| throws ExecutionException { | |||
| frame.createProjectReference(referenceName, model); | |||
| } | |||
| /** | |||
| * 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 | |||
| * @param model XXX Description of the Parameter | |||
| * @return Description of the Return Value | |||
| * @exception ExecutionException if the subbuild cannot be run | |||
| */ | |||
| /* | |||
| public Object setupBuild(File antFile, Map properties) | |||
| throws ExecutionException { | |||
| try { | |||
| @@ -213,7 +250,6 @@ public class CoreExecService implements ExecService { | |||
| XMLProjectParser parser = new XMLProjectParser(); | |||
| Project project | |||
| = parser.parseBuildFile(InitUtils.getFileURL(antFile)); | |||
| return setupBuild(project, properties); | |||
| } catch (MalformedURLException e) { | |||
| throw new ExecutionException(e); | |||
| @@ -221,8 +257,7 @@ public class CoreExecService implements ExecService { | |||
| throw new ExecutionException(e); | |||
| } | |||
| } | |||
| */ | |||
| /** | |||
| * Setup a sub-build. | |||
| * | |||
| @@ -56,9 +56,10 @@ import java.io.File; | |||
| import java.net.URL; | |||
| import java.util.HashMap; | |||
| import java.util.Iterator; | |||
| import java.util.List; | |||
| 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; | |||
| @@ -72,7 +73,6 @@ 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.MagicProperties; | |||
| import org.apache.ant.common.util.ConfigException; | |||
| import org.apache.ant.common.util.DemuxOutputReceiver; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| import org.apache.ant.common.util.FileUtils; | |||
| @@ -173,7 +173,8 @@ public class Frame implements DemuxOutputReceiver { | |||
| * @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 { | |||
| protected String replacePropertyRefs(String value) | |||
| throws ExecutionException { | |||
| return dataService.replacePropertyRefs(value); | |||
| } | |||
| @@ -189,15 +190,6 @@ public class Frame implements DemuxOutputReceiver { | |||
| this.project = project; | |||
| referencedFrames = new HashMap(); | |||
| for (Iterator i = project.getReferencedProjectNames(); i.hasNext();) { | |||
| String referenceName = (String) i.next(); | |||
| Project referencedProject | |||
| = project.getReferencedProject(referenceName); | |||
| Frame referencedFrame = createFrame(referencedProject); | |||
| referencedFrames.put(referenceName, referencedFrame); | |||
| } | |||
| configureServices(); | |||
| componentManager.setStandardLibraries(standardLibs); | |||
| setMagicProperties(); | |||
| @@ -209,7 +201,7 @@ public class Frame implements DemuxOutputReceiver { | |||
| * | |||
| * @return the project's name | |||
| */ | |||
| public String getProjectName() { | |||
| protected String getProjectName() { | |||
| if (project != null) { | |||
| return project.getName(); | |||
| } | |||
| @@ -547,6 +539,20 @@ public class Frame implements DemuxOutputReceiver { | |||
| } | |||
| } | |||
| /** | |||
| * Create a project reference. | |||
| * | |||
| * @param name the name under which the project will be | |||
| * referenced. | |||
| * @param project the project model. | |||
| * @exception ExecutionException if the project cannot be referenced. | |||
| */ | |||
| protected void createProjectReference(String name, Project project) | |||
| throws ExecutionException { | |||
| Frame referencedFrame = createFrame(project); | |||
| referencedFrames.put(name, referencedFrame); | |||
| referencedFrame.initialize(); | |||
| } | |||
| /** | |||
| * Create a new frame for a given project | |||
| @@ -618,8 +624,6 @@ public class Frame implements DemuxOutputReceiver { | |||
| * @exception ExecutionException if there is a problem in the build | |||
| */ | |||
| protected void runBuild(List targets) throws ExecutionException { | |||
| determineBaseDirs(); | |||
| initialize(); | |||
| if (targets.isEmpty()) { | |||
| // we just execute the default target if any | |||
| @@ -641,6 +645,77 @@ public class Frame implements DemuxOutputReceiver { | |||
| } | |||
| /** | |||
| * 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 | |||
| * | |||
| @@ -649,22 +724,19 @@ public class Frame implements DemuxOutputReceiver { | |||
| * of the target | |||
| */ | |||
| protected void executeTarget(String targetName) throws ExecutionException { | |||
| // to execute a target we must determine its dependencies and | |||
| // execute them in order. | |||
| try { | |||
| // firstly build a list of fully qualified target names to execute. | |||
| List dependencyOrder = project.getTargetDependencies(targetName); | |||
| // 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); | |||
| for (Iterator i = dependencyOrder.iterator(); i.hasNext();) { | |||
| String fullTargetName = (String) i.next(); | |||
| Frame frame = getContainingFrame(fullTargetName); | |||
| String localTargetName = getNameInFrame(fullTargetName); | |||
| frame.executeTargetTasks(localTargetName); | |||
| } | |||
| } catch (ConfigException e) { | |||
| throw new ExecutionException(e); | |||
| frame.executeTargetTasks(localTargetName); | |||
| } | |||
| } | |||
| @@ -767,11 +839,7 @@ public class Frame implements DemuxOutputReceiver { | |||
| * failed | |||
| */ | |||
| protected void initialize() throws ExecutionException { | |||
| for (Iterator i = getReferencedFrames(); i.hasNext();) { | |||
| Frame referencedFrame = (Frame) i.next(); | |||
| referencedFrame.initialize(); | |||
| } | |||
| determineBaseDir(); | |||
| Iterator taskIterator = project.getTasks(); | |||
| @@ -785,7 +853,7 @@ public class Frame implements DemuxOutputReceiver { | |||
| * @exception ExecutionException if the base directories cannot be | |||
| * determined | |||
| */ | |||
| private void determineBaseDirs() throws ExecutionException { | |||
| private void determineBaseDir() throws ExecutionException { | |||
| if (isDataValueSet(MagicProperties.BASEDIR)) { | |||
| baseDir | |||
| = new File(getDataValue(MagicProperties.BASEDIR).toString()); | |||
| @@ -809,12 +877,6 @@ public class Frame implements DemuxOutputReceiver { | |||
| } | |||
| } | |||
| setDataValue(MagicProperties.BASEDIR, baseDir.getAbsolutePath(), true); | |||
| for (Iterator i = getReferencedFrames(); i.hasNext();) { | |||
| Frame refFrame = (Frame) i.next(); | |||
| refFrame.determineBaseDirs(); | |||
| } | |||
| } | |||
| @@ -158,18 +158,7 @@ public class ProjectHandler extends ModelElementHandler { | |||
| Attributes attributes) | |||
| throws SAXParseException { | |||
| if (qualifiedName.equals(REF_ELEMENT)) { | |||
| RefHandler refHandler = new RefHandler(); | |||
| refHandler.start(getParseContext(), getXMLReader(), this, | |||
| getLocator(), attributes, getElementSource(), | |||
| qualifiedName); | |||
| try { | |||
| project.referenceProject(refHandler.getRefName(), | |||
| refHandler.getReferencedProject()); | |||
| } catch (ModelException e) { | |||
| throw new SAXParseException(e.getMessage(), getLocator(), e); | |||
| } | |||
| } else if (qualifiedName.equals(INCLUDE_ELEMENT)) { | |||
| if (qualifiedName.equals(INCLUDE_ELEMENT)) { | |||
| IncludeHandler includeHandler = new IncludeHandler(project); | |||
| includeHandler.start(getParseContext(), getXMLReader(), | |||
| this, getLocator(), attributes, getElementSource(), | |||
| @@ -193,7 +182,7 @@ public class ProjectHandler extends ModelElementHandler { | |||
| project.addTask(buildElementHandler.getBuildElement()); | |||
| } else { | |||
| // ignore namespaced elements | |||
| throw new SAXParseException("Only the \"ant\" namespace is " | |||
| throw new SAXParseException("namespace support is not " | |||
| + "currently recognized (" + qualifiedName + ")", getLocator()); | |||
| } | |||
| } | |||
| @@ -1,161 +0,0 @@ | |||
| /* | |||
| * 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.modelparser; | |||
| import java.net.MalformedURLException; | |||
| import java.net.URL; | |||
| import org.apache.ant.common.model.Project; | |||
| import org.apache.ant.antcore.xml.ElementHandler; | |||
| import org.apache.ant.antcore.xml.XMLParseException; | |||
| import org.xml.sax.SAXParseException; | |||
| /** | |||
| * The Ref handler handles the reference of one project to another. The | |||
| * project to be references is parsed with a new parser and then added to | |||
| * the current project under the given alias | |||
| * | |||
| * @author Conor MacNeill | |||
| * @created 10 January 2002 | |||
| */ | |||
| public class RefHandler extends ElementHandler { | |||
| /** The attribute used to name the ref. */ | |||
| public static final String NAME_ATTR = "name"; | |||
| /** The attribute name used to locate the project to be referenced. */ | |||
| public static final String SYSTEMID_ATTR = "project"; | |||
| /** The project that has been referenced. */ | |||
| private Project referencedProject; | |||
| /** | |||
| * Get the project referenced. | |||
| * | |||
| * @return an referenced Project. | |||
| */ | |||
| public Project getReferencedProject() { | |||
| return referencedProject; | |||
| } | |||
| /** | |||
| * Get the name under which the project is referenced. | |||
| * | |||
| * @return the ref name of the project | |||
| */ | |||
| public String getRefName() { | |||
| return getAttribute(NAME_ATTR); | |||
| } | |||
| /** | |||
| * Create an ref handler to reference a project. | |||
| * | |||
| * @param elementName the name of the ref element | |||
| * @exception SAXParseException if the ref element could not be parsed | |||
| */ | |||
| public void processElement(String elementName) | |||
| throws SAXParseException { | |||
| String refName = getAttribute(NAME_ATTR); | |||
| if (refName == null) { | |||
| throw new SAXParseException("Attribute " + NAME_ATTR + | |||
| " is required in a <ref> element", getLocator()); | |||
| } | |||
| String projectSystemId = getAttribute(SYSTEMID_ATTR); | |||
| if (projectSystemId == null) { | |||
| throw new SAXParseException("Attribute " + SYSTEMID_ATTR + | |||
| " is required in a <ref> element", getLocator()); | |||
| } | |||
| // create a new parser to read this project relative to the | |||
| // project's URI | |||
| try { | |||
| URL refURL = new URL(getElementSource(), projectSystemId); | |||
| ProjectHandler referencedProjectHandler = new ProjectHandler(); | |||
| getParseContext().parse(refURL, "project", | |||
| referencedProjectHandler); | |||
| referencedProject = referencedProjectHandler.getProject(); | |||
| } catch (XMLParseException e) { | |||
| throw new SAXParseException("Error parsing referenced project " | |||
| + projectSystemId + ": " + e.getMessage(), getLocator(), e); | |||
| } catch (NoProjectReadException e) { | |||
| throw new SAXParseException("No project found in the reference: " | |||
| + projectSystemId, getLocator(), e); | |||
| } catch (MalformedURLException e) { | |||
| throw new SAXParseException("Unable to reference project " | |||
| + projectSystemId + ": " + e.getMessage(), | |||
| getLocator(), e); | |||
| } | |||
| } | |||
| /** | |||
| * Validate that the given attribute and value are valid. | |||
| * | |||
| * @param attributeName The name of the attributes | |||
| * @param attributeValue The value of the attributes | |||
| * @exception SAXParseException if the attribute is not allowed on the | |||
| * element. | |||
| */ | |||
| protected void validateAttribute(String attributeName, | |||
| String attributeValue) | |||
| throws SAXParseException { | |||
| if (!attributeName.equals(SYSTEMID_ATTR) && | |||
| !attributeName.equals(NAME_ATTR)) { | |||
| throwInvalidAttribute(attributeName); | |||
| } | |||
| } | |||
| } | |||
| @@ -7,6 +7,8 @@ | |||
| <taskdef name="ant" classname="org.apache.ant.antlib.system.Ant"/> | |||
| <taskdef name="antcall" classname="org.apache.ant.antlib.system.AntCall"/> | |||
| <taskdef name="ref" classname="org.apache.ant.antlib.system.Ref"/> | |||
| <taskdef name="parallel" classname="org.apache.ant.antlib.system.Parallel"/> | |||
| <taskdef name="sequential" classname="org.apache.ant.antlib.system.Sequential"/> | |||
| @@ -53,8 +53,10 @@ | |||
| */ | |||
| package org.apache.ant.antlib.system; | |||
| import java.io.File; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| import org.apache.ant.common.model.Project; | |||
| import org.apache.ant.common.service.ExecService; | |||
| import org.apache.ant.common.service.MagicProperties; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| import org.apache.ant.common.util.FileUtils; | |||
| /** | |||
| @@ -71,6 +73,7 @@ public class Ant extends AntBase { | |||
| /** File to capture any output */ | |||
| private File outputFile; | |||
| /** | |||
| * sets the file containing the XML representation model to build | |||
| * | |||
| @@ -80,6 +83,7 @@ public class Ant extends AntBase { | |||
| this.antFileName = antFileName; | |||
| } | |||
| /** | |||
| * Set the base directory for the execution of the build | |||
| * | |||
| @@ -89,6 +93,7 @@ public class Ant extends AntBase { | |||
| this.baseDir = baseDir; | |||
| } | |||
| /** | |||
| * The output file for capturing the build output | |||
| * | |||
| @@ -98,6 +103,7 @@ public class Ant extends AntBase { | |||
| this.outputFile = outputFile; | |||
| } | |||
| /** | |||
| * Run the sub-build | |||
| * | |||
| @@ -107,23 +113,27 @@ public class Ant extends AntBase { | |||
| if (baseDir == null) { | |||
| baseDir = getExecService().getBaseDir(); | |||
| } | |||
| File antFile = null; | |||
| if (antFileName == null) { | |||
| antFile = new File(baseDir, "build.ant"); | |||
| if (!antFile.exists()) { | |||
| antFile = new File(baseDir, "build.xml"); | |||
| } | |||
| } else { | |||
| antFile | |||
| = FileUtils.newFileUtils().resolveFile(baseDir, antFileName); | |||
| antFile | |||
| = FileUtils.newFileUtils().resolveFile(baseDir, antFileName); | |||
| } | |||
| setProperty(MagicProperties.BASEDIR, baseDir.getAbsolutePath()); | |||
| Object key = getExecService().setupBuild(antFile, getProperties()); | |||
| ExecService execService = getExecService(); | |||
| Project model = execService.parseXMLBuildFile(antFile); | |||
| Object key = execService.setupBuild(model, getProperties()); | |||
| setSubBuildKey(key); | |||
| getExecService().runBuild(key, getTargets()); | |||
| execService.runBuild(key, getTargets()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,127 @@ | |||
| /* | |||
| * 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.antlib.system; | |||
| import java.io.File; | |||
| import org.apache.ant.common.antlib.AbstractTask; | |||
| import org.apache.ant.common.antlib.AntContext; | |||
| import org.apache.ant.common.model.Project; | |||
| import org.apache.ant.common.service.ExecService; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| /** | |||
| * A Task to create a project reference. | |||
| * | |||
| * @author Conor MacNeill | |||
| * @created 17 April 2002 | |||
| */ | |||
| public class Ref extends AbstractTask { | |||
| /** The project file containing the project to be referenced. */ | |||
| private File projectFile; | |||
| /** THe name under which this project is to be referenced. */ | |||
| private String name; | |||
| /** The core's ExecutionService for running builds and external programs */ | |||
| private ExecService execService; | |||
| /** | |||
| * 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); | |||
| execService = (ExecService) getCoreService(ExecService.class); | |||
| } | |||
| /** | |||
| * Sets the file containing the XML representation model of the referenced | |||
| * project | |||
| * | |||
| * @param projectFile the file to build | |||
| */ | |||
| public void setProject(File projectFile) { | |||
| this.projectFile = projectFile; | |||
| } | |||
| /** | |||
| * Set the name under which the project will be referenced | |||
| * | |||
| * @param name the reference label | |||
| */ | |||
| public void setName(String name) { | |||
| this.name = name; | |||
| } | |||
| /** | |||
| * Create the project reference | |||
| * | |||
| * @exception ExecutionException if the project cannot be referenced. | |||
| */ | |||
| public void execute() throws ExecutionException { | |||
| Project model = execService.parseXMLBuildFile(projectFile); | |||
| execService.createProjectReference(name, model); | |||
| } | |||
| } | |||
| @@ -202,7 +202,7 @@ public class BuildHelper { | |||
| args[index++] = "-classpath"; | |||
| args[index++] = path; | |||
| } | |||
| for (Iterator i = javaFiles.iterator(); i.hasNext(); ) { | |||
| for (Iterator i = javaFiles.iterator(); i.hasNext();) { | |||
| args[index++] = ((File) i.next()).getPath(); | |||
| } | |||
| @@ -60,10 +60,8 @@ import java.util.Iterator; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.Set; | |||
| import java.util.StringTokenizer; | |||
| import org.apache.ant.common.util.CircularDependencyChecker; | |||
| import org.apache.ant.common.util.CircularDependencyException; | |||
| import org.apache.ant.common.util.ConfigException; | |||
| import org.apache.ant.common.util.Location; | |||
| /** | |||
| @@ -98,25 +96,17 @@ public class Project extends ModelElement { | |||
| /** | |||
| * These are the targets which belong to the project. They will have | |||
| * interdependencies which are used to determine which targets need to | |||
| * be executed before a given target. | |||
| * interdependencies which are used to determine which targets need to be | |||
| * executed before a given target. | |||
| */ | |||
| private Map targets = new HashMap(); | |||
| /** | |||
| * The global tasks for this project. These are the tasks that will get | |||
| * executed whenever an execution context is associated with this | |||
| * project. | |||
| * executed whenever an execution context is associated with this project. | |||
| */ | |||
| private List tasks = new ArrayList(); | |||
| /** | |||
| * The projects referenced into this project. Each referenced project is | |||
| * given a name which is used to identify access to that project's | |||
| * elements. | |||
| */ | |||
| private Map referencedProjects = new HashMap(); | |||
| /** The URL where the project is defined. */ | |||
| private URL sourceURL; | |||
| @@ -192,6 +182,7 @@ public class Project extends ModelElement { | |||
| return base; | |||
| } | |||
| /** | |||
| * Get the name of the project element | |||
| * | |||
| @@ -200,7 +191,8 @@ public class Project extends ModelElement { | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| /** | |||
| * Get the targets in this project. | |||
| * | |||
| @@ -223,29 +215,6 @@ public class Project extends ModelElement { | |||
| } | |||
| /** | |||
| * Get the names of the referenced projects. | |||
| * | |||
| * @return an iterator which returns the name sof the referenced | |||
| * projects. | |||
| */ | |||
| public Iterator getReferencedProjectNames() { | |||
| return referencedProjects.keySet().iterator(); | |||
| } | |||
| /** | |||
| * Get a referenced project by name | |||
| * | |||
| * @param alias the name under which the project was referenced. | |||
| * @return the project asscociated with the given reference alias or | |||
| * null if there is no such project. | |||
| */ | |||
| public Project getReferencedProject(String alias) { | |||
| return (Project) referencedProjects.get(alias); | |||
| } | |||
| /** | |||
| * Get the initialisation tasks for this project | |||
| * | |||
| @@ -255,85 +224,6 @@ public class Project extends ModelElement { | |||
| return tasks.iterator(); | |||
| } | |||
| /** | |||
| * Get a target by its reference name - references may span multiple | |||
| * references. | |||
| * | |||
| * @param fullTargetName The name of the target relative to this project | |||
| * @return the Target object with the given name | |||
| * @exception ModelException if the given target does not exist in this | |||
| * project | |||
| */ | |||
| public Target getRefTarget(String fullTargetName) throws ModelException { | |||
| Project containingProject = getRefProject(fullTargetName); | |||
| if (containingProject == null) { | |||
| throw new ModelException("The target name \"" + fullTargetName | |||
| + "\" does not exist in this project"); | |||
| } | |||
| if (containingProject == this) { | |||
| return getTarget(fullTargetName); | |||
| } | |||
| int index = fullTargetName.lastIndexOf(REF_DELIMITER); | |||
| String targetName | |||
| = fullTargetName.substring(index + REF_DELIMITER.length()); | |||
| return containingProject.getTarget(targetName); | |||
| } | |||
| /** | |||
| * Get the project which directly contains the target specified by its | |||
| * full name. | |||
| * | |||
| * @param fullTargetName the full name of the target for which the | |||
| * containing project is required. | |||
| * @return The RefProject value | |||
| */ | |||
| public Project getRefProject(String fullTargetName) { | |||
| int index = fullTargetName.lastIndexOf(REF_DELIMITER); | |||
| if (index == -1) { | |||
| return this; | |||
| } | |||
| Project currentProject = this; | |||
| String relativeName = fullTargetName.substring(0, index); | |||
| StringTokenizer tokenizer | |||
| = new StringTokenizer(relativeName, REF_DELIMITER); | |||
| while (tokenizer.hasMoreTokens()) { | |||
| String refName = tokenizer.nextToken(); | |||
| currentProject = currentProject.getReferencedProject(refName); | |||
| if (currentProject == null) { | |||
| return null; | |||
| } | |||
| } | |||
| return currentProject; | |||
| } | |||
| /** | |||
| * 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 ConfigException if the given target could not be found | |||
| */ | |||
| public List getTargetDependencies(String fullTargetName) | |||
| throws ConfigException { | |||
| try { | |||
| List flattenedList = new ArrayList(); | |||
| flattenDependency(flattenedList, fullTargetName); | |||
| flattenedList.add(fullTargetName); | |||
| return flattenedList; | |||
| } catch (ConfigException e) { | |||
| throw new ConfigException(fullTargetName | |||
| + " does not exist in project"); | |||
| } | |||
| } | |||
| /** | |||
| * Add a target to the project. | |||
| * | |||
| @@ -361,47 +251,44 @@ public class Project extends ModelElement { | |||
| tasks.add(task); | |||
| } | |||
| /** | |||
| * Reference a project using the given name. | |||
| * | |||
| * @param referenceName the name under which the project will be | |||
| * referenced. | |||
| * @param project the referenced project. | |||
| * @throws ModelException if an existing project has already been | |||
| * referenced with that name. | |||
| */ | |||
| public void referenceProject(String referenceName, Project project) | |||
| throws ModelException { | |||
| if (referencedProjects.containsKey(referenceName)) { | |||
| throw new ModelException("A project has already been " | |||
| + "introduced with name '" + referenceName + "'"); | |||
| } | |||
| referencedProjects.put(referenceName, project); | |||
| } | |||
| /** | |||
| * Validate this project | |||
| * | |||
| * @exception ModelException if the project is not valid | |||
| */ | |||
| public void validate() throws ModelException { | |||
| validate(null); | |||
| // check whether all of dependencies for our targets | |||
| // exist in the model | |||
| // visited contains the targets we have already visited and verified | |||
| Set visited = new HashSet(); | |||
| // checker records the targets we are currently visiting | |||
| CircularDependencyChecker checker | |||
| = new CircularDependencyChecker("checking target dependencies"); | |||
| // dependency order is purely recorded for debug purposes | |||
| List dependencyOrder = new ArrayList(); | |||
| for (Iterator i = getTargets(); i.hasNext();) { | |||
| Target target = (Target) i.next(); | |||
| target.validate(); | |||
| fillinDependencyOrder(target, dependencyOrder, | |||
| visited, checker); | |||
| } | |||
| } | |||
| /** | |||
| * Determine target dependency order within this porject and verify that | |||
| * references to targets in other projects are valid | |||
| * Determine target dependency order within this project. | |||
| * | |||
| * @param globalName The global name of this project | |||
| * @param target The target being examined | |||
| * @param dependencyOrder The dependency order of targets | |||
| * @param visited Set of targets in this project already visited. | |||
| * @param checker A circular dependency checker | |||
| * @exception ModelException if the dependencies of the project's | |||
| * targets are not valid. | |||
| * @exception ModelException if the dependencies of the project's targets | |||
| * are not valid. | |||
| */ | |||
| public void fillinDependencyOrder(String globalName, Target target, | |||
| public void fillinDependencyOrder(Target target, | |||
| List dependencyOrder, Set visited, | |||
| CircularDependencyChecker checker) | |||
| throws ModelException { | |||
| @@ -411,38 +298,31 @@ public class Project extends ModelElement { | |||
| try { | |||
| String targetName = target.getName(); | |||
| String targetGlobalName = targetName; | |||
| if (globalName != null) { | |||
| targetGlobalName = globalName + REF_DELIMITER + targetName; | |||
| } | |||
| checker.visitNode(targetGlobalName); | |||
| checker.visitNode(targetName); | |||
| for (Iterator i = target.getDependencies(); i.hasNext();) { | |||
| String dependency = (String) i.next(); | |||
| boolean localTarget = (dependency.indexOf(REF_DELIMITER) == -1); | |||
| Target dependencyTarget | |||
| = localTarget ? getTarget(dependency) | |||
| : getRefTarget(dependency); | |||
| if (dependencyTarget == null) { | |||
| StringBuffer sb = new StringBuffer("Target '"); | |||
| if (globalName != null) { | |||
| sb.append(globalName + REF_DELIMITER); | |||
| if (localTarget) { | |||
| Target dependencyTarget = getTarget(dependency); | |||
| if (dependencyTarget == null) { | |||
| StringBuffer sb = new StringBuffer("Target '"); | |||
| sb.append(dependency); | |||
| sb.append("' does not exist in this project. "); | |||
| throw new ModelException(new String(sb), | |||
| target.getLocation()); | |||
| } | |||
| sb.append(dependency); | |||
| sb.append("' does not exist in this project. "); | |||
| throw new ModelException(new String(sb), | |||
| target.getLocation()); | |||
| } | |||
| if (localTarget) { | |||
| // need to check the targets we depend on | |||
| fillinDependencyOrder(globalName, dependencyTarget, | |||
| fillinDependencyOrder(dependencyTarget, | |||
| dependencyOrder, visited, checker); | |||
| } | |||
| } | |||
| visited.add(targetName); | |||
| checker.leaveNode(targetGlobalName); | |||
| checker.leaveNode(targetName); | |||
| dependencyOrder.add(targetName); | |||
| } catch (CircularDependencyException e) { | |||
| throw new ModelException(e.getMessage(), | |||
| @@ -450,95 +330,5 @@ public class Project extends ModelElement { | |||
| } | |||
| } | |||
| /** | |||
| * Validate that this build element is configured correctly | |||
| * | |||
| * @param globalName The name of this project in the reference name | |||
| * space | |||
| * @exception ModelException if the element is invalid | |||
| */ | |||
| protected void validate(String globalName) throws ModelException { | |||
| Set keys = referencedProjects.keySet(); | |||
| for (Iterator i = keys.iterator(); i.hasNext();) { | |||
| String refName = (String) i.next(); | |||
| Project referencedProject | |||
| = (Project) referencedProjects.get(refName); | |||
| String refGlobalName = refName; | |||
| if (globalName != null) { | |||
| refGlobalName = globalName + REF_DELIMITER + refName; | |||
| } | |||
| referencedProject.validate(refGlobalName); | |||
| } | |||
| // we now check whether all of dependencies for our targets | |||
| // exist in the model | |||
| // visited contains the targets we have already visited and verified | |||
| Set visited = new HashSet(); | |||
| // checker records the targets we are currently visiting | |||
| CircularDependencyChecker checker | |||
| = new CircularDependencyChecker("checking target dependencies"); | |||
| // dependency order is purely recorded for debug purposes | |||
| List dependencyOrder = new ArrayList(); | |||
| for (Iterator i = getTargets(); i.hasNext();) { | |||
| Target target = (Target) i.next(); | |||
| target.validate(); | |||
| fillinDependencyOrder(globalName, target, dependencyOrder, | |||
| visited, checker); | |||
| } | |||
| } | |||
| /** | |||
| * 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(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 ConfigException if the given target does not exist in the | |||
| * project hierarchy | |||
| */ | |||
| private void flattenDependency(List flattenedList, String fullTargetName) | |||
| throws ConfigException { | |||
| if (flattenedList.contains(fullTargetName)) { | |||
| return; | |||
| } | |||
| try { | |||
| String fullProjectName = getFullProjectName(fullTargetName); | |||
| Target target = getRefTarget(fullTargetName); | |||
| if (target == null) { | |||
| throw new ConfigException("Target " + fullTargetName | |||
| + " does not exist"); | |||
| } | |||
| for (Iterator i = target.getDependencies(); i.hasNext();) { | |||
| String localDependencyName = (String) i.next(); | |||
| String fullDependencyName | |||
| = fullProjectName == null ? localDependencyName | |||
| : fullProjectName + REF_DELIMITER + localDependencyName; | |||
| flattenDependency(flattenedList, fullDependencyName); | |||
| if (!flattenedList.contains(fullDependencyName)) { | |||
| flattenedList.add(fullDependencyName); | |||
| } | |||
| } | |||
| } catch (ModelException e) { | |||
| throw new ConfigException(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -147,7 +147,7 @@ public interface ComponentService { | |||
| void importLibrary(String libraryId) throws ExecutionException; | |||
| /** | |||
| * Imports a component defined in a nother frame. | |||
| * Imports a component defined in another frame. | |||
| * | |||
| * @param relativeName the qualified name of the component relative to | |||
| * this execution frame | |||
| @@ -67,56 +67,71 @@ import org.apache.ant.common.util.ExecutionException; | |||
| */ | |||
| public interface ExecService { | |||
| /** | |||
| * Setup a sub-build. | |||
| * Parse an XML file into a build model. | |||
| * | |||
| * @param antFile the file containing the XML description of the model | |||
| * @param properties the initiali properties to be used in the build | |||
| * @exception ExecutionException if the subbuild cannot be setup | |||
| * @return a key to the build allowing it to be executed and managed | |||
| * @param xmlBuildFile The file containing the XML build description. | |||
| * @return A Project model for the build. | |||
| * @exception ExecutionException if the build cannot be parsed | |||
| */ | |||
| Object setupBuild(File antFile, Map properties) | |||
| Project parseXMLBuildFile(File xmlBuildFile) throws ExecutionException; | |||
| /** | |||
| * Create a project reference. | |||
| * | |||
| * @param referenceName the name under which the project will be | |||
| * referenced. | |||
| * @param model the project model. | |||
| * @exception ExecutionException if the project cannot be referenced. | |||
| */ | |||
| void createProjectReference(String referenceName, Project model) | |||
| throws ExecutionException; | |||
| /** | |||
| * 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 | |||
| * @exception ExecutionException if the subbuild cannot be setup | |||
| * @return a key to the build allowing it to be executed and managed | |||
| * @exception ExecutionException if the subbuild cannot be setup | |||
| */ | |||
| Object setupBuild(Project model, Map properties) | |||
| throws ExecutionException; | |||
| /** | |||
| * Setup a sub-build using the current frame's project model | |||
| * | |||
| * @param properties the initiali properties to be used in the build | |||
| * @exception ExecutionException if the subbuild cannot be setup | |||
| * @return a key to the build allowing it to be executed and managed | |||
| * @exception ExecutionException if the subbuild cannot be setup | |||
| */ | |||
| 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 | |||
| * 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; | |||
| void runBuild(Object buildKey, List targets) throws ExecutionException; | |||
| /** | |||
| * execute a task. The task should have already been initialised by | |||
| * the core | |||
| * execute a task. The task should have already been initialised by the | |||
| * core | |||
| * | |||
| * @param task the task to be executed. | |||
| * @param task the task to be executed. | |||
| * @exception ExecutionException if there is a problem in execution. | |||
| */ | |||
| void executeTask(Task task) throws ExecutionException; | |||
| /** | |||
| * get the name of the project associated with this execution. | |||
| * | |||
| @@ -124,23 +139,24 @@ public interface ExecService { | |||
| */ | |||
| String getProjectName(); | |||
| /** | |||
| * Get the basedir for the current execution | |||
| * | |||
| * @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. | |||
| * | |||
| * @exception ExecutionException if the subbuild cannot be found. | |||
| */ | |||
| void handleBuildOutput(Object subbuildKey, String line, boolean isErr) | |||
| throws ExecutionException; | |||
| void handleBuildOutput(Object subbuildKey, String line, boolean isErr) | |||
| throws ExecutionException; | |||
| } | |||
| @@ -53,7 +53,6 @@ | |||
| */ | |||
| package org.apache.ant.cli; | |||
| import java.io.File; | |||
| import java.io.FileNotFoundException; | |||
| import java.io.FileOutputStream; | |||
| import java.io.IOException; | |||
| import java.io.PrintStream; | |||
| @@ -66,10 +65,8 @@ import java.util.Iterator; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import org.apache.ant.antcore.config.AntConfig; | |||
| import org.apache.ant.antcore.config.AntConfigHandler; | |||
| import org.apache.ant.antcore.execution.ExecutionManager; | |||
| import org.apache.ant.antcore.modelparser.XMLProjectParser; | |||
| import org.apache.ant.antcore.xml.ParseContext; | |||
| import org.apache.ant.antcore.xml.XMLParseException; | |||
| import org.apache.ant.common.event.BuildEvent; | |||
| import org.apache.ant.common.event.BuildListener; | |||