|
|
@@ -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); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|