silentbalanceyh/vertx-zero

View on GitHub
vertx-gaia/vertx-ams/src/main/java/io/horizon/util/IoDirectory.java

Summary

Maintainability
C
1 day
Test Coverage
package io.horizon.util;

import io.horizon.eon.VPath;
import io.horizon.eon.VString;
import io.horizon.fn.HFn;

import java.io.File;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;

final class IoDirectory {
    private static final LogUtil LOG = LogUtil.from(IoDirectory.class);

    private IoDirectory() {
    }

    static List<String> listFiles(final String folder, final String extension) {
        return HFn.runOr(new ArrayList<>(), () -> list(folder, extension, false), folder);
    }

    static List<String> listDirectories(final String folder) {
        return HFn.runOr(new ArrayList<>(), () -> list(folder, null, true), folder);
    }

    static List<String> listFilesN(final String folder, final String extension, final String prefix) {
        final List<String> folders = listDirectoriesN(folder);
        return folders.stream()
            .flatMap(single -> list(single, extension, false)
                .stream()
                .filter(file -> TIs.isNil(prefix) || file.contains(prefix))
                .map(file -> {
                    if (single.endsWith("/")) {
                        return single + file;
                    } else {
                        return single + "/" + file;
                    }
                }))
            .filter(file -> {
                final InputStream in = IoStream.readDirect(file);
                return Objects.nonNull(in);
            })
            .collect(Collectors.toList());
    }

    static List<String> listDirectoriesN(final String folder) {
        final String root = IoPath.root();
        LOG.info("List directories: root = {0}, folder = {1}", root, folder);
        return HFn.runOr(new ArrayList<>(), () -> listDirectoriesN(folder, root), folder);
    }

    private static List<String> listDirectoriesN(final String folder, final String root) {
        final List<String> folders = new ArrayList<>();
        // root + folder
        File folderObj = new File(IoPath.resolve(root, folder));
        if (!folderObj.exists()) {
            final URL url = Io.ioURL(folder);
            if (Objects.nonNull(url)) {
                // Url Processing to File
                folderObj = new File(url.getPath());
            } else {
                LOG.warn("URL is null, please check your path here.");
                folderObj = null;
            }
        }
        if (Objects.nonNull(folderObj) && folderObj.isDirectory()) {
            folders.add(folder);
            // Else
            final String[] folderList = folderObj.list();
            assert folderList != null;
            final String relatedPath = folderObj.getAbsolutePath().replace("\\", "/");
            Arrays.stream(folderList).forEach(folderS -> {
                final String rootCopy = root.replace("\\", "/");
                final String pathReplaced = relatedPath.replace(rootCopy, VString.EMPTY);
                folders.addAll(listDirectoriesN(pathReplaced + "/" + folderS, root));
            });
            LOG.info("Directories found: size = {0}", String.valueOf(folders.size()));
        }
        return folders;
    }

    private static List<String> list(final String folder,
                                     final String extension,
                                     final boolean isDirectory) {
        /*
         * list folder by related file first
         * /folder here
         */
        final File folderObj = new File(folder);
        final Set<String> retSet = new TreeSet<>();
        if (folderObj.exists()) {
            /*
             * Related path here, it means that
             * such as /folder/extra/ etc.
             */
            retSet.addAll(getFiles(folderObj, extension, isDirectory));
        } else {
            URL url = Io.ioURL(folder);
            if (Objects.isNull(url)) {
                /*
                 * Fix jar path issue here.
                 */
                if (folder.contains(VPath.SUFFIX.JAR_DIVIDER)) {
                    url = HFn.failOr(() -> new URL(folder), folder);
                }
            }
            /*
             * Split steps for url extraction
             */
            if (Objects.isNull(url)) {
                LOG.info("The url of folder = `{0}` is null", folder);
            } else {
                /*
                 * Whether it's jar path or common path.
                 */
                final String protocol = url.getProtocol();
                if (VPath.PROTOCOL.FILE.equals(protocol)) {
                    /*
                     * Common file
                     */
                    retSet.addAll(getFiles(url, extension, isDirectory));
                } else if (VPath.PROTOCOL.JAR.equals(protocol)) {
                    /*
                     * Jar File
                     */
                    retSet.addAll(getJars(url, extension, isDirectory));
                } else {
                    LOG.error("protocol error! protocol = {0}, url = {1}", protocol, url);
                }
            }
        }
        return new ArrayList<>(retSet);
    }

    static List<String> getJars(final URL url, final String extension, final boolean isDirectory) {
        return HFn.failOr(() -> {
            final JarURLConnection jarCon = (JarURLConnection) url.openConnection();
            final JarFile jarFile = jarCon.getJarFile();
            /*
             * JarEntry iterator
             */
            final String[] specifics = url.getPath().split("!/");
            final String folder = specifics[1];     // Jar Specification
            if (isDirectory) {
                /*
                 * Get folder entry
                 */
                return getJarDirectories(jarFile, folder);
            } else {
                /*
                 * Get file entry
                 */
                return getJarFiles(jarFile, folder, extension);
            }
        }, url);
    }

    private static List<String> getJarDirectories(final JarFile jarFile, final String folder) {
        final List<String> retList = new ArrayList<>();
        final Enumeration<JarEntry> entities = jarFile.entries();
        while (entities.hasMoreElements()) {
            final JarEntry entry = entities.nextElement();
            /*
             * First, we must filter the folder
             */
            final String entryName = entry.getName();
            final String filtered = folder + "/";
            if (entryName.startsWith(folder) && entry.isDirectory()
                && !filtered.equals(entryName)  // This condition is for folder only
            ) {
                /*
                 * The condition is ok to pickup folder only
                 * Because folder is end with '/', it means that you must replace the last folder
                 */
                final String replaced = entryName.substring(0, entryName.lastIndexOf('/'));
                final String found = replaced.substring(replaced.lastIndexOf('/') + 1);
                if (!TIs.isNil(found)) {
                    retList.add(found);
                }
            }
        }
        return retList;
    }

    private static List<String> getJarFiles(final JarFile jarFile, final String folder, final String extension) {
        final List<String> retList = new ArrayList<>();
        final Enumeration<JarEntry> entities = jarFile.entries();
        while (entities.hasMoreElements()) {
            final JarEntry entry = entities.nextElement();
            /*
             * First, we must filter the folder
             */
            final String entryName = entry.getName();
            if (entryName.startsWith(folder) && !entry.isDirectory()) {
                if (Objects.isNull(extension)) {
                    /*
                     * No Extension
                     */
                    final String foundFile = entryName.substring(entryName.lastIndexOf('/') + 1);
                    if (!TIs.isNil(foundFile)) {
                        retList.add(foundFile);
                    }
                } else {
                    if (entryName.endsWith(extension)) {
                        /*
                         * Extension enabled
                         */
                        final String foundFile = entryName.substring(entryName.lastIndexOf('/') + 1);
                        if (!TIs.isNil(foundFile)) {
                            retList.add(foundFile);
                        }
                    }
                }
            }
        }
        return retList;
    }

    private static List<String> getFiles(final File directory, final String extension, final boolean isDirectory) {
        final List<String> retList = new ArrayList<>();
        if (directory.isDirectory() && directory.exists()) {
            final File[] files = (isDirectory) ?
                directory.listFiles(File::isDirectory) :
                (null == extension ?
                    directory.listFiles(File::isFile) :
                    directory.listFiles((item) -> item.isFile() && item.getName().endsWith(extension)));
            if (null != files) {
                retList.addAll(Arrays.stream(files)
                    .map(File::getName)
                    .collect(Collectors.toList()));
            }
        } else {
            LOG.error("The file doest not exist, file = `{0}`", directory.getAbsolutePath());
        }
        return retList;
    }

    private static List<String> getFiles(final URL url, final String extension, final boolean isDirectory) {
        final File directory = new File(url.getFile());
        return getFiles(directory, extension, isDirectory);
    }
}