@@ -60,10 +60,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Set;
import java.util.Set;
import java.util.StringTokenizer;
import org.apache.ant.common.util.CircularDependencyChecker;
import org.apache.ant.common.util.CircularDependencyChecker;
import org.apache.ant.common.util.CircularDependencyException;
import org.apache.ant.common.util.CircularDependencyException;
import org.apache.ant.common.util.ConfigException;
import org.apache.ant.common.util.Location;
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
* 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();
private Map targets = new HashMap();
/**
/**
* The global tasks for this project. These are the tasks that will get
* 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();
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. */
/** The URL where the project is defined. */
private URL sourceURL;
private URL sourceURL;
@@ -192,6 +182,7 @@ public class Project extends ModelElement {
return base;
return base;
}
}
/**
/**
* Get the name of the project element
* Get the name of the project element
*
*
@@ -200,7 +191,8 @@ public class Project extends ModelElement {
public String getName() {
public String getName() {
return name;
return name;
}
}
/**
/**
* Get the targets in this project.
* 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
* Get the initialisation tasks for this project
*
*
@@ -255,85 +224,6 @@ public class Project extends ModelElement {
return tasks.iterator();
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.
* Add a target to the project.
*
*
@@ -361,47 +251,44 @@ public class Project extends ModelElement {
tasks.add(task);
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
* Validate this project
*
*
* @exception ModelException if the project is not valid
* @exception ModelException if the project is not valid
*/
*/
public void validate() throws ModelException {
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 target The target being examined
* @param dependencyOrder The dependency order of targets
* @param dependencyOrder The dependency order of targets
* @param visited Set of targets in this project already visited.
* @param visited Set of targets in this project already visited.
* @param checker A circular dependency checker
* @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,
List dependencyOrder, Set visited,
CircularDependencyChecker checker)
CircularDependencyChecker checker)
throws ModelException {
throws ModelException {
@@ -411,38 +298,31 @@ public class Project extends ModelElement {
try {
try {
String targetName = target.getName();
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();) {
for (Iterator i = target.getDependencies(); i.hasNext();) {
String dependency = (String) i.next();
String dependency = (String) i.next();
boolean localTarget = (dependency.indexOf(REF_DELIMITER) == -1);
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
// need to check the targets we depend on
fillinDependencyOrder(globalName, dependencyTarget,
fillinDependencyOrder(dependencyTarget,
dependencyOrder, visited, checker);
dependencyOrder, visited, checker);
}
}
}
}
visited.add(targetName);
visited.add(targetName);
checker.leaveNode(targetGlobal Name);
checker.leaveNode(targetName);
dependencyOrder.add(targetName);
dependencyOrder.add(targetName);
} catch (CircularDependencyException e) {
} catch (CircularDependencyException e) {
throw new ModelException(e.getMessage(),
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);
}
}
}
}