| @@ -285,6 +285,7 @@ Matthew Watson | |||
| Matthew Yanos | |||
| Matthias Bhend | |||
| Matthias Gutheil | |||
| Matthias Johann Vill | |||
| Michael Bayne | |||
| Michael Clarke | |||
| Michael Davey | |||
| @@ -1183,6 +1183,11 @@ | |||
| <first>Matthias</first> | |||
| <last>Gutheil</last> | |||
| </name> | |||
| <name> | |||
| <first>Matthias</first> | |||
| <middle>Johann</middle> | |||
| <last>Vill</last> | |||
| </name> | |||
| <name> | |||
| <first>Michael</first> | |||
| <last>Bayne</last> | |||
| @@ -1419,6 +1419,14 @@ of <a href="filelist.html"><code><filelist></code></a>.</p> | |||
| </td> | |||
| <td>No</td> | |||
| </tr> | |||
| <tr> | |||
| <td>preserveduplicates</td> | |||
| <td>Makes this <code>resourcelist</code> return all resources as | |||
| many times as they are specified. Otherwise | |||
| <code>resourcelist</code> will only return each resource, in the | |||
| order they first appear. <em>Since Ant 1.10.10</em></td> | |||
| <td>No</td> | |||
| </tr> | |||
| <tr> | |||
| <td>refid</td> | |||
| <td>Makes this <code>resourcelist</code> | |||
| @@ -0,0 +1,21 @@ | |||
| package org.apache.tools.ant.types.resources; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| /** | |||
| * Interface describing a collection of Resources, to which elements can be | |||
| * appended. | |||
| * | |||
| * @since Ant 1.10.10 | |||
| */ | |||
| public interface AppendableResourceCollection extends ResourceCollection { | |||
| /** | |||
| Add a ResourceCollection to the container. | |||
| @param c the ResourceCollection to add. | |||
| @throws BuildException on error. | |||
| @since Ant 1.10.10 | |||
| */ | |||
| void add(ResourceCollection c) throws BuildException; | |||
| } | |||
| @@ -37,7 +37,7 @@ import org.apache.tools.ant.types.ResourceCollection; | |||
| * @since Ant 1.7 | |||
| */ | |||
| public abstract class BaseResourceCollectionContainer | |||
| extends DataType implements ResourceCollection, Cloneable { | |||
| extends DataType implements AppendableResourceCollection, Cloneable { | |||
| private List<ResourceCollection> rc = new ArrayList<>(); | |||
| private Collection<Resource> coll = null; | |||
| private boolean cache = true; | |||
| @@ -92,6 +92,7 @@ public abstract class BaseResourceCollectionContainer | |||
| * @param c the ResourceCollection to add. | |||
| * @throws BuildException on error. | |||
| */ | |||
| @Override | |||
| public synchronized void add(ResourceCollection c) throws BuildException { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| @@ -47,14 +47,10 @@ import org.apache.tools.ant.types.ResourceCollection; | |||
| public class ResourceList extends DataType implements ResourceCollection { | |||
| private final Vector<FilterChain> filterChains = new Vector<>(); | |||
| private final ArrayList<ResourceCollection> textDocuments = new ArrayList<>(); | |||
| private final Union cachedResources = new Union(); | |||
| private volatile boolean cached = false; | |||
| private AppendableResourceCollection cachedResources = null; | |||
| private String encoding = null; | |||
| private File baseDir; | |||
| public ResourceList() { | |||
| cachedResources.setCache(true); | |||
| } | |||
| private boolean preserveDuplicates = false; | |||
| /** | |||
| * Adds a source. | |||
| @@ -116,6 +112,22 @@ public class ResourceList extends DataType implements ResourceCollection { | |||
| this.baseDir = baseDir; | |||
| } | |||
| /** | |||
| * Makes this <code>resourcelist</code> return all resources as | |||
| * many times as they are specified. Otherwise | |||
| * <code>resourcelist</code> will only return each resource, in the | |||
| * order they first appear. | |||
| * | |||
| * @param preserveDuplicates boolean | |||
| * @since Ant 1.10.10 | |||
| */ | |||
| public final void setPreserveDuplicates(boolean preserveDuplicates) { | |||
| if (isReference()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| this.preserveDuplicates = preserveDuplicates; | |||
| } | |||
| /** | |||
| * Makes this instance in effect a reference to another ResourceList | |||
| * instance. | |||
| @@ -207,20 +219,31 @@ public class ResourceList extends DataType implements ResourceCollection { | |||
| return getCheckedRef(ResourceList.class); | |||
| } | |||
| private AppendableResourceCollection newResourceCollection() { | |||
| if (preserveDuplicates) { | |||
| final Resources resources = new Resources(); | |||
| resources.setCache(true); | |||
| return resources; | |||
| } else { | |||
| final Union union = new Union(); | |||
| union.setCache(true); | |||
| return union; | |||
| } | |||
| } | |||
| private synchronized ResourceCollection cache() { | |||
| if (!cached) { | |||
| if (cachedResources == null) { | |||
| dieOnCircularReference(); | |||
| this.cachedResources = newResourceCollection(); | |||
| textDocuments.stream().flatMap(ResourceCollection::stream) | |||
| .map(this::read).forEach(cachedResources::add); | |||
| cached = true; | |||
| } | |||
| return cachedResources; | |||
| } | |||
| private ResourceCollection read(Resource r) { | |||
| try (BufferedReader reader = new BufferedReader(open(r))) { | |||
| Union streamResources = new Union(); | |||
| streamResources.setCache(true); | |||
| final AppendableResourceCollection streamResources = newResourceCollection(); | |||
| reader.lines().map(this::parse).forEach(streamResources::add); | |||
| return streamResources; | |||
| } catch (final IOException ioe) { | |||
| @@ -40,7 +40,7 @@ import org.apache.tools.ant.types.ResourceCollection; | |||
| * making no attempt to remove duplicates, or references another ResourceCollection. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Resources extends DataType implements ResourceCollection { | |||
| public class Resources extends DataType implements AppendableResourceCollection { | |||
| /** static empty ResourceCollection */ | |||
| public static final ResourceCollection NONE = new ResourceCollection() { | |||
| @Override | |||
| @@ -156,6 +156,7 @@ public class Resources extends DataType implements ResourceCollection { | |||
| * Add a ResourceCollection. | |||
| * @param c the ResourceCollection to add. | |||
| */ | |||
| @Override | |||
| public synchronized void add(ResourceCollection c) { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| @@ -101,4 +101,41 @@ ${input}/c.txt</echo> | |||
| </copy> | |||
| <au:assertFileExists file="${output}/antlib.xml"/> | |||
| </target> | |||
| <target name="testDuplicatesRemoved" depends="setUp"> | |||
| <echo file="${input}/a.txt">${input}/b.txt | |||
| ${input}/b.txt</echo> | |||
| <echo file="${input}/b.txt">Demo content</echo> | |||
| <echo file="${input}/c.txt">${input}/b.txt | |||
| ${input}/b.txt</echo> | |||
| <pathconvert property="1b" pathsep="|" preserveduplicates="true"> | |||
| <flattenmapper/> | |||
| <resourcelist> | |||
| <resources> | |||
| <file file="${input}/a.txt"/> | |||
| <file file="${input}/c.txt"/> | |||
| </resources> | |||
| </resourcelist> | |||
| </pathconvert> | |||
| <au:assertPropertyEquals name="1b" value="b.txt"/> | |||
| </target> | |||
| <target name="testDuplicatesPreserved" depends="setUp"> | |||
| <echo file="${input}/a.txt">${input}/b.txt | |||
| ${input}/b.txt</echo> | |||
| <echo file="${input}/b.txt">Demo content</echo> | |||
| <echo file="${input}/c.txt">${input}/b.txt | |||
| ${input}/b.txt</echo> | |||
| <pathconvert property="4bs" pathsep="|" preserveduplicates="true"> | |||
| <flattenmapper/> | |||
| <resourcelist preserveduplicates="true"> | |||
| <resources> | |||
| <file file="${input}/a.txt"/> | |||
| <file file="${input}/a.txt"/> | |||
| <file file="${input}/c.txt"/> | |||
| </resources> | |||
| </resourcelist> | |||
| </pathconvert> | |||
| <au:assertPropertyEquals name="4bs" value="b.txt|b.txt|b.txt|b.txt|b.txt|b.txt"/> | |||
| </target> | |||
| </project> | |||