org.apache.commons.io.file.PathUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.sling.feature.analyser Show documentation
Show all versions of org.apache.sling.feature.analyser Show documentation
A feature describes an OSGi system
/*
* 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 org.apache.commons.io.file;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.AclEntry;
import java.nio.file.attribute.AclFileAttributeView;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.file.Counters.PathCounters;
/**
* NIO Path utilities.
*
* @since 2.7
*/
public final class PathUtils {
/**
* Private worker/holder that computes and tracks relative path names and their equality. We reuse the sorted
* relative lists when comparing directories.
*/
private static class RelativeSortedPaths {
final boolean equals;
// final List relativeDirList1; // might need later?
// final List relativeDirList2; // might need later?
final List relativeFileList1;
final List relativeFileList2;
/**
* Constructs and initializes a new instance by accumulating directory and file info.
*
* @param dir1 First directory to compare.
* @param dir2 Seconds directory to compare.
* @param maxDepth See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @param linkOptions Options indicating how symbolic links are handled.
* @param fileVisitOptions See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @throws IOException if an I/O error is thrown by a visitor method.
*/
private RelativeSortedPaths(final Path dir1, final Path dir2, final int maxDepth,
final LinkOption[] linkOptions, final FileVisitOption[] fileVisitOptions) throws IOException {
List tmpRelativeDirList1 = null;
List tmpRelativeDirList2 = null;
List tmpRelativeFileList1 = null;
List tmpRelativeFileList2 = null;
if (dir1 == null && dir2 == null) {
equals = true;
} else if (dir1 == null ^ dir2 == null) {
equals = false;
} else {
final boolean parentDirExists1 = Files.exists(dir1, linkOptions);
final boolean parentDirExists2 = Files.exists(dir2, linkOptions);
if (!parentDirExists1 || !parentDirExists2) {
equals = !parentDirExists1 && !parentDirExists2;
} else {
final AccumulatorPathVisitor visitor1 = accumulate(dir1, maxDepth, fileVisitOptions);
final AccumulatorPathVisitor visitor2 = accumulate(dir2, maxDepth, fileVisitOptions);
if (visitor1.getDirList().size() != visitor2.getDirList().size()
|| visitor1.getFileList().size() != visitor2.getFileList().size()) {
equals = false;
} else {
tmpRelativeDirList1 = visitor1.relativizeDirectories(dir1, true, null);
tmpRelativeDirList2 = visitor2.relativizeDirectories(dir2, true, null);
if (!tmpRelativeDirList1.equals(tmpRelativeDirList2)) {
equals = false;
} else {
tmpRelativeFileList1 = visitor1.relativizeFiles(dir1, true, null);
tmpRelativeFileList2 = visitor2.relativizeFiles(dir2, true, null);
equals = tmpRelativeFileList1.equals(tmpRelativeFileList2);
}
}
}
}
// relativeDirList1 = tmpRelativeDirList1;
// relativeDirList2 = tmpRelativeDirList2;
relativeFileList1 = tmpRelativeFileList1;
relativeFileList2 = tmpRelativeFileList2;
}
}
/**
* Empty {@link LinkOption} array.
*
* @since 2.8.0
*/
public static final DeleteOption[] EMPTY_DELETE_OPTION_ARRAY = new DeleteOption[0];
/**
* Empty {@link FileVisitOption} array.
*/
public static final FileVisitOption[] EMPTY_FILE_VISIT_OPTION_ARRAY = new FileVisitOption[0];
/**
* Empty {@link LinkOption} array.
*/
public static final LinkOption[] EMPTY_LINK_OPTION_ARRAY = new LinkOption[0];
/**
* Empty {@link OpenOption} array.
*/
public static final OpenOption[] EMPTY_OPEN_OPTION_ARRAY = new OpenOption[0];
/**
* Accumulates file tree information in a {@link AccumulatorPathVisitor}.
*
* @param directory The directory to accumulate information.
* @param maxDepth See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @param fileVisitOptions See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @throws IOException if an I/O error is thrown by a visitor method.
* @return file tree information.
*/
private static AccumulatorPathVisitor accumulate(final Path directory, final int maxDepth,
final FileVisitOption[] fileVisitOptions) throws IOException {
return visitFileTree(AccumulatorPathVisitor.withLongCounters(), directory,
toFileVisitOptionSet(fileVisitOptions), maxDepth);
}
/**
* Cleans a directory including sub-directories without deleting directories.
*
* @param directory directory to clean.
* @return The visitation path counters.
* @throws IOException if an I/O error is thrown by a visitor method.
*/
public static PathCounters cleanDirectory(final Path directory) throws IOException {
return cleanDirectory(directory, EMPTY_DELETE_OPTION_ARRAY);
}
/**
* Cleans a directory including sub-directories without deleting directories.
*
* @param directory directory to clean.
* @param options options indicating how deletion is handled.
* @return The visitation path counters.
* @throws IOException if an I/O error is thrown by a visitor method.
* @since 2.8.0
*/
public static PathCounters cleanDirectory(final Path directory, final DeleteOption... options) throws IOException {
return visitFileTree(new CleaningPathVisitor(Counters.longPathCounters(), options), directory)
.getPathCounters();
}
/**
* Copies a directory to another directory.
*
* @param sourceDirectory The source directory.
* @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
* @return The visitation path counters.
* @throws IOException if an I/O error is thrown by a visitor method.
*/
public static PathCounters copyDirectory(final Path sourceDirectory, final Path targetDirectory,
final CopyOption... copyOptions) throws IOException {
return visitFileTree(
new CopyDirectoryVisitor(Counters.longPathCounters(), sourceDirectory, targetDirectory, copyOptions),
sourceDirectory).getPathCounters();
}
/**
* Copies a URL to a directory.
*
* @param sourceFile The source URL.
* @param targetFile The target file.
* @param copyOptions Specifies how the copying should be done.
* @return The target file
* @throws IOException if an I/O error occurs
* @see Files#copy(InputStream, Path, CopyOption...)
*/
public static Path copyFile(final URL sourceFile, final Path targetFile, final CopyOption... copyOptions)
throws IOException {
try (final InputStream inputStream = sourceFile.openStream()) {
Files.copy(inputStream, targetFile, copyOptions);
return targetFile;
}
}
/**
* Copies a file to a directory.
*
* @param sourceFile The source file.
* @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
* @return The target file
* @throws IOException if an I/O error occurs
* @see Files#copy(Path, Path, CopyOption...)
*/
public static Path copyFileToDirectory(final Path sourceFile, final Path targetDirectory,
final CopyOption... copyOptions) throws IOException {
return Files.copy(sourceFile, targetDirectory.resolve(sourceFile.getFileName()), copyOptions);
}
/**
* Copies a URL to a directory.
*
* @param sourceFile The source URL.
* @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
* @return The target file
* @throws IOException if an I/O error occurs
* @see Files#copy(InputStream, Path, CopyOption...)
*/
public static Path copyFileToDirectory(final URL sourceFile, final Path targetDirectory,
final CopyOption... copyOptions) throws IOException {
try (final InputStream inputStream = sourceFile.openStream()) {
Files.copy(inputStream, targetDirectory.resolve(sourceFile.getFile()), copyOptions);
return targetDirectory;
}
}
/**
* Counts aspects of a directory including sub-directories.
*
* @param directory directory to delete.
* @return The visitor used to count the given directory.
* @throws IOException if an I/O error is thrown by a visitor method.
*/
public static PathCounters countDirectory(final Path directory) throws IOException {
return visitFileTree(new CountingPathVisitor(Counters.longPathCounters()), directory).getPathCounters();
}
/**
* Deletes a file or directory. If the path is a directory, delete it and all sub-directories.
*
* The difference between File.delete() and this method are:
*
*
* - A directory to delete does not have to be empty.
* - You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a
* boolean.
*
*
* @param path file or directory to delete, must not be {@code null}
* @return The visitor used to delete the given directory.
* @throws NullPointerException if the directory is {@code null}
* @throws IOException if an I/O error is thrown by a visitor method or if an I/O error occurs.
*/
public static PathCounters delete(final Path path) throws IOException {
return delete(path, EMPTY_DELETE_OPTION_ARRAY);
}
/**
* Deletes a file or directory. If the path is a directory, delete it and all sub-directories.
*
* The difference between File.delete() and this method are:
*
*
* - A directory to delete does not have to be empty.
* - You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a
* boolean.
*
*
* @param path file or directory to delete, must not be {@code null}
* @param options options indicating how deletion is handled.
* @return The visitor used to delete the given directory.
* @throws NullPointerException if the directory is {@code null}
* @throws IOException if an I/O error is thrown by a visitor method or if an I/O error occurs.
* @since 2.8.0
*/
public static PathCounters delete(final Path path, final DeleteOption... options) throws IOException {
// File deletion through Files deletes links, not targets, so use LinkOption.NOFOLLOW_LINKS.
return Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS) ? deleteDirectory(path, options)
: deleteFile(path, options);
}
/**
* Deletes a directory including sub-directories.
*
* @param directory directory to delete.
* @return The visitor used to delete the given directory.
* @throws IOException if an I/O error is thrown by a visitor method.
*/
public static PathCounters deleteDirectory(final Path directory) throws IOException {
return deleteDirectory(directory, EMPTY_DELETE_OPTION_ARRAY);
}
/**
* Deletes a directory including sub-directories.
*
* @param directory directory to delete.
* @param options options indicating how deletion is handled.
* @return The visitor used to delete the given directory.
* @throws IOException if an I/O error is thrown by a visitor method.
* @since 2.8.0
*/
public static PathCounters deleteDirectory(final Path directory, final DeleteOption... options) throws IOException {
return visitFileTree(new DeletingPathVisitor(Counters.longPathCounters(), options), directory)
.getPathCounters();
}
/**
* Deletes the given file.
*
* @param file The file to delete.
* @return A visitor with path counts set to 1 file, 0 directories, and the size of the deleted file.
* @throws IOException if an I/O error occurs.
* @throws NoSuchFileException if the file is a directory.
*/
public static PathCounters deleteFile(final Path file) throws IOException {
return deleteFile(file, EMPTY_DELETE_OPTION_ARRAY);
}
/**
* Deletes the given file.
*
* @param file The file to delete.
* @param options options indicating how deletion is handled.
* @return A visitor with path counts set to 1 file, 0 directories, and the size of the deleted file.
* @throws IOException if an I/O error occurs.
* @throws NoSuchFileException if the file is a directory.
* @since 2.8.0
*/
public static PathCounters deleteFile(final Path file, final DeleteOption... options) throws IOException {
// Files.deleteIfExists() never follows links, so use LinkOption.NOFOLLOW_LINKS in other calls to Files.
if (Files.isDirectory(file, LinkOption.NOFOLLOW_LINKS)) {
throw new NoSuchFileException(file.toString());
}
final PathCounters pathCounts = Counters.longPathCounters();
final boolean exists = Files.exists(file, LinkOption.NOFOLLOW_LINKS);
final long size = exists ? Files.size(file) : 0;
if (overrideReadOnly(options) && exists) {
setReadOnly(file, false, LinkOption.NOFOLLOW_LINKS);
}
if (Files.deleteIfExists(file)) {
pathCounts.getFileCounter().increment();
pathCounts.getByteCounter().add(size);
}
return pathCounts;
}
/**
* Returns true if the given options contain {@link StandardDeleteOption#OVERRIDE_READ_ONLY}.
*
* @param options the array to test
* @return true if the given options contain {@link StandardDeleteOption#OVERRIDE_READ_ONLY}.
*/
private static boolean overrideReadOnly(final DeleteOption[] options) {
if (options == null) {
return false;
}
for (final DeleteOption deleteOption : options) {
if (deleteOption == StandardDeleteOption.OVERRIDE_READ_ONLY) {
return true;
}
}
return false;
}
/**
* Compares the file sets of two Paths to determine if they are equal or not while considering file contents. The
* comparison includes all files in all sub-directories.
*
* @param path1 The first directory.
* @param path2 The second directory.
* @return Whether the two directories contain the same files while considering file contents.
* @throws IOException if an I/O error is thrown by a visitor method
*/
public static boolean directoryAndFileContentEquals(final Path path1, final Path path2) throws IOException {
return directoryAndFileContentEquals(path1, path2, EMPTY_LINK_OPTION_ARRAY, EMPTY_OPEN_OPTION_ARRAY,
EMPTY_FILE_VISIT_OPTION_ARRAY);
}
/**
* Compares the file sets of two Paths to determine if they are equal or not while considering file contents. The
* comparison includes all files in all sub-directories.
*
* @param path1 The first directory.
* @param path2 The second directory.
* @param linkOptions options to follow links.
* @param openOptions options to open files.
* @param fileVisitOption options to configure traversal.
* @return Whether the two directories contain the same files while considering file contents.
* @throws IOException if an I/O error is thrown by a visitor method
*/
public static boolean directoryAndFileContentEquals(final Path path1, final Path path2,
final LinkOption[] linkOptions, final OpenOption[] openOptions, final FileVisitOption[] fileVisitOption)
throws IOException {
// First walk both file trees and gather normalized paths.
if (path1 == null && path2 == null) {
return true;
}
if (path1 == null ^ path2 == null) {
return false;
}
if (!Files.exists(path1) && !Files.exists(path2)) {
return true;
}
final RelativeSortedPaths relativeSortedPaths = new RelativeSortedPaths(path1, path2, Integer.MAX_VALUE,
linkOptions, fileVisitOption);
// If the normalized path names and counts are not the same, no need to compare contents.
if (!relativeSortedPaths.equals) {
return false;
}
// Both visitors contain the same normalized paths, we can compare file contents.
final List fileList1 = relativeSortedPaths.relativeFileList1;
final List fileList2 = relativeSortedPaths.relativeFileList2;
for (final Path path : fileList1) {
final int binarySearch = Collections.binarySearch(fileList2, path);
if (binarySearch > -1) {
if (!fileContentEquals(path1.resolve(path), path2.resolve(path), linkOptions, openOptions)) {
return false;
}
} else {
throw new IllegalStateException("Unexpected mismatch.");
}
}
return true;
}
/**
* Compares the file sets of two Paths to determine if they are equal or not without considering file contents. The
* comparison includes all files in all sub-directories.
*
* @param path1 The first directory.
* @param path2 The second directory.
* @return Whether the two directories contain the same files without considering file contents.
* @throws IOException if an I/O error is thrown by a visitor method
*/
public static boolean directoryContentEquals(final Path path1, final Path path2) throws IOException {
return directoryContentEquals(path1, path2, Integer.MAX_VALUE, EMPTY_LINK_OPTION_ARRAY,
EMPTY_FILE_VISIT_OPTION_ARRAY);
}
/**
* Compares the file sets of two Paths to determine if they are equal or not without considering file contents. The
* comparison includes all files in all sub-directories.
*
* @param path1 The first directory.
* @param path2 The second directory.
* @param maxDepth See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @param linkOptions options to follow links.
* @param fileVisitOptions options to configure the traversal
* @return Whether the two directories contain the same files without considering file contents.
* @throws IOException if an I/O error is thrown by a visitor method
*/
public static boolean directoryContentEquals(final Path path1, final Path path2, final int maxDepth,
final LinkOption[] linkOptions, final FileVisitOption[] fileVisitOptions) throws IOException {
return new RelativeSortedPaths(path1, path2, maxDepth, linkOptions, fileVisitOptions).equals;
}
/**
* Compares the file contents of two Paths to determine if they are equal or not.
*
* File content is accessed through {@link Files#newInputStream(Path,OpenOption...)}.
*
*
* @param path1 the first stream.
* @param path2 the second stream.
* @return true if the content of the streams are equal or they both don't exist, false otherwise.
* @throws NullPointerException if either input is null.
* @throws IOException if an I/O error occurs.
* @see org.apache.commons.io.FileUtils#contentEquals(java.io.File, java.io.File)
*/
public static boolean fileContentEquals(final Path path1, final Path path2) throws IOException {
return fileContentEquals(path1, path2, EMPTY_LINK_OPTION_ARRAY, EMPTY_OPEN_OPTION_ARRAY);
}
/**
* Compares the file contents of two Paths to determine if they are equal or not.
*
* File content is accessed through {@link Files#newInputStream(Path,OpenOption...)}.
*
*
* @param path1 the first stream.
* @param path2 the second stream.
* @param linkOptions options specifying how files are followed.
* @param openOptions options specifying how files are opened.
* @return true if the content of the streams are equal or they both don't exist, false otherwise.
* @throws NullPointerException if either input is null.
* @throws IOException if an I/O error occurs.
* @see org.apache.commons.io.FileUtils#contentEquals(java.io.File, java.io.File)
*/
public static boolean fileContentEquals(final Path path1, final Path path2, final LinkOption[] linkOptions,
final OpenOption[] openOptions) throws IOException {
if (path1 == null && path2 == null) {
return true;
}
if (path1 == null ^ path2 == null) {
return false;
}
final Path nPath1 = path1.normalize();
final Path nPath2 = path2.normalize();
final boolean path1Exists = Files.exists(nPath1, linkOptions);
if (path1Exists != Files.exists(nPath2, linkOptions)) {
return false;
}
if (!path1Exists) {
// Two not existing files are equal?
// Same as FileUtils
return true;
}
if (Files.isDirectory(nPath1, linkOptions)) {
// don't compare directory contents.
throw new IOException("Can't compare directories, only files: " + nPath1);
}
if (Files.isDirectory(nPath2, linkOptions)) {
// don't compare directory contents.
throw new IOException("Can't compare directories, only files: " + nPath2);
}
if (Files.size(nPath1) != Files.size(nPath2)) {
// lengths differ, cannot be equal
return false;
}
if (path1.equals(path2)) {
// same file
return true;
}
try (final InputStream inputStream1 = Files.newInputStream(nPath1, openOptions);
final InputStream inputStream2 = Files.newInputStream(nPath2, openOptions)) {
return IOUtils.contentEquals(inputStream1, inputStream2);
}
}
/**
* Reads the access control list from a file attribute view.
*
* @param sourcePath the path to the file.
* @return a file attribute view of the specified type, or null ifthe attribute view type is not available.
* @throws IOException if an I/O error occurs.
* @since 2.8.0
*/
public static List getAclEntryList(final Path sourcePath) throws IOException {
final AclFileAttributeView fileAttributeView = Files.getFileAttributeView(sourcePath,
AclFileAttributeView.class);
return fileAttributeView == null ? null : fileAttributeView.getAcl();
}
/**
* Returns whether the given file or directory is empty.
*
* @param path the the given file or directory to query.
* @return whether the given file or directory is empty.
* @throws IOException if an I/O error occurs
*/
public static boolean isEmpty(final Path path) throws IOException {
return Files.isDirectory(path) ? isEmptyDirectory(path) : isEmptyFile(path);
}
/**
* Returns whether the directory is empty.
*
* @param directory the the given directory to query.
* @return whether the given directory is empty.
* @throws IOException if an I/O error occurs
*/
public static boolean isEmptyDirectory(final Path directory) throws IOException {
try (DirectoryStream directoryStream = Files.newDirectoryStream(directory)) {
if (directoryStream.iterator().hasNext()) {
return false;
}
}
return true;
}
/**
* Returns whether the given file is empty.
*
* @param file the the given file to query.
* @return whether the given file is empty.
* @throws IOException if an I/O error occurs
*/
public static boolean isEmptyFile(final Path file) throws IOException {
return Files.size(file) <= 0;
}
/**
* Relativizes all files in the given {@code collection} against a {@code parent}.
*
* @param collection The collection of paths to relativize.
* @param parent relativizes against this parent path.
* @param sort Whether to sort the result.
* @param comparator How to sort.
* @return A collection of relativized paths, optionally sorted.
*/
static List relativize(final Collection collection, final Path parent, final boolean sort,
final Comparator super Path> comparator) {
Stream stream = collection.stream().map(parent::relativize);
if (sort) {
stream = comparator == null ? stream.sorted() : stream.sorted(comparator);
}
return stream.collect(Collectors.toList());
}
/**
* Sets the given Path to the {@code readOnly} value.
*
* This behavior is OS dependent.
*
*
* @param path The path to set.
* @param readOnly true for read-only, false for not read-only.
* @param options options indicating how symbolic links are handled.
* @return The given path.
* @throws IOException if an I/O error occurs.
* @since 2.8.0
*/
public static Path setReadOnly(final Path path, final boolean readOnly, final LinkOption... options)
throws IOException {
final DosFileAttributeView fileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class,
options);
if (fileAttributeView != null) {
fileAttributeView.setReadOnly(readOnly);
return path;
}
final PosixFileAttributeView posixFileAttributeView = Files.getFileAttributeView(path,
PosixFileAttributeView.class, options);
if (posixFileAttributeView != null) {
// Works on Windows but not on Ubuntu:
// Files.setAttribute(path, "unix:readonly", readOnly, options);
// java.lang.IllegalArgumentException: 'unix:readonly' not recognized
final PosixFileAttributes readAttributes = posixFileAttributeView.readAttributes();
final Set permissions = readAttributes.permissions();
permissions.remove(PosixFilePermission.OWNER_WRITE);
permissions.remove(PosixFilePermission.GROUP_WRITE);
permissions.remove(PosixFilePermission.OTHERS_WRITE);
return Files.setPosixFilePermissions(path, permissions);
}
throw new IOException("No DosFileAttributeView or PosixFileAttributeView for " + path);
}
/**
* Converts an array of {@link FileVisitOption} to a {@link Set}.
*
* @param fileVisitOptions input array.
* @return a new Set.
*/
static Set toFileVisitOptionSet(final FileVisitOption... fileVisitOptions) {
return fileVisitOptions == null ? EnumSet.noneOf(FileVisitOption.class)
: Arrays.stream(fileVisitOptions).collect(Collectors.toSet());
}
/**
* Performs {@link Files#walkFileTree(Path,FileVisitor)} and returns the given visitor.
*
* Note that {@link Files#walkFileTree(Path,FileVisitor)} returns the given path.
*
* @param visitor See {@link Files#walkFileTree(Path,FileVisitor)}.
* @param directory See {@link Files#walkFileTree(Path,FileVisitor)}.
* @param See {@link Files#walkFileTree(Path,FileVisitor)}.
* @return the given visitor.
*
* @throws IOException if an I/O error is thrown by a visitor method
*/
public static > T visitFileTree(final T visitor, final Path directory)
throws IOException {
Files.walkFileTree(directory, visitor);
return visitor;
}
/**
* Performs {@link Files#walkFileTree(Path,FileVisitor)} and returns the given visitor.
*
* Note that {@link Files#walkFileTree(Path,FileVisitor)} returns the given path.
*
* @param start See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @param options See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @param maxDepth See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @param visitor See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @param See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @return the given visitor.
*
* @throws IOException if an I/O error is thrown by a visitor method
*/
public static > T visitFileTree(final T visitor, final Path start,
final Set options, final int maxDepth) throws IOException {
Files.walkFileTree(start, options, maxDepth, visitor);
return visitor;
}
/**
* Performs {@link Files#walkFileTree(Path,FileVisitor)} and returns the given visitor.
*
* Note that {@link Files#walkFileTree(Path,FileVisitor)} returns the given path.
*
* @param visitor See {@link Files#walkFileTree(Path,FileVisitor)}.
* @param first See {@link Paths#get(String,String[])}.
* @param more See {@link Paths#get(String,String[])}.
* @param See {@link Files#walkFileTree(Path,FileVisitor)}.
* @return the given visitor.
*
* @throws IOException if an I/O error is thrown by a visitor method
*/
public static > T visitFileTree(final T visitor, final String first,
final String... more) throws IOException {
return visitFileTree(visitor, Paths.get(first, more));
}
/**
* Performs {@link Files#walkFileTree(Path,FileVisitor)} and returns the given visitor.
*
* Note that {@link Files#walkFileTree(Path,FileVisitor)} returns the given path.
*
* @param visitor See {@link Files#walkFileTree(Path,FileVisitor)}.
* @param uri See {@link Paths#get(URI)}.
* @param See {@link Files#walkFileTree(Path,FileVisitor)}.
* @return the given visitor.
*
* @throws IOException if an I/O error is thrown by a visitor method
*/
public static > T visitFileTree(final T visitor, final URI uri)
throws IOException {
return visitFileTree(visitor, Paths.get(uri));
}
/**
* Does allow to instantiate.
*/
private PathUtils() {
// do not instantiate.
}
}