public void unpack()

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);
        }
    }