com.blackducksoftware.integration.hub.detect.workflow.file.DetectFileFinder.java Source code

Java tutorial

Introduction

Here is the source code for com.blackducksoftware.integration.hub.detect.workflow.file.DetectFileFinder.java

Source

/**
 * hub-detect
 *
 * Copyright (C) 2019 Black Duck Software, Inc.
 * http://www.blackducksoftware.com/
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.blackducksoftware.integration.hub.detect.workflow.file;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DetectFileFinder {
    private final Logger logger = LoggerFactory.getLogger(DetectFileFinder.class);

    public String extractFinalPieceFromPath(final String path) {
        if (path == null || path.length() == 0) {
            return "";
        }
        final String normalizedPath = FilenameUtils.normalizeNoEndSeparator(path, true);
        return normalizedPath.substring(normalizedPath.lastIndexOf("/") + 1, normalizedPath.length());
    }

    public List<File> findFilesToDepth(final String sourceDirectory, final String filenamePattern,
            final int maxDepth) {
        return findFilesToDepth(new File(sourceDirectory), filenamePattern, maxDepth);
    }

    public boolean containsAllFiles(final String sourceDirectory, final String... filenamePatterns) {
        return containsAllFiles(new File(sourceDirectory), filenamePatterns);
    }

    public boolean containsAllFiles(final File sourceDirectory, final String... filenamePatterns) {
        if (!sourceDirectory.isDirectory()) {
            return false;
        }

        return Arrays.stream(filenamePatterns).allMatch(pattern -> findFile(sourceDirectory, pattern) != null);
    }

    public boolean containsAllFilesToDepth(final String sourcePath, final int maxDepth,
            final String... filenamePatterns) {
        final File sourceDirectory = new File(sourcePath);
        if (StringUtils.isBlank(sourcePath) || !sourceDirectory.isDirectory()) {
            return false;
        }

        return Arrays.stream(filenamePatterns).map(pattern -> findFilesToDepth(sourceDirectory, pattern, maxDepth))
                .allMatch(foundFiles -> !foundFiles.isEmpty());
    }

    public File findFile(final String sourceDirectory, final String filenamePattern) {
        return findFile(new File(sourceDirectory), filenamePattern);
    }

    public File findFile(final File sourceDirectory, final String filenamePattern) {
        final File foundFile;
        final List<File> foundFiles = findFiles(sourceDirectory, filenamePattern);
        if (foundFiles == null || foundFiles.isEmpty()) {
            logger.debug(String.format("Could not find any matches for %s in %s", filenamePattern,
                    sourceDirectory.getAbsolutePath()));
            foundFile = null;
        } else {
            foundFile = foundFiles.get(0);
            if (foundFiles.size() > 1) {
                logger.debug(String.format("Found multiple matches for %s in %s", filenamePattern,
                        sourceDirectory.getAbsolutePath()));
                logger.debug(String.format("Using %s", foundFile));
            } else {
                logger.debug(String.format("Found a match %s for file %s in %s", foundFile.getAbsolutePath(),
                        filenamePattern, sourceDirectory.getAbsolutePath()));
            }
        }
        return foundFile;
    }

    public List<File> findFiles(final File sourceDirectory, final String filenamePattern) {
        if (!sourceDirectory.isDirectory()) {
            return null;
        }
        final File[] foundFiles = sourceDirectory.listFiles((FilenameFilter) (directoryContainingTheFile,
                filename) -> FilenameUtils.wildcardMatchOnSystem(filename, filenamePattern));
        if (foundFiles == null || foundFiles.length == 0) {
            return null;
        }
        return Arrays.asList(foundFiles);
    }

    public List<File> findFilesToDepth(final File sourceDirectory, final String filenamePattern,
            final int maxDepth) {
        return findFilesRecursive(sourceDirectory, 0, maxDepth, null, true, filenamePattern);
    }

    /**
     * Will recursively look for files/directories matching these name patterns within the source directory. It will not look for matching files/directories within a directory that matched one of the patterns.
     */
    public List<File> findAllFilesToMaxDepth(final File sourceDirectory, final String... filenamePatterns) {
        return findFilesRecursive(sourceDirectory, 0, Integer.MAX_VALUE, null, false, filenamePatterns);
    }

    public List<File> findAllFilesToDepth(final File sourceDirectory, final StringBuilder maxDepthHitMsgPattern,
            final int maxDepth, final String... filenamePatterns) {
        return findFilesRecursive(sourceDirectory, 0, maxDepth, maxDepthHitMsgPattern, false, filenamePatterns);
    }

    public List<File> findDirectoriesContainingDirectoriesToDepth(final String sourcePath,
            final String filenamePattern, final int maxDepth) {
        return findDirectoriesContainingDirectoriesToDepth(new File(sourcePath), filenamePattern, maxDepth);
    }

    public List<File> findDirectoriesContainingDirectoriesToDepth(final File sourceDirectory,
            final String directoryPattern, final int maxDepth) {
        return findDirectoriesContainingDirectoriesToDepthRecursive(sourceDirectory, directoryPattern, 0, maxDepth);
    }

    private List<File> findFilesRecursive(final File sourceDirectory, final int currentDepth, final int maxDepth,
            StringBuilder maxDepthHitMsgPattern, final Boolean recurseIntoDirectoryMatch,
            final String... filenamePatterns) {
        final List<File> files = new ArrayList<>();
        if (currentDepth >= maxDepth) {
            if (StringUtils.isNotBlank(maxDepthHitMsgPattern)) {
                logger.warn(String.format(maxDepthHitMsgPattern.toString(), sourceDirectory.getAbsolutePath()));
                // Ensure msg only shown once
                maxDepthHitMsgPattern.setLength(0);
            }
        } else if (sourceDirectory.isDirectory()) {
            File[] children = sourceDirectory.listFiles();
            if (children != null && children.length > 0 && null != filenamePatterns
                    && filenamePatterns.length >= 1) {
                for (final File file : children) {
                    final boolean fileMatchesPatterns = Arrays.stream(filenamePatterns)
                            .anyMatch(pattern -> FilenameUtils.wildcardMatchOnSystem(file.getName(), pattern));

                    if (fileMatchesPatterns) {
                        files.add(file);
                    }

                    if (file.isDirectory() && (!fileMatchesPatterns || recurseIntoDirectoryMatch)) {
                        // only go into the directory if it is not a match OR it is a match and the flag is set to go into matching directories
                        files.addAll(findFilesRecursive(file, currentDepth + 1, maxDepth, maxDepthHitMsgPattern,
                                recurseIntoDirectoryMatch, filenamePatterns));
                    }
                }
            } else if (children == null) {
                logger.warn("Directory contents could not be accessed: " + sourceDirectory.getAbsolutePath());
            }
        }
        return files;
    }

    private List<File> findDirectoriesContainingDirectoriesToDepthRecursive(final File sourceDirectory,
            final String directoryPattern, final int currentDepth, final int maxDepth) {
        final List<File> files = new ArrayList<>();
        if (currentDepth > maxDepth || !sourceDirectory.isDirectory()) {
            return files;
        }
        for (final File file : sourceDirectory.listFiles()) {
            if (file.isDirectory()) {
                if (FilenameUtils.wildcardMatchOnSystem(file.getName(), directoryPattern)) {
                    files.add(file);
                } else {
                    files.addAll(findDirectoriesContainingDirectoriesToDepthRecursive(file, directoryPattern,
                            currentDepth + 1, maxDepth));
                }
            }
        }
        return files;
    }

    public List<File> findDirectoriesContainingFilesToDepth(final File sourceDirectory,
            final String filenamePattern, final int maxDepth) {
        return findDirectoriesContainingFilesRecursive(sourceDirectory, filenamePattern, 0, maxDepth);
    }

    private List<File> findDirectoriesContainingFilesRecursive(final File sourceDirectory,
            final String filenamePattern, final int currentDepth, final int maxDepth) {
        final Set<File> files = new HashSet<>();
        if (currentDepth > maxDepth || !sourceDirectory.isDirectory()) {
            return new ArrayList<>(files);
        }
        for (final File file : sourceDirectory.listFiles()) {
            if (file.isDirectory()) {
                files.addAll(
                        findDirectoriesContainingFilesRecursive(file, filenamePattern, currentDepth + 1, maxDepth));
            } else if (FilenameUtils.wildcardMatchOnSystem(file.getName(), filenamePattern)) {
                files.add(sourceDirectory);
            }
        }
        return new ArrayList<>(files);
    }

    public File findContainingDir(final File givenDir, int numberOfLevelsToWalkBack) {
        File containingDir = givenDir;
        for (; numberOfLevelsToWalkBack > 0; numberOfLevelsToWalkBack--) {
            containingDir = containingDir.getParentFile();
        }
        return containingDir;
    }

    public boolean isFileUnderDir(final File dir, final File file) {
        try {
            final String dirPath = dir.getCanonicalPath();
            final String filePath = file.getCanonicalPath();
            if (filePath.startsWith(dirPath)) {
                return true;
            }
            return false;
        } catch (final IOException e) {
            logger.warn(String.format("Error getting canonical path for either %s or %s", dir.getAbsolutePath(),
                    file.getAbsolutePath()));
            return false;
        }
    }
}