From a738000acab66d8d7ce5cf563f6dd96d9c7024fb Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Tue, 2 Dec 2008 12:06:32 +0000 Subject: [PATCH] refid-audit of indirect subclasses of DataType git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@722437 13f79535-47bb-0310-9956-ffa450edef68 --- .../tools/ant/types/AbstractFileSet.java | 4 ++ .../tools/ant/types/ArchiveFileSet.java | 24 ++++++-- .../apache/tools/ant/types/PatternSet.java | 4 ++ .../types/optional/depend/ClassfileSet.java | 22 ++++++- .../resources/AbstractClasspathResource.java | 32 +++++++++- .../ant/types/resources/ArchiveResource.java | 17 ++++++ .../ant/types/resources/FileResource.java | 21 +++++-- .../tools/ant/types/resources/Files.java | 29 ++++----- .../types/resources/JavaConstantResource.java | 2 +- .../types/resources/SizeLimitCollection.java | 1 + .../tools/ant/types/resources/Sort.java | 8 ++- .../tools/ant/types/resources/Tokens.java | 8 ++- .../types/resources/comparators/Reverse.java | 19 ++++++ .../selectors/AbstractSelectorContainer.java | 61 ++++++++++++++++++- .../ant/types/selectors/BaseSelector.java | 3 + .../selectors/BaseSelectorContainer.java | 27 ++++++++ 16 files changed, 246 insertions(+), 36 deletions(-) diff --git a/src/main/org/apache/tools/ant/types/AbstractFileSet.java b/src/main/org/apache/tools/ant/types/AbstractFileSet.java index 10e5816cc..124cc8814 100644 --- a/src/main/org/apache/tools/ant/types/AbstractFileSet.java +++ b/src/main/org/apache/tools/ant/types/AbstractFileSet.java @@ -899,6 +899,10 @@ public abstract class AbstractFileSet extends DataType pushAndInvokeCircularReferenceCheck((DataType) o, stk, p); } } + for (Iterator i = additionalPatterns.iterator(); i.hasNext(); ) { + PatternSet ps = (PatternSet) i.next(); + pushAndInvokeCircularReferenceCheck(ps, stk, p); + } setChecked(true); } } diff --git a/src/main/org/apache/tools/ant/types/ArchiveFileSet.java b/src/main/org/apache/tools/ant/types/ArchiveFileSet.java index ba9cebf6c..c3126f63f 100755 --- a/src/main/org/apache/tools/ant/types/ArchiveFileSet.java +++ b/src/main/org/apache/tools/ant/types/ArchiveFileSet.java @@ -183,6 +183,10 @@ public abstract class ArchiveFileSet extends FileSet { * @return the archive in case the archive is a file, null otherwise. */ public File getSrc() { + if (isReference()) { + return ((ArchiveFileSet) getCheckedRef()).getSrc(); + } + dieOnCircularReference(); if (src != null) { FileProvider fp = (FileProvider) src.as(FileProvider.class); if (fp != null) { @@ -215,6 +219,7 @@ public abstract class ArchiveFileSet extends FileSet { if (isReference()) { return ((ArchiveFileSet) getRef(p)).getPrefix(p); } + dieOnCircularReference(p); return prefix; } @@ -241,6 +246,7 @@ public abstract class ArchiveFileSet extends FileSet { if (isReference()) { return ((ArchiveFileSet) getRef(p)).getFullpath(p); } + dieOnCircularReference(p); return fullpath; } @@ -258,10 +264,10 @@ public abstract class ArchiveFileSet extends FileSet { * @return a directory scanner */ public DirectoryScanner getDirectoryScanner(Project p) { - dieOnCircularReference(); if (isReference()) { return getRef(p).getDirectoryScanner(p); } + dieOnCircularReference(); if (src == null) { return super.getDirectoryScanner(p); } @@ -323,6 +329,10 @@ public abstract class ArchiveFileSet extends FileSet { * @since Ant 1.7 */ public boolean isFilesystemOnly() { + if (isReference()) { + return ((ArchiveFileSet) getCheckedRef()).isFilesystemOnly(); + } + dieOnCircularReference(); return src == null; } @@ -361,6 +371,7 @@ public abstract class ArchiveFileSet extends FileSet { if (isReference()) { return ((ArchiveFileSet) getRef(p)).getFileMode(p); } + dieOnCircularReference(); return fileMode; } @@ -372,6 +383,7 @@ public abstract class ArchiveFileSet extends FileSet { if (isReference()) { return ((ArchiveFileSet) getRef(getProject())).hasFileModeBeenSet(); } + dieOnCircularReference(); return fileModeHasBeenSet; } @@ -409,6 +421,7 @@ public abstract class ArchiveFileSet extends FileSet { if (isReference()) { return ((ArchiveFileSet) getRef(p)).getDirMode(p); } + dieOnCircularReference(); return dirMode; } @@ -421,6 +434,7 @@ public abstract class ArchiveFileSet extends FileSet { if (isReference()) { return ((ArchiveFileSet) getRef(getProject())).hasDirModeBeenSet(); } + dieOnCircularReference(); return dirModeHasBeenSet; } @@ -521,9 +535,11 @@ public abstract class ArchiveFileSet extends FileSet { if (isChecked()) { return; } - if (isReference()) { - super.dieOnCircularReference(stk, p); - } else { + + // takes care of nested selectors + super.dieOnCircularReference(stk, p); + + if (!isReference()) { if (src != null) { pushAndInvokeCircularReferenceCheck(src, stk, p); } diff --git a/src/main/org/apache/tools/ant/types/PatternSet.java b/src/main/org/apache/tools/ant/types/PatternSet.java index dcf5d57b7..d66fb0a05 100644 --- a/src/main/org/apache/tools/ant/types/PatternSet.java +++ b/src/main/org/apache/tools/ant/types/PatternSet.java @@ -357,6 +357,7 @@ public class PatternSet extends DataType implements Cloneable { if (isReference()) { throw new BuildException("Cannot append to a reference"); } + dieOnCircularReference(p); String[] incl = other.getIncludePatterns(p); if (incl != null) { for (int i = 0; i < incl.length; i++) { @@ -380,6 +381,7 @@ public class PatternSet extends DataType implements Cloneable { if (isReference()) { return getRef(p).getIncludePatterns(p); } + dieOnCircularReference(p); readFiles(p); return makeArray(includeList, p); } @@ -393,6 +395,7 @@ public class PatternSet extends DataType implements Cloneable { if (isReference()) { return getRef(p).getExcludePatterns(p); } + dieOnCircularReference(p); readFiles(p); return makeArray(excludeList, p); } @@ -407,6 +410,7 @@ public class PatternSet extends DataType implements Cloneable { if (isReference()) { return getRef(p).hasPatterns(p); } + dieOnCircularReference(p); return includesFileList.size() > 0 || excludesFileList.size() > 0 || includeList.size() > 0 || excludeList.size() > 0; } diff --git a/src/main/org/apache/tools/ant/types/optional/depend/ClassfileSet.java b/src/main/org/apache/tools/ant/types/optional/depend/ClassfileSet.java index 6cc873b3f..475649343 100644 --- a/src/main/org/apache/tools/ant/types/optional/depend/ClassfileSet.java +++ b/src/main/org/apache/tools/ant/types/optional/depend/ClassfileSet.java @@ -17,8 +17,9 @@ */ package org.apache.tools.ant.types.optional.depend; -import java.util.Vector; import java.util.Enumeration; +import java.util.Stack; +import java.util.Vector; import org.apache.tools.ant.Project; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.types.FileSet; @@ -86,6 +87,7 @@ public class ClassfileSet extends FileSet { */ public void addRootFileset(FileSet rootFileSet) { rootFileSets.addElement(rootFileSet); + setChecked(false); } /** @@ -118,6 +120,7 @@ public class ClassfileSet extends FileSet { if (isReference()) { return getRef(p).getDirectoryScanner(p); } + dieOnCircularReference(p); Vector allRootClasses = (Vector) rootClasses.clone(); for (Enumeration e = rootFileSets.elements(); e.hasMoreElements();) { FileSet additionalRootSet = (FileSet) e.nextElement(); @@ -160,4 +163,21 @@ public class ClassfileSet extends FileSet { ? (ClassfileSet) (getRef(getProject())) : this); } + protected synchronized void dieOnCircularReference(Stack stk, Project p) { + if (isChecked()) { + return; + } + + // takes care of nested selectors + super.dieOnCircularReference(stk, p); + + if (!isReference()) { + for (Enumeration e = rootFileSets.elements(); + e.hasMoreElements();) { + FileSet additionalRootSet = (FileSet) e.nextElement(); + pushAndInvokeCircularReferenceCheck(additionalRootSet, stk, p); + } + setChecked(true); + } + } } diff --git a/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java b/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java index 79f9eb4b7..4d188c6ae 100644 --- a/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java +++ b/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java @@ -17,6 +17,7 @@ */ package org.apache.tools.ant.types.resources; +import org.apache.tools.ant.Project; import org.apache.tools.ant.types.Resource; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Reference; @@ -24,6 +25,7 @@ import org.apache.tools.ant.util.FileUtils; import java.io.InputStream; import java.io.IOException; +import java.util.Stack; /** * @@ -48,6 +50,7 @@ public abstract class AbstractClasspathResource extends Resource { } else { this.classpath.append(classpath); } + setChecked(false); } /** @@ -59,6 +62,7 @@ public abstract class AbstractClasspathResource extends Resource { if (classpath == null) { classpath = new Path(getProject()); } + setChecked(false); return classpath.createPath(); } @@ -77,8 +81,11 @@ public abstract class AbstractClasspathResource extends Resource { * @return The classpath */ public Path getClasspath() { - return isReference() - ? ((JavaResource) getCheckedRef()).getClasspath() : classpath; + if (isReference()) { + return ((AbstractClasspathResource) getCheckedRef()).getClasspath(); + } + dieOnCircularReference(); + return classpath; } /** @@ -86,6 +93,10 @@ public abstract class AbstractClasspathResource extends Resource { * @return the loader. */ public Reference getLoader() { + if (isReference()) { + return ((AbstractClasspathResource) getCheckedRef()).getLoader(); + } + dieOnCircularReference(); return loader; } @@ -125,6 +136,7 @@ public abstract class AbstractClasspathResource extends Resource { if (isReference()) { return ((Resource) getCheckedRef()).isExists(); } + dieOnCircularReference(); InputStream is = null; try { is = getInputStream(); @@ -145,6 +157,7 @@ public abstract class AbstractClasspathResource extends Resource { if (isReference()) { return ((Resource) getCheckedRef()).getInputStream(); } + dieOnCircularReference(); ClassLoader cl = null; if (loader != null) { cl = (ClassLoader) loader.getReferencedObject(); @@ -170,4 +183,19 @@ public abstract class AbstractClasspathResource extends Resource { * @throws IOException if an error occurs. */ protected abstract InputStream openInputStream(ClassLoader cl) throws IOException; + + protected synchronized void dieOnCircularReference(Stack stk, Project p) { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); + } else { + if (classpath != null) { + pushAndInvokeCircularReferenceCheck(classpath, stk, p); + } + setChecked(true); + } + } + } diff --git a/src/main/org/apache/tools/ant/types/resources/ArchiveResource.java b/src/main/org/apache/tools/ant/types/resources/ArchiveResource.java index bc5d2a78e..8329a1969 100644 --- a/src/main/org/apache/tools/ant/types/resources/ArchiveResource.java +++ b/src/main/org/apache/tools/ant/types/resources/ArchiveResource.java @@ -18,8 +18,10 @@ package org.apache.tools.ant.types.resources; import java.io.File; +import java.util.Stack; import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; import org.apache.tools.ant.types.Resource; import org.apache.tools.ant.types.ResourceCollection; import org.apache.tools.ant.types.Reference; @@ -241,6 +243,7 @@ public abstract class ArchiveResource extends Resource { } private synchronized void checkEntry() throws BuildException { + dieOnCircularReference(); if (haveEntry) { return; } @@ -266,4 +269,18 @@ public abstract class ArchiveResource extends Resource { * fetches information from the named entry inside the archive. */ protected abstract void fetchEntry(); + + protected synchronized void dieOnCircularReference(Stack stk, Project p) { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); + } else { + if (archive != null) { + pushAndInvokeCircularReferenceCheck(archive, stk, p); + } + setChecked(true); + } + } } diff --git a/src/main/org/apache/tools/ant/types/resources/FileResource.java b/src/main/org/apache/tools/ant/types/resources/FileResource.java index 20758fec7..5e37204b2 100644 --- a/src/main/org/apache/tools/ant/types/resources/FileResource.java +++ b/src/main/org/apache/tools/ant/types/resources/FileResource.java @@ -104,7 +104,11 @@ public class FileResource extends Resource implements Touchable, FileProvider, * @return the File. */ public File getFile() { - return isReference() ? ((FileResource) getCheckedRef()).getFile() : file; + if (isReference()) { + return ((FileResource) getCheckedRef()).getFile(); + } + dieOnCircularReference(); + return file; } /** @@ -121,8 +125,11 @@ public class FileResource extends Resource implements Touchable, FileProvider, * @return the basedir as File. */ public File getBaseDir() { - return isReference() - ? ((FileResource) getCheckedRef()).getBaseDir() : baseDir; + if (isReference()) { + return ((FileResource) getCheckedRef()).getBaseDir(); + } + dieOnCircularReference(); + return baseDir; } /** @@ -322,8 +329,11 @@ public class FileResource extends Resource implements Touchable, FileProvider, * @return whether this Resource is a FileResource. */ public boolean isFilesystemOnly() { - return !isReference() - || ((FileResource) getCheckedRef()).isFilesystemOnly(); + if (isReference()) { + return ((FileResource) getCheckedRef()).isFilesystemOnly(); + } + dieOnCircularReference(); + return true; } /** @@ -347,6 +357,7 @@ public class FileResource extends Resource implements Touchable, FileProvider, if (getFile() == null) { throw new BuildException("file attribute is null!"); } + dieOnCircularReference(); return getFile(); } diff --git a/src/main/org/apache/tools/ant/types/resources/Files.java b/src/main/org/apache/tools/ant/types/resources/Files.java index cfd7190a3..f318ca6d8 100644 --- a/src/main/org/apache/tools/ant/types/resources/Files.java +++ b/src/main/org/apache/tools/ant/types/resources/Files.java @@ -36,14 +36,13 @@ import org.apache.tools.ant.types.selectors.AbstractSelectorContainer; * @since Ant 1.7 */ public class Files extends AbstractSelectorContainer - implements Cloneable, ResourceCollection { + implements ResourceCollection { private static final Iterator EMPTY_ITERATOR = Collections.EMPTY_SET.iterator(); private PatternSet defaultPatterns = new PatternSet(); private Vector additionalPatterns = new Vector(); - private Vector selectors = new Vector(); private boolean useDefaultExcludes = true; private boolean caseSensitive = true; @@ -67,7 +66,6 @@ public class Files extends AbstractSelectorContainer protected Files(Files f) { this.defaultPatterns = f.defaultPatterns; this.additionalPatterns = f.additionalPatterns; - this.selectors = f.selectors; this.useDefaultExcludes = f.useDefaultExcludes; this.caseSensitive = f.caseSensitive; this.followSymlinks = f.followSymlinks; @@ -90,7 +88,7 @@ public class Files extends AbstractSelectorContainer if (!additionalPatterns.isEmpty()) { throw noChildrenAllowed(); } - if (!selectors.isEmpty()) { + if (hasSelectors()) { throw noChildrenAllowed(); } super.setRefid(r); @@ -107,6 +105,7 @@ public class Files extends AbstractSelectorContainer PatternSet patterns = new PatternSet(); additionalPatterns.addElement(patterns); ds = null; + setChecked(false); return patterns; } @@ -353,6 +352,7 @@ public class Files extends AbstractSelectorContainer if (isReference()) { return getRef().hasPatterns(); } + dieOnCircularReference(); if (hasPatterns(defaultPatterns)) { return true; } @@ -408,19 +408,14 @@ public class Files extends AbstractSelectorContainer if (isReference()) { return getRef().clone(); } - try { - Files f = (Files) super.clone(); - f.defaultPatterns = (PatternSet) defaultPatterns.clone(); - f.additionalPatterns = new Vector(additionalPatterns.size()); - for (Iterator iter = additionalPatterns.iterator(); iter.hasNext();) { - PatternSet ps = (PatternSet) iter.next(); - f.additionalPatterns.add(ps.clone()); - } - f.selectors = new Vector(selectors); - return f; - } catch (CloneNotSupportedException e) { - throw new BuildException(e); + Files f = (Files) super.clone(); + f.defaultPatterns = (PatternSet) defaultPatterns.clone(); + f.additionalPatterns = new Vector(additionalPatterns.size()); + for (Iterator iter = additionalPatterns.iterator(); iter.hasNext();) { + PatternSet ps = (PatternSet) iter.next(); + f.additionalPatterns.add(ps.clone()); } + return f; } /** @@ -453,6 +448,7 @@ public class Files extends AbstractSelectorContainer if (isReference()) { return getRef().mergePatterns(p); } + dieOnCircularReference(); PatternSet ps = new PatternSet(); ps.append(defaultPatterns, p); final int count = additionalPatterns.size(); @@ -482,6 +478,7 @@ public class Files extends AbstractSelectorContainer } private synchronized void ensureDirectoryScannerSetup() { + dieOnCircularReference(); if (ds == null) { ds = new DirectoryScanner(); PatternSet ps = mergePatterns(getProject()); diff --git a/src/main/org/apache/tools/ant/types/resources/JavaConstantResource.java b/src/main/org/apache/tools/ant/types/resources/JavaConstantResource.java index 6a22073ee..f8ff6e2a8 100644 --- a/src/main/org/apache/tools/ant/types/resources/JavaConstantResource.java +++ b/src/main/org/apache/tools/ant/types/resources/JavaConstantResource.java @@ -31,7 +31,7 @@ import java.lang.reflect.Field; public class JavaConstantResource extends AbstractClasspathResource { /** - * open the inpout stream from a specific classloader + * open the input stream from a specific classloader * * @param cl the classloader to use. Will be null if the system classloader is used * @return an open input stream for the resource diff --git a/src/main/org/apache/tools/ant/types/resources/SizeLimitCollection.java b/src/main/org/apache/tools/ant/types/resources/SizeLimitCollection.java index aeb42ddf7..c8e772be0 100644 --- a/src/main/org/apache/tools/ant/types/resources/SizeLimitCollection.java +++ b/src/main/org/apache/tools/ant/types/resources/SizeLimitCollection.java @@ -34,6 +34,7 @@ public abstract class SizeLimitCollection extends BaseResourceCollectionWrapper * @param i the count as int. */ public synchronized void setCount(int i) { + checkAttributesAllowed(); count = i; } diff --git a/src/main/org/apache/tools/ant/types/resources/Sort.java b/src/main/org/apache/tools/ant/types/resources/Sort.java index a4a78ba5d..24e10b30f 100644 --- a/src/main/org/apache/tools/ant/types/resources/Sort.java +++ b/src/main/org/apache/tools/ant/types/resources/Sort.java @@ -141,9 +141,11 @@ public class Sort extends BaseResourceCollectionWrapper { if (isChecked()) { return; } - if (isReference()) { - super.dieOnCircularReference(stk, p); - } else { + + // check nested collection + super.dieOnCircularReference(stk, p); + + if (!isReference()) { DataType.pushAndInvokeCircularReferenceCheck(comp, stk, p); setChecked(true); } diff --git a/src/main/org/apache/tools/ant/types/resources/Tokens.java b/src/main/org/apache/tools/ant/types/resources/Tokens.java index 3d56d6e16..d717596d9 100644 --- a/src/main/org/apache/tools/ant/types/resources/Tokens.java +++ b/src/main/org/apache/tools/ant/types/resources/Tokens.java @@ -117,9 +117,11 @@ public class Tokens extends BaseResourceCollectionWrapper { if (isChecked()) { return; } - if (isReference()) { - super.dieOnCircularReference(stk, p); - } else { + + // check nested collection + super.dieOnCircularReference(stk, p); + + if (!isReference()) { if (tokenizer instanceof DataType) { pushAndInvokeCircularReferenceCheck((DataType) tokenizer, stk, p); diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/Reverse.java b/src/main/org/apache/tools/ant/types/resources/comparators/Reverse.java index e7c1e9592..2c9e62384 100755 --- a/src/main/org/apache/tools/ant/types/resources/comparators/Reverse.java +++ b/src/main/org/apache/tools/ant/types/resources/comparators/Reverse.java @@ -17,7 +17,10 @@ */ package org.apache.tools.ant.types.resources.comparators; +import java.util.Stack; import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; import org.apache.tools.ant.types.Resource; /** @@ -54,6 +57,7 @@ public class Reverse extends ResourceComparator { throw new BuildException(ONE_NESTED); } nested = c; + setChecked(false); } /** @@ -68,4 +72,19 @@ public class Reverse extends ResourceComparator { ? foo.compareTo(bar) : nested.compare(foo, bar)); } + protected void dieOnCircularReference(Stack stk, Project p) + throws BuildException { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); + } else { + if (nested instanceof DataType) { + pushAndInvokeCircularReferenceCheck((DataType) nested, stk, + p); + } + setChecked(true); + } + } } diff --git a/src/main/org/apache/tools/ant/types/selectors/AbstractSelectorContainer.java b/src/main/org/apache/tools/ant/types/selectors/AbstractSelectorContainer.java index f0eae3f13..481312e86 100644 --- a/src/main/org/apache/tools/ant/types/selectors/AbstractSelectorContainer.java +++ b/src/main/org/apache/tools/ant/types/selectors/AbstractSelectorContainer.java @@ -19,8 +19,11 @@ package org.apache.tools.ant.types.selectors; import java.util.Enumeration; +import java.util.Iterator; +import java.util.Stack; import java.util.Vector; +import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.types.DataType; import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; @@ -32,7 +35,7 @@ import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; * @since 1.7 */ public abstract class AbstractSelectorContainer extends DataType - implements SelectorContainer { + implements Cloneable, SelectorContainer { private Vector selectorsList = new Vector(); @@ -41,6 +44,10 @@ public abstract class AbstractSelectorContainer extends DataType * @return true if there are selectors */ public boolean hasSelectors() { + if (isReference()) { + return ((AbstractSelectorContainer) getCheckedRef()).hasSelectors(); + } + dieOnCircularReference(); return !(selectorsList.isEmpty()); } @@ -49,6 +56,10 @@ public abstract class AbstractSelectorContainer extends DataType * @return the number of selectors */ public int selectorCount() { + if (isReference()) { + return ((AbstractSelectorContainer) getCheckedRef()).selectorCount(); + } + dieOnCircularReference(); return selectorsList.size(); } @@ -58,6 +69,11 @@ public abstract class AbstractSelectorContainer extends DataType * @return an array of selectors */ public FileSelector[] getSelectors(Project p) { + if (isReference()) { + return ((AbstractSelectorContainer) getCheckedRef(p)) + .getSelectors(p); + } + dieOnCircularReference(p); FileSelector[] result = new FileSelector[selectorsList.size()]; selectorsList.copyInto(result); return result; @@ -68,6 +84,11 @@ public abstract class AbstractSelectorContainer extends DataType * @return an enumerator for the selectors */ public Enumeration selectorElements() { + if (isReference()) { + return ((AbstractSelectorContainer) getCheckedRef()) + .selectorElements(); + } + dieOnCircularReference(); return selectorsList.elements(); } @@ -99,7 +120,11 @@ public abstract class AbstractSelectorContainer extends DataType * @param selector the new selector to add */ public void appendSelector(FileSelector selector) { + if (isReference()) { + throw noChildrenAllowed(); + } selectorsList.addElement(selector); + setChecked(false); } /** @@ -119,6 +144,10 @@ public abstract class AbstractSelectorContainer extends DataType * */ public void validate() { + if (isReference()) { + ((AbstractSelectorContainer) getCheckedRef()).validate(); + } + dieOnCircularReference(); Enumeration e = selectorElements(); while (e.hasMoreElements()) { Object o = e.nextElement(); @@ -293,4 +322,34 @@ public abstract class AbstractSelectorContainer extends DataType appendSelector(selector); } + protected synchronized void dieOnCircularReference(Stack stk, Project p) { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); + } else { + for (Iterator i = selectorsList.iterator(); i.hasNext(); ) { + Object o = i.next(); + if (o instanceof DataType) { + pushAndInvokeCircularReferenceCheck((DataType) o, stk, p); + } + } + setChecked(true); + } + } + + public synchronized Object clone() { + if (isReference()) { + return ((AbstractSelectorContainer) getCheckedRef()).clone(); + } + try { + AbstractSelectorContainer sc = + (AbstractSelectorContainer) super.clone(); + sc.selectorsList = new Vector(selectorsList); + return sc; + } catch (CloneNotSupportedException e) { + throw new BuildException(e); + } + } } diff --git a/src/main/org/apache/tools/ant/types/selectors/BaseSelector.java b/src/main/org/apache/tools/ant/types/selectors/BaseSelector.java index 9feeb7e6f..61d7a1a27 100644 --- a/src/main/org/apache/tools/ant/types/selectors/BaseSelector.java +++ b/src/main/org/apache/tools/ant/types/selectors/BaseSelector.java @@ -89,6 +89,9 @@ public abstract class BaseSelector extends DataType implements FileSelector { if (getError() != null) { throw new BuildException(errmsg); } + if (!isReference()) { + dieOnCircularReference(); + } } /** diff --git a/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java b/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java index e5f7d539d..a49455256 100644 --- a/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java +++ b/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java @@ -20,10 +20,13 @@ package org.apache.tools.ant.types.selectors; import java.io.File; import java.util.Enumeration; +import java.util.Iterator; +import java.util.Stack; import java.util.Vector; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; /** @@ -47,6 +50,7 @@ public abstract class BaseSelectorContainer extends BaseSelector * @return true if there are selectors */ public boolean hasSelectors() { + dieOnCircularReference(); return !(selectorsList.isEmpty()); } @@ -55,6 +59,7 @@ public abstract class BaseSelectorContainer extends BaseSelector * @return the number of selectors */ public int selectorCount() { + dieOnCircularReference(); return selectorsList.size(); } @@ -64,6 +69,7 @@ public abstract class BaseSelectorContainer extends BaseSelector * @return an array of selectors */ public FileSelector[] getSelectors(Project p) { + dieOnCircularReference(); FileSelector[] result = new FileSelector[selectorsList.size()]; selectorsList.copyInto(result); return result; @@ -74,6 +80,7 @@ public abstract class BaseSelectorContainer extends BaseSelector * @return an enumerator for the selectors */ public Enumeration selectorElements() { + dieOnCircularReference(); return selectorsList.elements(); } @@ -85,6 +92,7 @@ public abstract class BaseSelectorContainer extends BaseSelector * @return comma separated list of Selectors contained in this one */ public String toString() { + dieOnCircularReference(); StringBuffer buf = new StringBuffer(); Enumeration e = selectorElements(); if (e.hasMoreElements()) { @@ -106,6 +114,7 @@ public abstract class BaseSelectorContainer extends BaseSelector */ public void appendSelector(FileSelector selector) { selectorsList.addElement(selector); + setChecked(false); } /** @@ -126,6 +135,7 @@ public abstract class BaseSelectorContainer extends BaseSelector */ public void validate() { verifySettings(); + dieOnCircularReference(); String errmsg = getError(); if (errmsg != null) { throw new BuildException(errmsg); @@ -318,4 +328,21 @@ public abstract class BaseSelectorContainer extends BaseSelector appendSelector(selector); } + protected synchronized void dieOnCircularReference(Stack stk, Project p) + throws BuildException { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); + } else { + for (Iterator i = selectorsList.iterator(); i.hasNext();) { + Object o = i.next(); + if (o instanceof DataType) { + pushAndInvokeCircularReferenceCheck((DataType) o, stk, p); + } + } + setChecked(true); + } + } }