summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatt Benson <mbenson@apache.org>2022-02-09 13:00:49 -0600
committerMatt Benson <mbenson@apache.org>2022-02-09 13:00:49 -0600
commit90ed3ff6cca8634e38d7c3c82858ce48c9c4be2b (patch)
tree17a53c9f6ed4304cf566bfe315451abe800f4f01 /src
parentaf035b0fc772cff76cd3c5879012cf8c91f7ae4e (diff)
downloadant-90ed3ff6cca8634e38d7c3c82858ce48c9c4be2b.tar.gz
pathconvert to outputstream so that logging requires no in-memory String accumulation
Diffstat (limited to 'src')
-rw-r--r--src/main/org/apache/tools/ant/taskdefs/PathConvert.java126
1 files changed, 60 insertions, 66 deletions
diff --git a/src/main/org/apache/tools/ant/taskdefs/PathConvert.java b/src/main/org/apache/tools/ant/taskdefs/PathConvert.java
index fa68c3f2e..be46bbdd2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/PathConvert.java
+++ b/src/main/org/apache/tools/ant/taskdefs/PathConvert.java
@@ -18,10 +18,16 @@
package org.apache.tools.ant.taskdefs;
import java.io.File;
-import java.util.ArrayList;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
import java.util.List;
-import java.util.StringTokenizer;
+import java.util.Objects;
import java.util.Vector;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
@@ -31,12 +37,12 @@ import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.Mapper;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
-import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.Resources;
import org.apache.tools.ant.types.resources.Union;
import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.ant.util.IdentityMapper;
+import org.apache.tools.ant.util.PropertyOutputStream;
/**
* Converts path and classpath information to a specific target OS
@@ -195,7 +201,7 @@ public class PathConvert extends Task {
private synchronized Resources getPath() {
if (path == null) {
path = new Resources(getProject());
- path.setCache(true);
+ path.setCache(false);
}
return path;
}
@@ -344,56 +350,18 @@ public class PathConvert extends Task {
}
validateSetup(); // validate our setup
- // Currently, we deal with only two path formats: Unix and Windows
- // And Unix is everything that is not Windows
- // (with the exception for NetWare and OS/2 below)
-
- // for NetWare and OS/2, piggy-back on Windows, since here and
- // in the apply code, the same assumptions can be made as with
- // windows - that \\ is an OK separator, and do comparisons
- // case-insensitive.
- String fromDirSep = onWindows ? "\\" : "/";
-
- StringBuilder rslt = new StringBuilder();
-
- ResourceCollection resources = isPreserveDuplicates() ? path : new Union(path);
- List<String> ret = new ArrayList<>();
- FileNameMapper mapperImpl = mapper == null ? new IdentityMapper() : mapper.getImplementation();
- for (Resource r : resources) {
- String[] mapped = mapperImpl.mapFileName(String.valueOf(r));
- for (int m = 0; mapped != null && m < mapped.length; ++m) {
- ret.add(mapped[m]);
- }
- }
boolean first = true;
- for (String string : ret) {
- String elem = mapElement(string); // Apply the path prefix map
-
- // Now convert the path and file separator characters from the
- // current os to the target os.
-
- if (!first) {
- rslt.append(pathSep);
- }
- first = false;
-
- StringTokenizer stDirectory = new StringTokenizer(elem, fromDirSep, true);
-
- while (stDirectory.hasMoreTokens()) {
- String token = stDirectory.nextToken();
- rslt.append(fromDirSep.equals(token) ? dirSep : token);
- }
- }
- // Place the result into the specified property,
- // unless setonempty == false
- if (setonempty || rslt.length() > 0) {
- String value = rslt.toString();
- if (property == null) {
- log(value);
- } else {
- log("Set property " + property + " = " + value, Project.MSG_VERBOSE);
- getProject().setNewProperty(property, value);
+ try (Writer w = new OutputStreamWriter(createOutputStream())) {
+ for (String s : (Iterable<String>) streamResources()::iterator) {
+ if (first) {
+ first = false;
+ } else {
+ w.write(pathSep);
+ }
+ w.write(s);
}
+ } catch (IOException e) {
+ throw new BuildException(e);
}
} finally {
path = savedPath;
@@ -402,6 +370,44 @@ public class PathConvert extends Task {
}
}
+ private OutputStream createOutputStream() {
+ if (property == null) {
+ return new LogOutputStream(this);
+ }
+ return new PropertyOutputStream(getProject(), property) {
+ @Override
+ public void close() {
+ if (setonempty || size() > 0) {
+ super.close();
+ log("Set property " + property + " = " + getProject().getProperty(property), Project.MSG_VERBOSE);
+ }
+ }
+ };
+ }
+
+ private Stream<String> streamResources() {
+ ResourceCollection resources = isPreserveDuplicates() ? path : Union.getInstance(path);
+ FileNameMapper mapperImpl = mapper == null ? new IdentityMapper() : mapper.getImplementation();
+
+ final boolean parallel = false;
+ Stream<String> result = StreamSupport.stream(resources.spliterator(), parallel).map(String::valueOf)
+ .map(mapperImpl::mapFileName).filter(Objects::nonNull).flatMap(Stream::of).map(this::mapElement);
+
+ // Currently, we deal with only two path formats: Unix and Windows
+ // And Unix is everything that is not Windows
+ // (with the exception for NetWare and OS/2 below)
+
+ // for NetWare and OS/2, piggy-back on Windows, since here and
+ // in the apply code, the same assumptions can be made as with
+ // windows - that \\ is an OK separator, and do comparisons
+ // case-insensitive.
+ final String fromDirSep = onWindows ? "\\" : "/";
+ if (fromDirSep.equals(dirSep)) {
+ return result;
+ }
+ return result.map(s -> s.replace(fromDirSep, dirSep));
+ }
+
/**
* Apply the configured map to a path element. The map is used to convert
* between Windows drive letters and Unix paths. If no map is configured,
@@ -411,20 +417,8 @@ public class PathConvert extends Task {
* @return String Updated element.
*/
private String mapElement(String elem) {
- // Iterate over the map entries and apply each one.
- // Stop when one of the entries actually changes the element.
-
- for (MapEntry entry : prefixMap) {
- String newElem = entry.apply(elem);
-
- // Note I'm using "!=" to see if we got a new object back from
- // the apply method.
-
- if (newElem != elem) {
- return newElem;
- }
- }
- return elem;
+ final Predicate<Object> changed = o -> o != elem;
+ return prefixMap.stream().map(e -> e.apply(elem)).filter(changed).findFirst().orElse(elem);
}
/**