Browse Source

Make Projectref's dynamic and task based

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272494 13f79535-47bb-0310-9956-ffa450edef68
master
Conor MacNeill 23 years ago
parent
commit
c2f14ffad1
12 changed files with 368 additions and 501 deletions
  1. +39
    -4
      proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/CoreExecService.java
  2. +100
    -38
      proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java
  3. +2
    -13
      proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java
  4. +0
    -161
      proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/RefHandler.java
  5. +2
    -0
      proposal/mutant/src/java/antlibs/system/antlib.xml
  6. +18
    -8
      proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ant.java
  7. +127
    -0
      proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ref.java
  8. +1
    -1
      proposal/mutant/src/java/bootstrap/org/apache/ant/builder/BuildHelper.java
  9. +43
    -253
      proposal/mutant/src/java/common/org/apache/ant/common/model/Project.java
  10. +1
    -1
      proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java
  11. +35
    -19
      proposal/mutant/src/java/common/org/apache/ant/common/service/ExecService.java
  12. +0
    -3
      proposal/mutant/src/java/frontend/org/apache/ant/cli/Commandline.java

+ 39
- 4
proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/CoreExecService.java View File

@@ -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.
*


+ 100
- 38
proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java View File

@@ -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();
}
}




+ 2
- 13
proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java View File

@@ -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());
}
}


+ 0
- 161
proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/RefHandler.java View File

@@ -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);
}
}
}



+ 2
- 0
proposal/mutant/src/java/antlibs/system/antlib.xml View File

@@ -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"/>


+ 18
- 8
proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ant.java View File

@@ -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());
}
}


+ 127
- 0
proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ref.java View File

@@ -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);
}
}


+ 1
- 1
proposal/mutant/src/java/bootstrap/org/apache/ant/builder/BuildHelper.java View File

@@ -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();
}



+ 43
- 253
proposal/mutant/src/java/common/org/apache/ant/common/model/Project.java View File

@@ -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);
}
}
}


+ 1
- 1
proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java View File

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


+ 35
- 19
proposal/mutant/src/java/common/org/apache/ant/common/service/ExecService.java View File

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


+ 0
- 3
proposal/mutant/src/java/frontend/org/apache/ant/cli/Commandline.java View File

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


Loading…
Cancel
Save