All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.wizard.common.utils.SearchPathUtils Maven / Gradle / Ivy

package org.bidib.wizard.common.utils;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOCase;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.bidib.jbidibc.messages.SoftwareVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

public class SearchPathUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(SearchPathUtils.class);

    public static List findFiles(String fileName, boolean searchSubDirs, String... searchPaths) {

        LOGGER.debug("Find files in searchPaths: {}", new Object[] { searchPaths });

        final List files = new LinkedList<>();

        for (String searchPath : searchPaths) {

            LOGGER.debug("Prepared filename to load file: {}", fileName.toString());

            if (searchPath.startsWith("classpath:")) {
                // search in the classpath
                int beginIndex = "classpath:".length();
                String lookup = "/" + searchPath.substring(beginIndex);
                lookup = lookup.replaceAll("\\\\", "/");
                LOGGER.info("Lookup file internally: {}", lookup);

                URL pathString = SearchPathUtils.class.getResource(lookup);
                LOGGER.info("Prepared pathString: {}", pathString);

                if (pathString == null) {
                    LOGGER.info("No resource for lookup '{}' found.", lookup);
                    continue;
                }

                FileSystem fs = null;
                try {

                    URI lookupURI = pathString.toURI();
                    LOGGER.info("Prepared lookupURI: {}", lookupURI);

                    final String[] array = lookupURI.toString().split("!");

                    Path path = null;
                    if (array.length > 1) {
                        final Map env = new HashMap<>();
                        LOGGER.debug("Create new filesystem for: {}", array[0]);
                        fs = FileSystems.newFileSystem(URI.create(array[0]), env);
                        path = fs.getPath(array[1]);
                        LOGGER.debug("Prepared path: {}", path);
                    }
                    else {
                        path = Paths.get(lookupURI);
                    }

                    final FileSystem fsInner = fs;

                    Files.walkFileTree(path.getParent(), new SimpleFileVisitor() {
                        @Override
                        public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
                            LOGGER.info("Current file: {}", path);

                            if (FilenameUtils.wildcardMatch(path.toString(), fileName, IOCase.INSENSITIVE)) {
                                LOGGER.info("Found matching path: {}, absolutePath: {}", path, path.toAbsolutePath());

                                File file = null;
                                if (fsInner != null) {
                                    String filePath = array[0] + "!" + path.toAbsolutePath();
                                    file = new File(filePath);
                                }
                                else {

                                    file = path.toFile();
                                }

                                LOGGER.info("Add matching file: {}", file);

                                files.add(file);
                            }

                            return FileVisitResult.CONTINUE;
                        }

                        @Override
                        public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
                            if (e == null) {
                                LOGGER.info("Current directory: {}", dir);
                                return FileVisitResult.CONTINUE;
                            }
                            else {
                                // directory iteration failed
                                throw e;
                            }
                        }
                    });
                }
                catch (Exception e) {
                    LOGGER.warn("Convert uri to path failed.", e);
                }
                finally {
                    if (fs != null) {
                        try {
                            fs.close();
                        }
                        catch (Exception ex) {
                            LOGGER.warn("Close filesystem failed.", ex);
                        }
                    }
                }

                LOGGER.debug("Found matching files: {}", files);
            }
            else {
                LOGGER.debug("Search for files in searchPath: {}", searchPath);
                File searchFile = new File(searchPath, fileName);
                File searchDirectory = searchFile.getParentFile();
                if (searchDirectory.exists()) {
                    // use filename with wildcards
                    IOFileFilter fileFilter =
                        WildcardFileFilter.builder().setWildcards(fileName).setIoCase(IOCase.INSENSITIVE).get();
                    files
                        .addAll(FileUtils
                            .listFiles(searchDirectory, fileFilter, searchSubDirs ? TrueFileFilter.INSTANCE : null));

                    LOGGER.debug("Found matching files: {}", files);
                }
                else {
                    LOGGER.info("The directory to search does not exist: {}", searchDirectory.toString());
                }
            }
        }
        return files;
    }

    public static List findResources(String fileName, boolean searchSubDirs, String... searchPaths) {

        LOGGER.info("Find files in searchPaths: {}", new Object[] { searchPaths });

        final List files = new LinkedList<>();

        for (String searchPath : searchPaths) {

            LOGGER.info("Prepared filename to load file: {}, searchPath: {}", fileName, searchPath);

            if (searchPath.startsWith("classpath:")) {
                // search in the classpath
                int beginIndex = "classpath:".length();
                String lookup = "/" + searchPath.substring(beginIndex);
                lookup = lookup.replaceAll("\\\\", "/");
                LOGGER.info("Lookup file internally: {}", lookup);

                try {
                    String filenameSearch = fileName.toString();
                    String searchPathResolver =
                        ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + lookup + "/" + filenameSearch;
                    LOGGER.info("Prepared searchPathResolver: {}", searchPathResolver);

                    Resource[] resources =
                        new PathMatchingResourcePatternResolver(SearchPathUtils.class.getClassLoader())
                            .getResources(searchPathResolver);

                    LOGGER.info("Found resources: {}", Arrays.asList(resources));

                    for (Resource resource : resources) {
                        LOGGER.info("Current resource: {}", resource);
                        files.add(resource);
                    }
                }
                catch (Exception e) {
                    LOGGER.warn("Convert uri to path failed.", e);
                }
                LOGGER.debug("Found matching files: {}", files);
            }
            else {
                LOGGER.debug("Search for files in searchPath: {}", searchPath);
                File searchFile = new File(searchPath, fileName);
                File searchDirectory = searchFile.getParentFile();
                if (searchDirectory.exists()) {
                    // use filename with wildcards
                    try {
                        // use filename with wildcards
                        IOFileFilter fileFilter =
                            WildcardFileFilter.builder().setWildcards(fileName).setIoCase(IOCase.INSENSITIVE).get();
                        final Collection listFiles =
                            FileUtils
                                .listFiles(searchDirectory, fileFilter, searchSubDirs ? TrueFileFilter.INSTANCE : null);

                        for (File file : listFiles) {
                            LOGGER.info("Current file: {}", file);
                            files.add(new FileSystemResource(file));
                        }
                    }
                    catch (Exception e) {
                        LOGGER.warn("Convert uri to path failed.", e);
                    }

                    LOGGER.debug("Found matching files: {}", files);
                }
                else {
                    LOGGER.info("The directory to search does not exist: {}", searchDirectory.toString());
                }
            }
        }
        return files;
    }

    public static String lookupFilesInClasspath(
        String searchPath, SoftwareVersion softwareVersion, String filename, String lookup, String filenameSearch) {

        int beginIndex = "classpath:".length();

        final List files = new LinkedList<>();
        try {
            String mapperPackagePath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + lookup + filenameSearch;
            LOGGER.info("Prepared mapperPackagePath: {}", mapperPackagePath);

            Resource[] resources =
                new PathMatchingResourcePatternResolver(SearchPathUtils.class.getClassLoader())
                    .getResources(mapperPackagePath);

            LOGGER.info("Found resources: {}", Arrays.asList(resources));

            for (Resource resource : resources) {
                LOGGER.info("Current resource: {}", resource);
                files.add(resource);
            }
        }
        catch (Exception e) {
            LOGGER.warn("Convert uri to path failed.", e);
        }

        LOGGER.info("Found matching files: {}", files);

        if (CollectionUtils.isNotEmpty(files)) {
            List fileCollection = new LinkedList<>();
            for (Resource file : files) {
                fileCollection.add(file);
            }

            Resource vendorCvFile = findMatchingVendorCVResource(fileCollection, filename.toString(), softwareVersion);
            LOGGER.info("Matching vendorCvFile: {}", vendorCvFile);
            if (vendorCvFile != null) {
                String lookupPath = vendorCvFile.getFilename();

                lookup = searchPath.substring(beginIndex) + "/" + lookupPath;

                LOGGER.info("Prepared vendor CV lookup: {}", lookup);
            }
            else {
                LOGGER.warn("No matching vendorCV file found.");
                lookup = null;
            }
        }
        else {
            LOGGER.info("No matching vendorCV file found!");
            lookup = null;
        }

        return lookup;
    }

    protected static Resource findMatchingVendorCVResource(
        Collection files, String defaultFilename, SoftwareVersion softwareVersion) {
        if (CollectionUtils.isNotEmpty(files)) {
            LOGGER.info("Search for matching CV definition for software version: {}", softwareVersion);

            Resource defaultCvDefinition = null;
            Resource cvDefinition = null;

            // logic to detect the matching CV definition
            SortedMap weightedMap = new TreeMap<>(Collections.reverseOrder());
            for (Resource file : files) {

                if (file == null || file.getFilename() == null) {
                    continue;
                }

                String fileName = FilenameUtils.getBaseName(file.getFilename());
                LOGGER.info("Check if filename is matching: {}", fileName);

                int index = fileName.lastIndexOf("-");
                if (index > -1 && index < fileName.length()) {
                    String lastPart = fileName.substring(index + 1);
                    LOGGER.info("Check last part: {}", lastPart);
                    // scan version
                    if (lastPart.matches("^\\d+(\\.\\d+){0,2}")) {
                        String[] splited = lastPart.split("\\.");

                        LOGGER.info("Found version schema: {}", (Object[]) splited);

                        int majorVersion = Integer.parseInt(splited[0]);
                        int minorVersion = -1;
                        if (splited.length > 1) {
                            minorVersion = Integer.parseInt(splited[1]);
                        }
                        int microVersion = -1;
                        if (splited.length > 2) {
                            microVersion = Integer.parseInt(splited[2]);
                        }

                        LOGGER
                            .info("Found version, major: {}, minor: {}, micro: {}", majorVersion, minorVersion,
                                microVersion);

                        SoftwareVersion current = new SoftwareVersion(majorVersion, minorVersion, microVersion) {
                            @Override
                            public int compareTo(SoftwareVersion other) {
                                LOGGER.info("Compare sw version, other: {}, this: {}", other, this);

                                int myVersion = toInt();
                                int otherVersion = other.toInt();

                                if (secondVersion == -1) {
                                    // skip compare second and third version
                                    SoftwareVersion myVersion2 = new SoftwareVersion(firstVersion, 255, 255);
                                    myVersion = myVersion2.toInt();
                                    LOGGER
                                        .info("Skip compare the micro version, otherVersion: {}, myVersion: {}",
                                            otherVersion, myVersion);
                                }
                                else if (thirdVersion == -1) {
                                    // skip compare third version
                                    SoftwareVersion myVersion2 = new SoftwareVersion(firstVersion, secondVersion, 255);
                                    myVersion = myVersion2.toInt();
                                    LOGGER
                                        .info("Skip compare the micro version, otherVersion: {}, myVersion: {}",
                                            otherVersion, myVersion);
                                }

                                return (otherVersion - myVersion);
                            }
                        };

                        int difference = current.compareTo(softwareVersion);
                        LOGGER.info("The comparison difference: {}", difference);
                        weightedMap.put(difference, file);
                        if (difference == 0) {
                            LOGGER.info("Found excactly matching version in file: {}", file);

                            cvDefinition = file;
                            break;
                        }
                    }
                    else {
                        LOGGER.info("Last part does not match version schema: {}", lastPart);
                    }
                }

                String resourceFilename = file.getFilename();
                if (defaultFilename != null && resourceFilename.equalsIgnoreCase(defaultFilename)) {
                    LOGGER.info("Found the default CV definition: {}", file);
                    defaultCvDefinition = file;
                }
            }

            LOGGER.info("Weighted map: {}", weightedMap);

            if (cvDefinition == null && MapUtils.isNotEmpty(weightedMap)) {
                // get the shortest distance
                for (Entry weightedKey : weightedMap.entrySet()) {
                    if (weightedKey.getKey() > 0) {
                        continue;
                    }

                    cvDefinition = weightedKey.getValue();
                    LOGGER.info("Use closest cvDefinition: {}", cvDefinition);

                    break;
                }
            }

            if (cvDefinition == null) {
                LOGGER.info("Use defaultCvDefinition: {}", defaultCvDefinition);
                cvDefinition = defaultCvDefinition;
            }
            return cvDefinition;
        }

        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy