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

org.openlca.util.Dirs Maven / Gradle / Ivy

There is a newer version: 2.2.1
Show newest version
package org.openlca.util;

import java.io.File;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
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.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;

/**
 * A simple utility class for directory operations.
 */
public final class Dirs {

	/**
	 * Returns true if and only if the given file is an empty folder.
	 */
	public static boolean isEmpty(File file) {
		if (file == null)
			return false;
		return isEmpty(file.toPath());
	}

	/**
	 * Returns true if and only if the given path points to an empty folder.
	 */
	public static boolean isEmpty(Path path) {
		if (path == null)
			return false;
		if (!Files.isDirectory(path) || !Files.exists(path))
			return false;
		try (var stream = Files.newDirectoryStream(path)) {
			return !stream.iterator().hasNext();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	public static boolean isPresent(File dir) {
		return dir != null && isPresent(dir.toPath());
	}

	public static boolean isPresent(Path path) {
		return path != null && Files.isDirectory(path);
	}

	public static void createIfAbsent(File dir) {
		if (dir == null)
			return;
		createIfAbsent(dir.toPath());
	}

	public static void createIfAbsent(String path) {
		if (path == null)
			return;
		createIfAbsent(Paths.get(path));
	}

	public static void createIfAbsent(Path dir) {
		if (dir == null || Files.exists(dir))
			return;
		try {
			Files.createDirectories(dir);
		} catch (IOException e) {
			throw new RuntimeException("failed to create directory: " + dir, e);
		}
	}

	public static void clean(File dir) {
		if (dir == null || !dir.exists() || !dir.isDirectory())
			return;
		clean(dir.toPath());
	}

	/**
	 * Deletes the content from the given directory but not the directory
	 * itself.
	 */
	public static void clean(Path dir) {
		if (dir == null)
			return;
		try (var stream = Files.newDirectoryStream(dir)) {
			stream.forEach(Dirs::delete);
		} catch (IOException e) {
			throw new RuntimeException("failed to clean " + dir, e);
		}
	}

	/**
	 * Copies a directory recursively.
	 */
	public static void copy(Path from, Path to) {
		if (from == null || to == null || !Files.exists(from))
			return;
		try {
			Files.walkFileTree(from, new Copy(from, to));
		} catch (IOException e) {
			throw new RuntimeException("failed to copy " + from + " to " + to, e);
		}
	}

	public static void delete(File dir) {
		if (dir == null || !dir.exists())
			return;
		delete(dir.toPath());
	}

	/**
	 * Deletes a directory recursively.
	 */
	public static void delete(String path) {
		delete(Paths.get(path));
	}

	/**
	 * Deletes a directory recursively.
	 */
	public static void delete(Path dir) {
		if (dir == null || !Files.exists(dir))
			return;
		try {
			// walkFileTree also works with single files, however, we may call
			// this on many files, e.g. in `Dirs.clean`, and want to avoid
			// unnecessary object allocations
			if (Files.isDirectory(dir)) {
				Files.walkFileTree(dir, Delete.instance);
			} else {
				internalDelete(dir);
			}
		} catch (IOException e) {
			throw new RuntimeException("failed to delete " + dir, e);
		}
	}

	/**
	 * Moves the given directory to the new location.
	 */
	public static void move(Path from, Path to) {
		copy(from, to);
		delete(from);
	}

	/**
	 * Determines the size of the content of a directory recursively.
	 */
	public static long size(Path dir) {
		if (dir == null || !Files.exists(dir))
			return 0;
		try {
			Size size = new Size();
			Files.walkFileTree(dir, size);
			return size.size;
		} catch (IOException e) {
			throw new RuntimeException("failed to determine size of directory " + dir, e);
		}
	}

	private static void internalDelete(Path file) throws IOException {
		try {
			Files.delete(file);
		} catch (AccessDeniedException e) {
			// Files.delete fails for read-only files on Windows with an
			// access-denied exception; thus, we try to set them writable
			// here and delete again
			var f = file.toFile();
			if (!f.canWrite() && f.setWritable(true)) {
				Files.delete(file);
			} else {
				throw e;
			}
		}
	}

	private static class Size extends SimpleFileVisitor {

		private long size;

		@Override
		public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
			size += attrs.size();
			return FileVisitResult.CONTINUE;
		}

		@Override
		public FileVisitResult visitFileFailed(Path file, IOException exc) {
			return FileVisitResult.CONTINUE;
		}

		@Override
		public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
			return FileVisitResult.CONTINUE;
		}

	}

	private static class Copy extends SimpleFileVisitor {

		private final Path from;
		private final Path to;

		public Copy(Path from, Path to) {
			this.from = from;
			this.to = to;
		}

		@Override
		public FileVisitResult preVisitDirectory(Path fromDir,
			BasicFileAttributes attrs) throws IOException {
			Path toDir = to.resolve(from.relativize(fromDir));
			if (!Files.exists(toDir))
				Files.createDirectory(toDir);
			return FileVisitResult.CONTINUE;
		}

		@Override
		public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
			throws IOException {
			Files.copy(file, to.resolve(from.relativize(file)),
				StandardCopyOption.REPLACE_EXISTING);
			return FileVisitResult.CONTINUE;
		}
	}

	private static class Delete extends SimpleFileVisitor {

		private static final Delete instance = new Delete();

		@Override
		public FileVisitResult visitFile(Path file, BasicFileAttributes atts)
			throws IOException {
			internalDelete(file);
			return FileVisitResult.CONTINUE;
		}

		@Override
		public FileVisitResult postVisitDirectory(Path dir, IOException exc)
			throws IOException {
			if (exc != null)
				throw exc;
			internalDelete(dir);
			return FileVisitResult.CONTINUE;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy