diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionAdapter.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionAdapter.java index 0f00b557e..c9f548e99 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionAdapter.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionAdapter.java @@ -160,23 +160,6 @@ public class ExtensionAdapter extends DataType { || null != implementationURL) { throw tooManyAttributes(); } - // change this to get the objects from the other reference - Object o = reference.getReferencedObject(getProject()); - if (o instanceof ExtensionAdapter) { - final ExtensionAdapter other = (ExtensionAdapter) o; - extensionName = other.extensionName; - specificationVersion = other.specificationVersion; - specificationVendor = other.specificationVendor; - implementationVersion = other.implementationVersion; - implementationVendorID = other.implementationVendorID; - implementationVendor = other.implementationVendor; - implementationURL = other.implementationURL; - } else { - final String message = - reference.getRefId() + " doesn\'t refer to a Extension"; - throw new BuildException(message); - } - super.setRefid(reference); } @@ -194,6 +177,10 @@ public class ExtensionAdapter extends DataType { */ Extension toExtension() throws BuildException { + if (isReference()) { + return ((ExtensionAdapter) getCheckedRef()).toExtension(); + } + dieOnCircularReference(); if (null == extensionName) { final String message = "Extension is missing name."; throw new BuildException(message); diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java index 069f095fa..743edd95e 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java @@ -19,6 +19,8 @@ package org.apache.tools.ant.taskdefs.optional.extension; import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; +import java.util.Stack; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.types.DataType; @@ -49,6 +51,10 @@ public class ExtensionSet * @param extensionAdapter an extension that this library requires. */ public void addExtension(final ExtensionAdapter extensionAdapter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); extensions.add(extensionAdapter); } @@ -58,6 +64,10 @@ public class ExtensionSet * @param fileSet a set of files about which extensions data will be extracted. */ public void addLibfileset(final LibFileSet fileSet) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); extensionsFilesets.add(fileSet); } @@ -67,6 +77,10 @@ public class ExtensionSet * @param fileSet a set of files about which extensions data will be extracted. */ public void addFileset(final FileSet fileSet) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); extensionsFilesets.add(fileSet); } @@ -79,6 +93,10 @@ public class ExtensionSet */ public Extension[] toExtensions(final Project proj) throws BuildException { + if (isReference()) { + return ((ExtensionSet) getCheckedRef()).toExtensions(proj); + } + dieOnCircularReference(); final ArrayList extensionsList = ExtensionUtil.toExtensions(extensions); ExtensionUtil.extractExtensions(proj, extensionsList, extensionsFilesets); return (Extension[]) extensionsList.toArray(new Extension[extensionsList.size()]); @@ -99,20 +117,26 @@ public class ExtensionSet if (!extensions.isEmpty() || !extensionsFilesets.isEmpty()) { throw tooManyAttributes(); } - // change this to get the objects from the other reference - final Object object = - reference.getReferencedObject(getProject()); - if (object instanceof ExtensionSet) { - final ExtensionSet other = (ExtensionSet) object; - extensions.addAll(other.extensions); - extensionsFilesets.addAll(other.extensionsFilesets); + super.setRefid(reference); + } + + protected synchronized void dieOnCircularReference(Stack stk, Project p) + throws BuildException { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); } else { - final String message = - reference.getRefId() + " doesn\'t refer to a ExtensionSet"; - throw new BuildException(message); + for (Iterator i = extensions.iterator(); i.hasNext(); ) { + pushAndInvokeCircularReferenceCheck((ExtensionAdapter) i.next(), + stk, p); + } + for (Iterator i = extensionsFilesets.iterator(); i.hasNext(); ) { + pushAndInvokeCircularReferenceCheck((FileSet) i.next(), stk, p); + } + setChecked(true); } - - super.setRefid(reference); } /** diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java index 0a131187c..cf40922de 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java @@ -36,7 +36,7 @@ import org.apache.tools.ant.BuildEvent; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildListener; import org.apache.tools.ant.Project; -import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.ProjectComponent; import org.apache.tools.ant.util.FileUtils; /** @@ -67,7 +67,7 @@ import org.apache.tools.ant.util.FileUtils; * * @since Ant 1.8.0 */ -public class FailureRecorder extends DataType implements JUnitResultFormatter, BuildListener { +public class FailureRecorder extends ProjectComponent implements JUnitResultFormatter, BuildListener { /** * This is the name of a magic System property ({@value}). The value of this diff --git a/src/main/org/apache/tools/ant/types/AbstractFileSet.java b/src/main/org/apache/tools/ant/types/AbstractFileSet.java index c1d04c0d9..10e5816cc 100644 --- a/src/main/org/apache/tools/ant/types/AbstractFileSet.java +++ b/src/main/org/apache/tools/ant/types/AbstractFileSet.java @@ -18,8 +18,10 @@ package org.apache.tools.ant.types; import java.io.File; -import java.util.Vector; import java.util.Enumeration; +import java.util.Iterator; +import java.util.Stack; +import java.util.Vector; import org.apache.tools.ant.Project; import org.apache.tools.ant.FileScanner; @@ -147,7 +149,11 @@ public abstract class AbstractFileSet extends DataType * @return File. */ public synchronized File getDir(Project p) { - return (isReference()) ? getRef(p).getDir(p) : dir; + if (isReference()) { + return getRef(p).getDir(p); + } + dieOnCircularReference(); + return dir; } /** @@ -342,8 +348,11 @@ public abstract class AbstractFileSet extends DataType * @since Ant 1.6.3 */ public synchronized boolean getDefaultexcludes() { - return (isReference()) - ? getRef(getProject()).getDefaultexcludes() : useDefaultExcludes; + if (isReference()) { + return getRef(getProject()).getDefaultexcludes(); + } + dieOnCircularReference(); + return useDefaultExcludes; } /** @@ -368,8 +377,11 @@ public abstract class AbstractFileSet extends DataType * @since Ant 1.7 */ public synchronized boolean isCaseSensitive() { - return (isReference()) - ? getRef(getProject()).isCaseSensitive() : caseSensitive; + if (isReference()) { + return getRef(getProject()).isCaseSensitive(); + } + dieOnCircularReference(); + return caseSensitive; } /** @@ -394,8 +406,11 @@ public abstract class AbstractFileSet extends DataType * @since Ant 1.6 */ public synchronized boolean isFollowSymlinks() { - return (isReference()) - ? getRef(getProject()).isFollowSymlinks() : followSymlinks; + if (isReference()) { + return getRef(getProject()).isCaseSensitive(); + } + dieOnCircularReference(); + return followSymlinks; } /** @@ -435,6 +450,7 @@ public abstract class AbstractFileSet extends DataType if (isReference()) { return getRef(p).getDirectoryScanner(p); } + dieOnCircularReference(); DirectoryScanner ds = null; synchronized (this) { if (directoryScanner != null && p == getProject()) { @@ -484,6 +500,7 @@ public abstract class AbstractFileSet extends DataType getRef(p).setupDirectoryScanner(ds, p); return; } + dieOnCircularReference(p); if (ds == null) { throw new IllegalArgumentException("ds cannot be null"); } @@ -523,8 +540,11 @@ public abstract class AbstractFileSet extends DataType * @return whether any selectors are in this container. */ public synchronized boolean hasSelectors() { - return (isReference() && getProject() != null) - ? getRef(getProject()).hasSelectors() : !(selectors.isEmpty()); + if (isReference()) { + return getRef(getProject()).hasSelectors(); + } + dieOnCircularReference(); + return !(selectors.isEmpty()); } /** @@ -536,6 +556,7 @@ public abstract class AbstractFileSet extends DataType if (isReference() && getProject() != null) { return getRef(getProject()).hasPatterns(); } + dieOnCircularReference(); if (defaultPatterns.hasPatterns(getProject())) { return true; } @@ -555,8 +576,11 @@ public abstract class AbstractFileSet extends DataType * @return the number of selectors in this container as an int. */ public synchronized int selectorCount() { - return (isReference() && getProject() != null) - ? getRef(getProject()).selectorCount() : selectors.size(); + if (isReference()) { + return getRef(getProject()).selectorCount(); + } + dieOnCircularReference(); + return selectors.size(); } /** @@ -565,8 +589,11 @@ public abstract class AbstractFileSet extends DataType * @return a FileSelector[] of the selectors in this container. */ public synchronized FileSelector[] getSelectors(Project p) { - return (isReference()) - ? getRef(p).getSelectors(p) : (FileSelector[]) (selectors.toArray( + if (isReference()) { + return getRef(getProject()).getSelectors(p); + } + dieOnCircularReference(p); + return (FileSelector[]) (selectors.toArray( new FileSelector[selectors.size()])); } @@ -576,8 +603,11 @@ public abstract class AbstractFileSet extends DataType * @return an Enumeration of selectors. */ public synchronized Enumeration selectorElements() { - return (isReference() && getProject() != null) - ? getRef(getProject()).selectorElements() : selectors.elements(); + if (isReference()) { + return getRef(getProject()).selectorElements(); + } + dieOnCircularReference(); + return selectors.elements(); } /** @@ -591,6 +621,7 @@ public abstract class AbstractFileSet extends DataType } selectors.addElement(selector); directoryScanner = null; + setChecked(false); } /* Methods below all add specific selectors */ @@ -763,6 +794,10 @@ public abstract class AbstractFileSet extends DataType * @return a String of included filenames. */ public String toString() { + if (isReference()) { + return getRef(getProject()).toString(); + } + dieOnCircularReference(); DirectoryScanner ds = getDirectoryScanner(getProject()); String[] files = ds.getIncludedFiles(); StringBuffer sb = new StringBuffer(); @@ -840,6 +875,7 @@ public abstract class AbstractFileSet extends DataType if (isReference()) { return getRef(p).mergePatterns(p); } + dieOnCircularReference(); PatternSet ps = (PatternSet) defaultPatterns.clone(); final int count = additionalPatterns.size(); for (int i = 0; i < count; i++) { @@ -849,4 +885,21 @@ public abstract class AbstractFileSet extends DataType return ps; } + protected synchronized void dieOnCircularReference(Stack stk, Project p) + throws BuildException { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); + } else { + for (Iterator i = selectors.iterator(); i.hasNext(); ) { + Object o = i.next(); + if (o instanceof DataType) { + pushAndInvokeCircularReferenceCheck((DataType) o, stk, p); + } + } + setChecked(true); + } + } } diff --git a/src/main/org/apache/tools/ant/types/AntFilterReader.java b/src/main/org/apache/tools/ant/types/AntFilterReader.java index 737bcec68..64f6f027e 100644 --- a/src/main/org/apache/tools/ant/types/AntFilterReader.java +++ b/src/main/org/apache/tools/ant/types/AntFilterReader.java @@ -17,8 +17,10 @@ */ package org.apache.tools.ant.types; +import java.util.Stack; import java.util.Vector; import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; /** * An AntFilterReader is a wrapper class that encloses the classname @@ -39,6 +41,9 @@ public final class AntFilterReader * @param className a String value */ public void setClassName(final String className) { + if (isReference()) { + throw tooManyAttributes(); + } this.className = className; } @@ -48,6 +53,10 @@ public final class AntFilterReader * @return a String value */ public String getClassName() { + if (isReference()) { + return ((AntFilterReader) getCheckedRef()).getClassName(); + } + dieOnCircularReference(); return className; } @@ -57,6 +66,9 @@ public final class AntFilterReader * @param param a Parameter value */ public void addParam(final Parameter param) { + if (isReference()) { + throw noChildrenAllowed(); + } parameters.addElement(param); } @@ -73,6 +85,7 @@ public final class AntFilterReader } else { this.classpath.append(classpath); } + setChecked(false); } /** @@ -86,6 +99,7 @@ public final class AntFilterReader if (this.classpath == null) { this.classpath = new Path(getProject()); } + setChecked(false); return this.classpath.createPath(); } @@ -94,6 +108,10 @@ public final class AntFilterReader * @return the classpath */ public Path getClasspath() { + if (isReference()) { + ((AntFilterReader) getCheckedRef()).getClasspath(); + } + dieOnCircularReference(); return classpath; } @@ -115,6 +133,10 @@ public final class AntFilterReader * @return a Parameter[] value */ public Parameter[] getParams() { + if (isReference()) { + ((AntFilterReader) getCheckedRef()).getParams(); + } + dieOnCircularReference(); Parameter[] params = new Parameter[parameters.size()]; parameters.copyInto(params); return params; @@ -135,23 +157,21 @@ public final class AntFilterReader || classpath != null) { throw tooManyAttributes(); } - // change this to get the objects from the other reference - Object o = r.getReferencedObject(getProject()); - if (o instanceof AntFilterReader) { - AntFilterReader afr = (AntFilterReader) o; - setClassName(afr.getClassName()); - setClasspath(afr.getClasspath()); - Parameter[] p = afr.getParams(); - if (p != null) { - for (int i = 0; i < p.length; i++) { - addParam(p[i]); - } - } + super.setRefid(r); + } + + protected synchronized void dieOnCircularReference(Stack stk, Project p) + throws BuildException { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); } else { - String msg = r.getRefId() + " doesn\'t refer to a FilterReader"; - throw new BuildException(msg); + if (classpath != null) { + pushAndInvokeCircularReferenceCheck(classpath, stk, p); + } + setChecked(true); } - - super.setRefid(r); } } diff --git a/src/main/org/apache/tools/ant/types/FilterChain.java b/src/main/org/apache/tools/ant/types/FilterChain.java index 82999b605..ebfc1531a 100644 --- a/src/main/org/apache/tools/ant/types/FilterChain.java +++ b/src/main/org/apache/tools/ant/types/FilterChain.java @@ -17,9 +17,12 @@ */ package org.apache.tools.ant.types; +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.filters.ChainableReader; import org.apache.tools.ant.filters.ClassConstants; import org.apache.tools.ant.filters.EscapeUnicode; @@ -52,6 +55,10 @@ public class FilterChain extends DataType * @param filterReader an AntFilterReader value */ public void addFilterReader(final AntFilterReader filterReader) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(filterReader); } @@ -61,6 +68,10 @@ public class FilterChain extends DataType * @return a Vector value containing the filters */ public Vector getFilterReaders() { + if (isReference()) { + return ((FilterChain) getCheckedRef()).getFilterReaders(); + } + dieOnCircularReference(); return filterReaders; } @@ -70,6 +81,10 @@ public class FilterChain extends DataType * @param classConstants a ClassConstants value */ public void addClassConstants(final ClassConstants classConstants) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(classConstants); } @@ -79,6 +94,10 @@ public class FilterChain extends DataType * @param expandProperties an ExpandProperties value */ public void addExpandProperties(final ExpandProperties expandProperties) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(expandProperties); } @@ -88,6 +107,10 @@ public class FilterChain extends DataType * @param headFilter a HeadFilter value */ public void addHeadFilter(final HeadFilter headFilter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(headFilter); } @@ -97,6 +120,10 @@ public class FilterChain extends DataType * @param lineContains a LineContains value */ public void addLineContains(final LineContains lineContains) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(lineContains); } @@ -107,6 +134,10 @@ public class FilterChain extends DataType */ public void addLineContainsRegExp(final LineContainsRegExp lineContainsRegExp) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(lineContainsRegExp); } @@ -116,6 +147,10 @@ public class FilterChain extends DataType * @param prefixLines a PrefixLines value */ public void addPrefixLines(final PrefixLines prefixLines) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(prefixLines); } @@ -125,6 +160,10 @@ public class FilterChain extends DataType * @param replaceTokens a ReplaceTokens value */ public void addReplaceTokens(final ReplaceTokens replaceTokens) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(replaceTokens); } @@ -135,6 +174,10 @@ public class FilterChain extends DataType */ public void addStripJavaComments(final StripJavaComments stripJavaComments) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(stripJavaComments); } @@ -145,6 +188,10 @@ public class FilterChain extends DataType */ public void addStripLineBreaks(final StripLineBreaks stripLineBreaks) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(stripLineBreaks); } @@ -155,6 +202,10 @@ public class FilterChain extends DataType */ public void addStripLineComments(final StripLineComments stripLineComments) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(stripLineComments); } @@ -164,6 +215,10 @@ public class FilterChain extends DataType * @param tabsToSpaces a TabsToSpaces value */ public void addTabsToSpaces(final TabsToSpaces tabsToSpaces) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(tabsToSpaces); } @@ -173,6 +228,10 @@ public class FilterChain extends DataType * @param tailFilter a TailFilter value */ public void addTailFilter(final TailFilter tailFilter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(tailFilter); } @@ -183,6 +242,10 @@ public class FilterChain extends DataType * @since Ant 1.6 */ public void addEscapeUnicode(final EscapeUnicode escapeUnicode) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(escapeUnicode); } @@ -193,6 +256,10 @@ public class FilterChain extends DataType * @since Ant 1.6 */ public void addTokenFilter(final TokenFilter tokenFilter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(tokenFilter); } @@ -203,6 +270,10 @@ public class FilterChain extends DataType * @since Ant 1.6 */ public void addDeleteCharacters(TokenFilter.DeleteCharacters filter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(filter); } @@ -213,6 +284,10 @@ public class FilterChain extends DataType * @since Ant 1.6 */ public void addContainsRegex(TokenFilter.ContainsRegex filter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(filter); } @@ -222,6 +297,10 @@ public class FilterChain extends DataType * @param filter a TokenFilter.ReplaceRegex value */ public void addReplaceRegex(TokenFilter.ReplaceRegex filter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(filter); } @@ -232,6 +311,10 @@ public class FilterChain extends DataType * @since Ant 1.6 */ public void addTrim(TokenFilter.Trim filter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(filter); } @@ -243,6 +326,10 @@ public class FilterChain extends DataType */ public void addReplaceString( TokenFilter.ReplaceString filter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(filter); } @@ -254,6 +341,10 @@ public class FilterChain extends DataType */ public void addIgnoreBlank( TokenFilter.IgnoreBlank filter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(filter); } @@ -272,16 +363,6 @@ public class FilterChain extends DataType if (!filterReaders.isEmpty()) { throw tooManyAttributes(); } - // change this to get the objects from the other reference - Object o = r.getReferencedObject(getProject()); - if (o instanceof FilterChain) { - FilterChain fc = (FilterChain) o; - filterReaders = fc.getFilterReaders(); - } else { - String msg = r.getRefId() + " doesn\'t refer to a FilterChain"; - throw new BuildException(msg); - } - super.setRefid(r); } @@ -293,7 +374,28 @@ public class FilterChain extends DataType */ public void add(ChainableReader filter) { + if (isReference()) { + throw noChildrenAllowed(); + } + setChecked(false); filterReaders.addElement(filter); } + protected synchronized void dieOnCircularReference(Stack stk, Project p) + throws BuildException { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); + } else { + for (Iterator i = filterReaders.iterator(); i.hasNext(); ) { + Object o = i.next(); + if (o instanceof DataType) { + pushAndInvokeCircularReferenceCheck((DataType) o, stk, p); + } + } + setChecked(true); + } + } } diff --git a/src/main/org/apache/tools/ant/types/FilterSet.java b/src/main/org/apache/tools/ant/types/FilterSet.java index ee322d974..55cd6191f 100644 --- a/src/main/org/apache/tools/ant/types/FilterSet.java +++ b/src/main/org/apache/tools/ant/types/FilterSet.java @@ -218,6 +218,7 @@ public class FilterSet extends DataType implements Cloneable { if (isReference()) { return getRef().getFilters(); } + dieOnCircularReference(); //silly hack to avoid stack overflow... if (!readingFiles) { readingFiles = true; @@ -245,6 +246,10 @@ public class FilterSet extends DataType implements Cloneable { * @return The hash of the tokens and values for quick lookup. */ public synchronized Hashtable getFilterHash() { + if (isReference()) { + return getRef().getFilterHash(); + } + dieOnCircularReference(); if (filterHash == null) { filterHash = new Hashtable(getFilters().size()); for (Enumeration e = getFilters().elements(); e.hasMoreElements();) { diff --git a/src/main/org/apache/tools/ant/types/PropertySet.java b/src/main/org/apache/tools/ant/types/PropertySet.java index c39776001..2ac084398 100644 --- a/src/main/org/apache/tools/ant/types/PropertySet.java +++ b/src/main/org/apache/tools/ant/types/PropertySet.java @@ -23,6 +23,7 @@ import java.util.Iterator; import java.util.Map; import java.util.HashSet; import java.util.Set; +import java.util.Stack; import java.util.TreeMap; import java.util.Hashtable; import java.util.Properties; @@ -181,6 +182,7 @@ public class PropertySet extends DataType implements ResourceCollection { */ public void addPropertyref(PropertyRef ref) { assertNotReference(); + setChecked(false); ptyRefs.addElement(ref); } @@ -190,6 +192,7 @@ public class PropertySet extends DataType implements ResourceCollection { */ public void addPropertyset(PropertySet ref) { assertNotReference(); + setChecked(false); setRefs.addElement(ref); } @@ -203,6 +206,7 @@ public class PropertySet extends DataType implements ResourceCollection { throw new BuildException("Too many s!"); } mapper = new Mapper(getProject()); + setChecked(false); return mapper; } @@ -245,7 +249,11 @@ public class PropertySet extends DataType implements ResourceCollection { * @return true if the property set is to be evalulated each time it is used. */ public boolean getDynamic() { - return isReference() ? getRef().dynamic : dynamic; + if (isReference()) { + return getRef().dynamic; + } + dieOnCircularReference(); + return dynamic; } /** @@ -253,7 +261,11 @@ public class PropertySet extends DataType implements ResourceCollection { * @return the mapper attribute. */ public Mapper getMapper() { - return isReference() ? getRef().mapper : mapper; + if (isReference()) { + return getRef().mapper; + } + dieOnCircularReference(); + return mapper; } /** @@ -279,6 +291,7 @@ public class PropertySet extends DataType implements ResourceCollection { if (isReference()) { return getRef().getProperties(); } + dieOnCircularReference(); Set names = null; Project prj = getProject(); Hashtable props = @@ -343,6 +356,10 @@ public class PropertySet extends DataType implements ResourceCollection { * avoid needless duplication of the Hashtable during recursion. */ private void addPropertyNames(Set names, Hashtable properties) { + if (isReference()) { + getRef().addPropertyNames(names, properties); + } + dieOnCircularReference(); // Add this PropertySet's property names. for (Enumeration e = ptyRefs.elements(); e.hasMoreElements();) { PropertyRef r = (PropertyRef) e.nextElement(); @@ -453,6 +470,10 @@ public class PropertySet extends DataType implements ResourceCollection { * @return a string rep of this object. */ public String toString() { + if (isReference()) { + return getRef().toString(); + } + dieOnCircularReference(); StringBuffer b = new StringBuffer(); TreeMap sorted = new TreeMap(getProperties()); for (Iterator i = sorted.entrySet().iterator(); i.hasNext();) { @@ -473,6 +494,10 @@ public class PropertySet extends DataType implements ResourceCollection { * @since Ant 1.7 */ public Iterator iterator() { + if (isReference()) { + return getRef().iterator(); + } + dieOnCircularReference(); final Enumeration e = getProperties().propertyNames(); return new Iterator() { public boolean hasNext() { @@ -500,7 +525,30 @@ public class PropertySet extends DataType implements ResourceCollection { * @return whether this is a filesystem-only resource collection. */ public boolean isFilesystemOnly() { - return isReference() && getRef().isFilesystemOnly(); + if (isReference()) { + return getRef().isFilesystemOnly(); + } + dieOnCircularReference(); + return false; + } + + protected synchronized void dieOnCircularReference(Stack stk, Project p) + throws BuildException { + if (isChecked()) { + return; + } + if (isReference()) { + super.dieOnCircularReference(stk, p); + } else { + if (mapper != null) { + pushAndInvokeCircularReferenceCheck(mapper, stk, p); + } + for (Iterator i = setRefs.iterator(); i.hasNext(); ) { + pushAndInvokeCircularReferenceCheck((PropertySet) i.next(), stk, + p); + } + setChecked(true); + } } } diff --git a/src/main/org/apache/tools/ant/types/RedirectorElement.java b/src/main/org/apache/tools/ant/types/RedirectorElement.java index 507fbe2f1..479ff2a70 100755 --- a/src/main/org/apache/tools/ant/types/RedirectorElement.java +++ b/src/main/org/apache/tools/ant/types/RedirectorElement.java @@ -592,9 +592,7 @@ public class RedirectorElement extends DataType { if (v[i] != null) { for (Iterator fci = v[i].iterator(); fci.hasNext();) { FilterChain fc = (FilterChain) fci.next(); - stk.push(fc); - fc.dieOnCircularReference(stk, p); - stk.pop(); + pushAndInvokeCircularReferenceCheck(fc, stk, p); } } }