Merge pull request #237 from apache/mappedresources-npe-fix
Avoid NPE in <mappedresources>
diff --git a/WHATSNEW b/WHATSNEW
index 23fb76d..ffcb2c0 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -54,6 +54,10 @@
fixed.
Bugzilla Report 70158
+ * <mappedresources> with "enableMultipleMappings" set to "true" threw
+ a NullPointerException if the mapper didn't apply to one of the
+ resources. Unmapped resources are now omitted from the collection.
+
Changes from Ant 1.10.16 TO Ant 1.10.17
=======================================
diff --git a/src/main/org/apache/tools/ant/types/resources/MappedResourceCollection.java b/src/main/org/apache/tools/ant/types/resources/MappedResourceCollection.java
index 544c60b..6c5b9e9 100644
--- a/src/main/org/apache/tools/ant/types/resources/MappedResourceCollection.java
+++ b/src/main/org/apache/tools/ant/types/resources/MappedResourceCollection.java
@@ -20,7 +20,6 @@
import java.io.File;
import java.util.Collection;
import java.util.Iterator;
-import java.util.Objects;
import java.util.Stack;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -237,10 +236,15 @@
Stream<MappedResource> stream;
if (enableMultipleMappings) {
stream = nested.stream()
- .flatMap(r -> Stream.of(m.mapFileName(r.getName()))
- .filter(Objects::nonNull)
- .map(MergingMapper::new)
- .map(mm -> new MappedResource(r, mm)));
+ .flatMap(r -> {
+ String[] names = m.mapFileName(r.getName());
+ if (names == null) {
+ return Stream.empty();
+ }
+ return Stream.of(names)
+ .map(MergingMapper::new)
+ .map(mm -> new MappedResource(r, mm));
+ });
} else {
stream = nested.stream().map(r -> new MappedResource(r, m));
}
diff --git a/src/tests/antunit/types/resources/mappedresources-test.xml b/src/tests/antunit/types/resources/mappedresources-test.xml
new file mode 100644
index 0000000..4752554
--- /dev/null
+++ b/src/tests/antunit/types/resources/mappedresources-test.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
+
+ <import file="../../antunit-base.xml"/>
+
+ <target name="setUp">
+ <echo file="${input}/a.txt">a</echo>
+ <echo file="${input}/b.dat">b</echo>
+ <echo file="${input}/c.txt">c</echo>
+ </target>
+
+ <target name="testMultipleMappingsSkipsUnmappedResources">
+ <mappedresources id="mapped" enableMultipleMappings="true">
+ <filelist dir="${input}" files="a.txt,b.dat,c.txt"/>
+ <globmapper from="*.txt" to="*.bak"/>
+ </mappedresources>
+ <resourcecount property="count">
+ <mappedresources refid="mapped"/>
+ </resourcecount>
+ <au:assertPropertyEquals name="count" value="2"/>
+ <pathconvert property="names" pathsep=",">
+ <mappedresources refid="mapped"/>
+ </pathconvert>
+ <au:assertPropertyEquals name="names" value="a.bak,c.bak"/>
+ </target>
+
+ <target name="testMultipleMappingsIsEmptyWhenNothingMaps">
+ <mappedresources id="mapped" enableMultipleMappings="true">
+ <filelist dir="${input}" files="a.txt,b.dat,c.txt"/>
+ <globmapper from="*.nomatch" to="*.bak"/>
+ </mappedresources>
+ <resourcecount property="count">
+ <mappedresources refid="mapped"/>
+ </resourcecount>
+ <au:assertPropertyEquals name="count" value="0"/>
+ <au:assertEquals expected="" actual="${toString:mapped}"/>
+ </target>
+
+ <target name="testMultipleMappingsKeepsEveryMappedName">
+ <mappedresources id="mapped" enableMultipleMappings="true">
+ <filelist dir="${input}" files="a.txt,b.dat"/>
+ <compositemapper>
+ <globmapper from="a.*" to="one.*"/>
+ <globmapper from="a.*" to="two.*"/>
+ </compositemapper>
+ </mappedresources>
+ <resourcecount property="count">
+ <mappedresources refid="mapped"/>
+ </resourcecount>
+ <au:assertPropertyEquals name="count" value="2"/>
+ <pathconvert property="names" pathsep=",">
+ <mappedresources refid="mapped"/>
+ </pathconvert>
+ <au:assertPropertyEquals name="names" value="one.txt,two.txt"/>
+ </target>
+
+ <target name="testMultipleMappingsWithCachingIsStableAcrossIterations">
+ <mappedresources id="mapped" enableMultipleMappings="true" cache="true">
+ <filelist dir="${input}" files="a.txt,b.dat,c.txt"/>
+ <globmapper from="*.txt" to="*.bak"/>
+ </mappedresources>
+ <pathconvert property="first" pathsep=",">
+ <mappedresources refid="mapped"/>
+ </pathconvert>
+ <pathconvert property="second" pathsep=",">
+ <mappedresources refid="mapped"/>
+ </pathconvert>
+ <au:assertPropertyEquals name="first" value="a.bak,c.bak"/>
+ <au:assertPropertyEquals name="second" value="a.bak,c.bak"/>
+ </target>
+
+ <target name="testCopyWithNonMatchingMapper">
+ <mkdir dir="${output}"/>
+ <copy todir="${output}">
+ <mappedresources enableMultipleMappings="true">
+ <filelist dir="${input}" files="a.txt,b.dat,c.txt"/>
+ <globmapper from="*.dat" to="*.copied"/>
+ </mappedresources>
+ </copy>
+ <au:assertFileExists file="${output}/b.copied"/>
+ <au:assertFileDoesntExist file="${output}/a.txt"/>
+ <au:assertFileDoesntExist file="${output}/a.copied"/>
+ <au:assertFilesMatch expected="${input}/b.dat"
+ actual="${output}/b.copied"/>
+ </target>
+</project>