diff --git a/src/main/org/apache/tools/ant/types/resources/Resources.java b/src/main/org/apache/tools/ant/types/resources/Resources.java index cf6bc03bc..b00f061f7 100644 --- a/src/main/org/apache/tools/ant/types/resources/Resources.java +++ b/src/main/org/apache/tools/ant/types/resources/Resources.java @@ -26,8 +26,13 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.Spliterator; +import java.util.Spliterators; import java.util.Stack; import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; @@ -61,10 +66,8 @@ public class Resources extends DataType implements AppendableResourceCollection public static final Iterator EMPTY_ITERATOR = Collections.emptyIterator(); private class MyCollection extends AbstractCollection { - private Collection cached; + private volatile Collection cached; - MyCollection() { - } @Override public int size() { return getCache().size(); @@ -74,45 +77,41 @@ public class Resources extends DataType implements AppendableResourceCollection return getCache().iterator(); } private synchronized Collection getCache() { - Collection coll = cached; - if (coll == null) { - coll = new ArrayList<>(); - new MyIterator().forEachRemaining(coll::add); - if (cache) { - cached = coll; - } + if (cached == null) { + cached = internalResources().collect(Collectors.toList()); } - return coll; + return cached; } - private class MyIterator implements Iterator { - private Iterator rci = getNested().iterator(); - private Iterator ri = null; + } - @Override - public boolean hasNext() { - boolean result = ri != null && ri.hasNext(); - while (!result && rci.hasNext()) { - ri = rci.next().iterator(); - result = ri.hasNext(); - } - return result; - } - @Override - public Resource next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - return ri.next(); + private class MyIterator implements Iterator { + private Iterator rci = getNested().iterator(); + private Iterator ri; + + @Override + public boolean hasNext() { + boolean result = ri != null && ri.hasNext(); + while (!result && rci.hasNext()) { + ri = rci.next().iterator(); + result = ri.hasNext(); } - @Override - public void remove() { - throw new UnsupportedOperationException(); + return result; + } + @Override + public Resource next() { + if (!hasNext()) { + throw new NoSuchElementException(); } + return ri.next(); + } + @Override + public void remove() { + throw new UnsupportedOperationException(); } } private List rc; - private Collection coll; + private Optional> cacheColl = Optional.empty(); private volatile boolean cache = false; /** @@ -156,7 +155,7 @@ public class Resources extends DataType implements AppendableResourceCollection } rc.add(c); invalidateExistingIterators(); - coll = null; + cacheColl = Optional.empty(); setChecked(false); } @@ -170,7 +169,7 @@ public class Resources extends DataType implements AppendableResourceCollection return getRef().iterator(); } validate(); - return new FailFast(this, coll.iterator()); + return new FailFast(this, cacheColl.map(Iterable::iterator).orElseGet(MyIterator::new)); } /** @@ -183,7 +182,7 @@ public class Resources extends DataType implements AppendableResourceCollection return getRef().size(); } validate(); - return coll.size(); + return cacheColl.isPresent() ? cacheColl.get().size() : (int) internalResources().count(); } /** @@ -196,8 +195,7 @@ public class Resources extends DataType implements AppendableResourceCollection return getRef().isFilesystemOnly(); } validate(); - return getNested().stream() - .allMatch(ResourceCollection::isFilesystemOnly); + return getNested().stream().allMatch(ResourceCollection::isFilesystemOnly); } /** @@ -210,11 +208,8 @@ public class Resources extends DataType implements AppendableResourceCollection return getRef().toString(); } validate(); - if (coll == null || coll.isEmpty()) { - return ""; - } - return coll.stream().map(Object::toString) - .collect(Collectors.joining(File.pathSeparator)); + final Stream stream = cache ? cacheColl.get().stream() : getNested().stream(); + return stream.map(String::valueOf).collect(Collectors.joining(File.pathSeparator)); } /** @@ -227,17 +222,13 @@ public class Resources extends DataType implements AppendableResourceCollection @Override protected void dieOnCircularReference(Stack stk, Project p) throws BuildException { - if (isChecked()) { - return; - } if (isReference()) { super.dieOnCircularReference(stk, p); - } else { - for (ResourceCollection resourceCollection : getNested()) { - if (resourceCollection instanceof DataType) { - pushAndInvokeCircularReferenceCheck((DataType) resourceCollection, stk, p); - } - } + return; + } + if (!isChecked()) { + getNested().stream().filter(DataType.class::isInstance).map(DataType.class::cast) + .forEach(dt -> pushAndInvokeCircularReferenceCheck(dt, stk, p)); setChecked(true); } } @@ -259,10 +250,17 @@ public class Resources extends DataType implements AppendableResourceCollection private synchronized void validate() { dieOnCircularReference(); - coll = (coll == null) ? new MyCollection() : coll; + if (cache && !cacheColl.isPresent()) { + cacheColl = Optional.of(new MyCollection()); + } } private synchronized List getNested() { return rc == null ? Collections.emptyList() : rc; } + + private synchronized Stream internalResources() { + return StreamSupport.stream( + Spliterators.spliteratorUnknownSize(new MyIterator(), Spliterator.NONNULL), false); + } }