in arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/archive/Extractor.java [55:138]
public void unpack(final Path archive, final Path exploded) {
try {
final boolean isZip = archive.getFileName().toString().endsWith(".zip");
final InputStream fileStream = new BufferedInputStream(Files.newInputStream(archive));
final Predicate<ArchiveEntry> isLink = isZip ?
e -> ZipArchiveEntry.class.cast(e).isUnixSymlink() :
e -> TarArchiveEntry.class.cast(e).isSymbolicLink();
final BiFunction<ArchiveInputStream, ArchiveEntry, String> linkPath = isZip ?
(a, e) -> { // todo: validate this with cygwin
try {
return new BufferedReader(new InputStreamReader(a)).readLine();
} catch (final IOException ex) {
throw new IllegalStateException(ex);
}
} :
(a, e) -> TarArchiveEntry.class.cast(e).getLinkName();
final Map<Path, Path> linksToCopy = new HashMap<>();
final Map<Path, Path> linksToRetry = new HashMap<>();
try (final ArchiveInputStream archiveInputStream = isZip ?
new ZipArchiveInputStream(fileStream) :
new TarArchiveInputStream(new GzipCompressorInputStream(fileStream))) {
ArchiveEntry entry;
while ((entry = archiveInputStream.getNextEntry()) != null) {
final String entryName = entry.getName();
if (!archiveInputStream.canReadEntryData(entry)) {
log.error("Can't read '" + entryName + "'");
continue;
}
final int sep = entryName.indexOf('/');
if (sep == entryName.length() || sep < 0) { // first level folder, skip
continue;
}
final Path target = exploded.resolve(entryName.substring(sep + 1));
if (entry.isDirectory()) {
ensureExists(target);
} else {
ensureExists(target.getParent());
if (isLink.test(entry)) {
final Path targetLinked = Paths.get(linkPath.apply(archiveInputStream, entry));
if (Files.exists(target.getParent().resolve(targetLinked))) {
try {
Files.createSymbolicLink(target, targetLinked);
setExecutableIfNeeded(target);
} catch (final IOException ioe) {
linksToCopy.put(target, targetLinked);
}
} else {
linksToRetry.put(target, targetLinked);
}
} else {
Files.copy(archiveInputStream, target, StandardCopyOption.REPLACE_EXISTING);
Files.setLastModifiedTime(target, FileTime.fromMillis(entry.getLastModifiedDate().getTime()));
setExecutableIfNeeded(target);
}
}
}
}
linksToRetry.forEach((target, targetLinked) -> {
try {
Files.createSymbolicLink(target, targetLinked);
setExecutableIfNeeded(target);
} catch (final IOException ioe) {
linksToCopy.put(target, targetLinked);
}
});
linksToCopy.forEach((target, targetLinked) -> {
final Path actualTarget = target.getParent().resolve(targetLinked);
if (!Files.exists(actualTarget)) {
log.warn("No file '" + targetLinked + "' found, skipping link");
return;
}
try {
Files.copy(actualTarget, target, StandardCopyOption.REPLACE_EXISTING);
setExecutableIfNeeded(target);
} catch (final IOException e) {
throw new IllegalStateException(e);
}
});
} catch (final IOException e) {
throw new IllegalStateException("Can't unpack graal archive", e);
}
}