com.github.blindpirate.gogradle.util.IOUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.github.blindpirate.gogradle.util.IOUtils.java

Source

/*
 * Copyright 2016-2017 the original author or authors.
 *
 * 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.github.blindpirate.gogradle.util;

import com.github.blindpirate.gogradle.GogradleGlobal;
import com.github.blindpirate.gogradle.core.dependency.install.DependencyInstallFileFilter;
import com.github.blindpirate.gogradle.crossplatform.Os;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UncheckedIOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
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.nio.file.attribute.PosixFilePermissions;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.github.blindpirate.gogradle.GogradleGlobal.DEFAULT_CHARSET;
import static com.github.blindpirate.gogradle.GogradleGlobal.MAX_DFS_DEPTH;

/**
 * Encapsulation of {@link FileUtils} and {@link org.apache.commons.io.IOUtils},
 * it never throws checked exceptions.
 */
public final class IOUtils {

    public static void forceMkdir(File directory) {
        try {
            FileUtils.forceMkdir(directory);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static File mkdir(File baseDir, String newDirName) {
        Assert.isNotNull(baseDir);
        File ret = new File(baseDir, newDirName);
        forceMkdir(ret);
        return ret;
    }

    public static void forceDelete(final File file) {
        try {
            if (file != null) {
                FileUtils.forceDelete(file);
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static void deleteQuitely(final File file) {
        FileUtils.deleteQuietly(file);
    }

    public static boolean dirIsEmpty(File directory) {
        if (!directory.exists()) {
            return true;
        }
        String[] files = Assert.isNotNull(directory.list());
        return files.length == 0;
    }

    public static Path ensureDirExistAndWritable(Path path) {
        Assert.isTrue(path.isAbsolute(), "path must be absolute!");
        File dir = path.toFile();
        IOUtils.forceMkdir(dir);
        Assert.isTrue(Files.isWritable(dir.toPath()), "Cannot write to directory:" + path);
        return path;
    }

    public static Path ensureDirExistAndWritable(Path base, String relativePath) {
        return ensureDirExistAndWritable(base.resolve(Paths.get(relativePath)));
    }

    public static void copyDirectory(File src, File dest) {
        try {
            org.apache.commons.io.FileUtils.copyDirectory(src, dest);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static byte[] toByteArray(ByteBuffer buf) {
        ((Buffer) buf).position(0);
        byte[] ret = new byte[buf.remaining()];
        buf.get(ret);
        return ret;
    }

    public static void copyDependencies(final File srcDir, final File destDir, final Set<String> subpackages) {
        try {
            Assert.isTrue(dirIsEmpty(destDir));
            DependencyInstallFileFilter filter = DependencyInstallFileFilter.subpackagesFilter(srcDir, subpackages);
            FileUtils.copyDirectory(srcDir, destDir, filter);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static void copyFile(File src, File dest) {
        try {
            FileUtils.copyFile(src, dest);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static void touch(File file) {
        try {
            org.apache.commons.io.FileUtils.touch(file);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static void write(File file, CharSequence data) {
        try {
            org.apache.commons.io.FileUtils.write(file, data, DEFAULT_CHARSET);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static File write(File baseDir, String fileName, CharSequence data) {
        Assert.isNotNull(baseDir);
        File targetFile = new File(baseDir, fileName);
        forceMkdir(targetFile.getParentFile());
        write(targetFile, data);
        return targetFile;
    }

    public static String toString(File file) {
        try (InputStream is = new FileInputStream(file)) {
            return org.apache.commons.io.IOUtils.toString(is, DEFAULT_CHARSET);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static List<String> collectFileNames(List<File> files) {
        return files.stream().map(StringUtils::toUnixString).collect(Collectors.toList());
    }

    public static List<String> safeList(File dir) {
        String[] files = dir.list();
        return files == null ? Collections.emptyList() : Arrays.asList(files);
    }

    public static List<File> safeListFiles(File dir) {
        File[] files = dir.listFiles();
        return files == null ? Collections.emptyList() : Arrays.asList(files);
    }

    public static boolean isValidDirectory(File dir) {
        return dir.isDirectory();
    }

    public static String toString(InputStream inputStream) {
        try {
            return org.apache.commons.io.IOUtils.toString(inputStream, DEFAULT_CHARSET);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static void append(File baseDir, String file, String str) {
        append(new File(baseDir, file), str);
    }

    public static void append(File file, String str) {
        try {
            FileUtils.write(file, str, GogradleGlobal.DEFAULT_CHARSET, true);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static List<String> readLines(File file) {
        String content = toString(file);
        if (StringUtils.isEmpty(content)) {
            return Collections.emptyList();
        } else {
            return Arrays.asList(content.split("\n"));
        }
    }

    public static void walkFileTreeSafely(Path path, FileVisitor<? super Path> visitor) {
        try {
            Files.walkFileTree(path, EnumSet.noneOf(FileVisitOption.class), MAX_DFS_DEPTH, visitor);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static Collection<File> filterFilesRecursively(File dir, IOFileFilter filter) {
        return FileUtils.listFiles(dir, filter, filter);
    }

    public static Collection<File> filterFilesRecursively(File dir, IOFileFilter fileFilter,
            IOFileFilter dirFilter) {
        return FileUtils.listFiles(dir, fileFilter, dirFilter);
    }

    public static Collection<File> listAllDescendents(File dir) {
        return FileUtils.listFilesAndDirs(dir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
    }

    public static void clearDirectory(File dir) {
        try {
            if (dir == null || !dir.exists()) {
                return;
            }
            FileUtils.cleanDirectory(dir);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static void chmodAddX(Path filePath) {
        try {
            if (Os.getHostOs() != Os.WINDOWS) {
                Files.setPosixFilePermissions(filePath, PosixFilePermissions.fromString("rwx------"));
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static Path toRealPath(Path path) {
        try {
            return path.toRealPath();
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static String byteCountToDisplaySize(long size) {
        return FileUtils.byteCountToDisplaySize(size);
    }

    public static String encodeInternally(String s) {
        try {
            return URLEncoder.encode(s, "UTF8");
        } catch (UnsupportedEncodingException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static String decodeInternally(String encoded) {
        try {
            return URLDecoder.decode(encoded, "UTF8");
        } catch (UnsupportedEncodingException e) {
            throw new UncheckedIOException(e);
        }
    }

    // It is said that this method has very bad performance
    // http://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java
    @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
    public static long countLines(Path path) {
        try (Stream<String> lines = Files.lines(path)) {
            return lines.count();
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static void copyURLToFile(URL url, File dest) {
        try {
            FileUtils.copyURLToFile(url, dest);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static void serialize(Object obj, File file) {
        if (!file.exists()) {
            write(file, "");
        }

        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
            oos.writeObject(obj);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static Object deserialize(File file) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
            return ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            throw ExceptionHandler.uncheckException(e);
        }
    }

    public static void markAndDeleteUnmarked(File rootDir, Predicate<File> predicate) {
        MarkDirectoryVisitor markVisitor = new MarkDirectoryVisitor(rootDir, predicate);
        walkFileTreeSafely(rootDir.toPath(), markVisitor);

        DeleteUnmarkedDirectoryVisitor deleteVisitor = new DeleteUnmarkedDirectoryVisitor(markVisitor);
        walkFileTreeSafely(rootDir.toPath(), deleteVisitor);
    }

    static class MarkDirectoryVisitor extends SimpleFileVisitor<Path> {
        private Set<File> markedDirectories = new HashSet<>();
        private Set<File> ancestorsOfMarkedDirectories = new HashSet<>();
        private Predicate<File> dirPredicate;
        private File rootDir;

        MarkDirectoryVisitor(File rootDir, Predicate<File> dirPredicate) {
            this.dirPredicate = dirPredicate;
            this.rootDir = rootDir;
        }

        Set<File> getMarkedDirectories() {
            return markedDirectories;
        }

        Set<File> getAncestorsOfMarkedDirectories() {
            return ancestorsOfMarkedDirectories;
        }

        @Override
        public FileVisitResult preVisitDirectory(Path dirPath, BasicFileAttributes attrs) throws IOException {
            File dir = dirPath.toFile();
            if (dirPredicate.test(dir)) {
                markedDirectories.add(dir);
                while (!rootDir.equals(dir)) {
                    dir = dir.getParentFile();
                    ancestorsOfMarkedDirectories.add(dir);
                }
                return FileVisitResult.SKIP_SUBTREE;
            } else {
                return FileVisitResult.CONTINUE;
            }
        }
    }

    static class DeleteUnmarkedDirectoryVisitor extends SimpleFileVisitor<Path> {
        private MarkDirectoryVisitor markDirectoryVisitor;

        DeleteUnmarkedDirectoryVisitor(MarkDirectoryVisitor markDirectoryVisitor) {
            this.markDirectoryVisitor = markDirectoryVisitor;
        }

        @Override
        public FileVisitResult preVisitDirectory(Path dirPath, BasicFileAttributes attrs) throws IOException {
            File dir = dirPath.toFile();
            if (isMarked(dir)) {
                return FileVisitResult.SKIP_SUBTREE;
            } else if (isAncestorOfMarked(dir)) {
                return FileVisitResult.CONTINUE;
            } else {
                IOUtils.forceDelete(dir);
                return FileVisitResult.SKIP_SUBTREE;
            }
        }

        private boolean isMarked(File dir) {
            return markDirectoryVisitor.getMarkedDirectories().contains(dir);
        }

        private boolean isAncestorOfMarked(File dir) {
            return markDirectoryVisitor.getAncestorsOfMarkedDirectories().contains(dir);
        }
    }

}