com.thoughtworks.go.util.FileUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.thoughtworks.go.util.FileUtil.java

Source

/*
 * Copyright 2019 ThoughtWorks, Inc.
 *
 * Licensed 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.thoughtworks.go.util;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;

import java.io.*;
import java.net.URI;
import java.util.Base64;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.UUID;

import static java.lang.System.getProperty;

public class FileUtil {
    private static final String CRUISE_TMP_FOLDER = "cruise" + "-" + UUID.randomUUID().toString();
    private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(FileUtil.class);

    private static final boolean ON_NETWARE = OperatingSystem.isFamily("netware");
    private static final boolean ON_DOS = OperatingSystem.isFamily("dos");
    public static final String TMP_PARENT_DIR = "data";

    public static boolean isFolderEmpty(File folder) {
        if (folder == null) {
            return true;
        }
        File[] files = folder.listFiles();
        return files == null || files.length == 0;
    }

    public static boolean isDirectoryReadable(File directory) {
        return directory.canRead() && directory.canExecute() && directory.listFiles() != null;
    }

    public static boolean isHidden(File file) {
        return file.isHidden() || file.getName().startsWith(".");
    }

    public static String applyBaseDirIfRelativeAndNormalize(File baseDir, File actualFileToUse) {
        return FilenameUtils.separatorsToUnix(applyBaseDirIfRelative(baseDir, actualFileToUse).getPath());
    }

    public static File applyBaseDirIfRelative(File baseDir, File actualFileToUse) {
        if (actualFileToUse == null) {
            return baseDir;
        }
        if (actualFileToUse.isAbsolute()) {
            return actualFileToUse;
        }

        if (StringUtils.isBlank(baseDir.getPath())) {
            return actualFileToUse;
        }

        return new File(baseDir, actualFileToUse.getPath());

    }

    public static void validateAndCreateDirectory(File directory) {
        if (directory.exists()) {
            return;
        }
        try {
            FileUtils.forceMkdir(directory);
        } catch (IOException e) {
            throw new RuntimeException("Failed to create folder: " + directory.getAbsolutePath());
        }
    }

    public static void createParentFolderIfNotExist(File file) {
        File parentFile = file.getParentFile();
        if (parentFile != null && !parentFile.exists()) {
            parentFile.mkdirs();
        }
    }

    public static String lineSeparator() {
        return getProperty("line.separator");
    }

    public static String fileseparator() {
        return File.separator;
    }

    public static String toFileURI(File file) {
        URI uri = file.toURI();
        String uriString = uri.toASCIIString();
        return uriString.replaceAll("^file:/", "file:///");
    }

    public static String toFileURI(String path) {
        return toFileURI(new File(path));
    }

    public static String filesystemSafeFileHash(File folder) {
        String hash = Base64.getEncoder().encodeToString(DigestUtils.sha1(folder.getAbsolutePath().getBytes()));
        hash = hash.replaceAll("[^0-9a-zA-Z\\.\\-]", "");
        return hash;
    }

    public static boolean isChildOf(File parent, File subdirectory) throws IOException {
        File parentFile = parent.getCanonicalFile();
        File current = subdirectory.getCanonicalFile();
        return !current.equals(parentFile) && isSubdirectoryOf(parent, subdirectory);
    }

    public static boolean isSubdirectoryOf(File parent, File subdirectory) throws IOException {
        File parentFile = parent.getCanonicalFile();
        File current = subdirectory.getCanonicalFile();
        while (current != null) {
            if (current.equals(parentFile)) {
                return true;
            }
            current = current.getParentFile();
        }
        return false;
    }

    //CopiedFromAnt

    public static boolean isAbsolutePath(String filename) {
        File file = new File(filename);
        boolean absolute = file.isAbsolute();
        if (absolute && OperatingSystem.isFamily(OperatingSystem.WINDOWS)) {
            if (filename.startsWith("\\\\") && !filename.matches("\\\\\\\\.*\\\\.+")) {
                absolute = false;
            }
        }
        return absolute;
    }

    public static String[] dissect(String path) {
        char sep = File.separatorChar;
        path = path.replace('/', sep).replace('\\', sep);

        // make sure we are dealing with an absolute path
        if (!isAbsolutePath(path)) {
            throw new RuntimeException(path + " is not an absolute path");
        }
        String root;
        int colon = path.indexOf(':');
        if (colon > 0 && (ON_DOS || ON_NETWARE)) {

            int next = colon + 1;
            root = path.substring(0, next);
            char[] ca = path.toCharArray();
            root += sep;
            //remove the initial separator; the root has it.
            next = (ca[next] == sep) ? next + 1 : next;

            StringBuilder sbPath = new StringBuilder();
            // Eliminate consecutive slashes after the drive spec:
            for (int i = next; i < ca.length; i++) {
                if (ca[i] != sep || ca[i - 1] != sep) {
                    sbPath.append(ca[i]);
                }
            }
            path = sbPath.toString();
        } else if (path.length() > 1 && path.charAt(1) == sep) {
            // UNC drive
            int nextsep = path.indexOf(sep, 2);
            nextsep = path.indexOf(sep, nextsep + 1);
            root = (nextsep > 2) ? path.substring(0, nextsep + 1) : path;
            path = path.substring(root.length());
        } else {
            root = File.separator;
            path = path.substring(1);
        }
        return new String[] { root, path };
    }

    public static File normalize(final String path) {
        Stack s = new Stack();
        String[] dissect = dissect(path);
        s.push(dissect[0]);

        StringTokenizer tok = new StringTokenizer(dissect[1], File.separator);
        while (tok.hasMoreTokens()) {
            String thisToken = tok.nextToken();
            if (".".equals(thisToken)) {
                continue;
            }
            if ("..".equals(thisToken)) {
                if (s.size() < 2) {
                    // Cannot resolve it, so skip it.
                    return new File(path);
                }
                s.pop();
            } else { // plain component
                s.push(thisToken);
            }
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.size(); i++) {
            if (i > 1) {
                // not before the filesystem root and not after it, since root
                // already contains one
                sb.append(File.separatorChar);
            }
            sb.append(s.elementAt(i));
        }
        return new File(sb.toString());
    }

    public static String removeLeadingPath(File leading, File path) {
        String l = normalize(leading.getAbsolutePath()).getAbsolutePath();
        String p = normalize(path.getAbsolutePath()).getAbsolutePath();
        if (l.equals(p)) {
            return "";
        }
        // ensure that l ends with a /
        // so we never think /foo was a parent directory of /foobar
        if (!l.endsWith(File.separator)) {
            l += File.separator;
        }
        return removeLeadingPath(l, p);
    }

    public static String removeLeadingPath(String leading, String path) {
        if (StringUtils.isBlank(leading)) {
            return path;
        }
        return (path.startsWith(leading)) ? path.substring(leading.length()) : path;
    }

    public static boolean isSymbolicLink(File parent, String name) throws IOException {
        if (parent == null) {
            File f = new File(name);
            parent = f.getParentFile();
            name = f.getName();
        }
        File toTest = new File(parent.getCanonicalPath(), name);
        return !toTest.getAbsolutePath().equals(toTest.getCanonicalPath());
    }

    public static void createFilesByPath(File baseDir, String... files) throws IOException {
        for (String file : files) {
            if (file.endsWith("/")) {
                File file1 = new File(baseDir, file);
                file1.mkdirs();
            } else {
                File file1 = new File(baseDir, file);
                file1.getParentFile().mkdirs();
                file1.createNewFile();
            }
        }
    }

    public static String subtractPath(File rootPath, File file) {
        String fullPath = FilenameUtils.separatorsToUnix(file.getParentFile().getPath());
        String basePath = FilenameUtils.separatorsToUnix(rootPath.getPath());
        return StringUtils.removeStart(StringUtils.removeStart(fullPath, basePath), "/");
    }

    public static File createTempFolder() {
        File tempDir = new File(TMP_PARENT_DIR, CRUISE_TMP_FOLDER);
        File dir = new File(tempDir, UUID.randomUUID().toString());
        boolean ret = dir.mkdirs();
        if (!ret) {
            throw new RuntimeException("FileUtil#createTempFolder - Could not create temp folder");
        }
        return dir;
    }

    public static String getCanonicalPath(File workDir) {
        try {
            return workDir.getCanonicalPath();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void deleteDirectoryNoisily(File defaultDirectory) {
        if (!defaultDirectory.exists()) {
            return;
        }

        try {
            FileUtils.deleteDirectory(defaultDirectory);
        } catch (IOException e) {
            throw new RuntimeException("Failed to delete directory: " + defaultDirectory.getAbsolutePath(), e);
        }
    }

    public static String join(File defaultWorkingDir, String actualFileToUse) {
        if (actualFileToUse == null) {
            LOGGER.trace("Using the default Directory->{}", defaultWorkingDir);
            return FilenameUtils.separatorsToUnix(defaultWorkingDir.getPath());
        }
        return applyBaseDirIfRelativeAndNormalize(defaultWorkingDir, new File(actualFileToUse));
    }

    public static String sha1Digest(File file) {
        try (InputStream is = new BufferedInputStream(new FileInputStream(file))) {
            byte[] hash = DigestUtils.sha1(is);
            return Base64.getEncoder().encodeToString(hash);
        } catch (IOException e) {
            throw ExceptionUtils.bomb(e);
        }
    }
}