/* * WorldEdit, a Minecraft world manipulation toolkit * Copyright (C) sk89q * Copyright (C) WorldEdit team and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.sk89q.worldedit.util.io.file; import com.google.common.collect.ImmutableList; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Optional; import java.util.ServiceLoader; import java.util.stream.Stream; public class ArchiveNioSupports { private static final List SUPPORTS; static { ImmutableList.Builder builder = ImmutableList.builder(); SUPPORTS = builder.add(ZipArchiveNioSupport.getInstance()) .addAll(ServiceLoader.load(ArchiveNioSupport.class)) .build(); } public static Optional tryOpenAsDir(Path archive) throws IOException { for (ArchiveNioSupport support : SUPPORTS) { Optional fs = support.tryOpenAsDir(archive); if (fs.isPresent()) { return fs; } } return Optional.empty(); } private static final ArchiveNioSupport COMBINED = ArchiveNioSupports::tryOpenAsDir; /** * Get an {@link ArchiveNioSupport} that combines all known instances. * @return a combined {@link ArchiveNioSupport} instance */ public static ArchiveNioSupport combined() { return COMBINED; } /** * If root contains a folder with the same name as {@code name}, and no regular files, * returns the path to that folder. Otherwise, return the root path. * *

* This method is used to provide equal outputs for archives that do and do not contain * their name as part of their root folder. *

* * @param root the root path * @param name the name that might exist inside root * @return the corrected path */ public static Path skipRootSameName(Path root, String name) throws IOException { Path innerDir = root.resolve(name); if (Files.isDirectory(innerDir)) { try (Stream files = Files.list(root)) { // The reason we check this, is that macOS creates a __MACOSX directory inside // its zip files. We want to allow this to pass if that exists, or a similar // mechanism, but fail if there are regular files, since that indicates that // it may not be the right thing to do. if (files.allMatch(Files::isDirectory)) { return innerDir; } } } return root; } private ArchiveNioSupports() { } }