From e8d2007cff10bf96dfe533c7ed89685702c9add7 Mon Sep 17 00:00:00 2001
From: Stefan Bodewig
Date: Tue, 5 Sep 2000 14:15:50 +0000
Subject: [PATCH] Add a nested element to . This means one path
can include another path (by reference as well as literally, although I doubt
the latter is of any use). Circular references should be caught. Suggested
by: Barrie Treloar
git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267962 13f79535-47bb-0310-9956-ffa450edef68
---
docs/index.html | 17 +++
src/main/org/apache/tools/ant/types/Path.java | 115 ++++++++++++++--
.../org/apache/tools/ant/types/Reference.java | 2 +-
.../org/apache/tools/ant/types/PathTest.java | 127 ++++++++++++++++++
4 files changed, 249 insertions(+), 12 deletions(-)
diff --git a/docs/index.html b/docs/index.html
index 87c1d70cc..2f437bc82 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -465,6 +465,23 @@ you can define them with a <path>
element at the
same level as targets and reference them via their
id attribute - see References for an
example.
+A PATH like structure can include a reference to another PATH like
+structure via a nested <path>
elements.
+
+ <path id="base.path">
+ <pathelement path="${classpath}" />
+ <fileset dir="lib">
+ <include name="**/*.jar" />
+ </fileset;>
+ <pathelement location="classes" />
+ </path>
+
+ <path id="tests.path">
+ <path refid="base.path" />
+ <pathelement location="testclasses" />
+ </path>
+
+
Several tasks take arguments that shall be passed to another
diff --git a/src/main/org/apache/tools/ant/types/Path.java b/src/main/org/apache/tools/ant/types/Path.java
index 565abfdff..d564fb61e 100644
--- a/src/main/org/apache/tools/ant/types/Path.java
+++ b/src/main/org/apache/tools/ant/types/Path.java
@@ -60,8 +60,10 @@ import org.apache.tools.ant.Project;
import org.apache.tools.ant.PathTokenizer;
import java.io.File;
-import java.util.Vector;
+import java.util.Enumeration;
import java.util.StringTokenizer;
+import java.util.Stack;
+import java.util.Vector;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
@@ -97,6 +99,11 @@ public class Path implements Cloneable {
private Vector elements;
private Project project;
+ private boolean isReference = false;
+ /**
+ * Are we sure we don't hold circular references?
+ */
+ private boolean checked = true;
public static Path systemClasspath =
new Path(null, System.getProperty("java.class.path"));
@@ -140,7 +147,10 @@ public class Path implements Cloneable {
* @param location the location of the element to add (must not be
* null
nor empty.
*/
- public void setLocation(File location) {
+ public void setLocation(File location) throws BuildException {
+ if (isReference) {
+ throw tooManyAttributes();
+ }
createPathElement().setLocation(location);
}
@@ -149,15 +159,35 @@ public class Path implements Cloneable {
* Parses a path definition and creates single PathElements.
* @param path the path definition.
*/
- public void setPath(String path) {
+ public void setPath(String path) throws BuildException {
+ if (isReference) {
+ throw tooManyAttributes();
+ }
createPathElement().setPath(path);
}
+ /**
+ * Makes this instance in effect a reference too another Path instance.
+ *
+ *
You must not set another attribute or nest elements inside
+ * this element if you make it a reference.
+ */
+ public void setRefid(Reference r) throws BuildException {
+ isReference = true;
+ if (!elements.isEmpty()) {
+ throw tooManyAttributes();
+ }
+ elements.addElement(r);
+ checked = false;
+ }
/**
- * Created the nested element.
+ * Creates the nested element.
*/
- public PathElement createPathElement() {
+ public PathElement createPathElement() throws BuildException {
+ if (isReference) {
+ throw noChildrenAllowed();
+ }
PathElement pe = new PathElement();
elements.addElement(pe);
return pe;
@@ -166,17 +196,36 @@ public class Path implements Cloneable {
/**
* Adds a nested element.
*/
- public void addFileset(FileSet fs) {
+ public void addFileset(FileSet fs) throws BuildException {
+ if (isReference) {
+ throw noChildrenAllowed();
+ }
elements.addElement(fs);
}
/**
* Adds a nested element.
*/
- public void addFilesetRef(Reference r) {
+ public void addFilesetRef(Reference r) throws BuildException {
+ if (isReference) {
+ throw noChildrenAllowed();
+ }
elements.addElement(r);
}
+ /**
+ * Creates a nested element.
+ */
+ public Path createPath() throws BuildException {
+ if (isReference) {
+ throw noChildrenAllowed();
+ }
+ Path p = new Path(project);
+ elements.add(p);
+ checked = false;
+ return p;
+ }
+
/**
* Append the contents of the other Path instance to this.
*/
@@ -214,19 +263,26 @@ public class Path implements Cloneable {
}
/**
- * Returns all path elements defined by this and netsed path objects.
+ * Returns all path elements defined by this and nested path objects.
* @return list of path elements.
*/
public String[] list() {
+ if (!checked) {
+ // make sure we don't have a circular reference here
+ Stack stk = new Stack();
+ stk.push(this);
+ bailOnCircularReference(stk);
+ }
+
Vector result = new Vector(2*elements.size());
for (int i=0; i dummy2 --> dummy3 --> dummy1
+ Path p1 = new Path(project);
+ project.addReference("dummy1", p1);
+ Path p2 = p1.createPath();
+ project.addReference("dummy2", p2);
+ Path p3 = p2.createPath();
+ project.addReference("dummy3", p3);
+ p3.setRefid(new Reference("dummy1"));
+ try {
+ p1.list();
+ fail("Can make circular reference.");
+ } catch (BuildException be) {
+ assertEquals("This path contains a circular reference.",
+ be.getMessage());
+ }
+
+ // dummy1 --> dummy2 --> dummy3 (with Path "/a")
+ p1 = new Path(project);
+ project.addReference("dummy1", p1);
+ p2 = p1.createPath();
+ project.addReference("dummy2", p2);
+ p3 = p2.createPath();
+ project.addReference("dummy3", p3);
+ p3.setLocation(new File("/a"));
+ String[] l = p1.list();
+ assertEquals("One element burried deep inside a nested path structure",
+ 1, l.length);
+ if (isUnixStyle) {
+ assertEquals("/a", l[0]);
+ } else {
+ assertEquals("\\a", l[0]);
+ }
}
}