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