This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-io.git
The following commit(s) were added to refs/heads/master by this push: new 3cb5fd7 Add tests for PathUtils.newOutputStream() and fix PathUtils.newOutputStream(). 3cb5fd7 is described below commit 3cb5fd7b5a6349fcf27e9025e4a42d812a492b43 Author: Gary Gregory <gardgreg...@gmail.com> AuthorDate: Wed Aug 4 17:16:38 2021 -0400 Add tests for PathUtils.newOutputStream() and fix PathUtils.newOutputStream(). --- .../java/org/apache/commons/io/file/PathUtils.java | 226 +++++++++------------ .../org/apache/commons/io/file/PathUtilsTest.java | 46 +++++ 2 files changed, 138 insertions(+), 134 deletions(-) diff --git a/src/main/java/org/apache/commons/io/file/PathUtils.java b/src/main/java/org/apache/commons/io/file/PathUtils.java index fa16f1d..da90fec 100644 --- a/src/main/java/org/apache/commons/io/file/PathUtils.java +++ b/src/main/java/org/apache/commons/io/file/PathUtils.java @@ -73,8 +73,8 @@ import org.apache.commons.io.filefilter.IOFileFilter; 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 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 { @@ -94,8 +94,8 @@ public final class PathUtils { * @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 { + private RelativeSortedPaths(final Path dir1, final Path dir2, final int maxDepth, final LinkOption[] linkOptions, + final FileVisitOption[] fileVisitOptions) throws IOException { final List<Path> tmpRelativeDirList1; final List<Path> tmpRelativeDirList2; List<Path> tmpRelativeFileList1 = null; @@ -112,8 +112,7 @@ public final class PathUtils { } 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()) { + if (visitor1.getDirList().size() != visitor2.getDirList().size() || visitor1.getFileList().size() != visitor2.getFileList().size()) { equals = false; } else { tmpRelativeDirList1 = visitor1.relativizeDirectories(dir1, true, null); @@ -187,10 +186,8 @@ public final class PathUtils { * @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); + private static AccumulatorPathVisitor accumulate(final Path directory, final int maxDepth, final FileVisitOption[] fileVisitOptions) throws IOException { + return visitFileTree(AccumulatorPathVisitor.withLongCounters(), directory, toFileVisitOptionSet(fileVisitOptions), maxDepth); } /** @@ -213,10 +210,8 @@ public final class PathUtils { * @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... deleteOptions) - throws IOException { - return visitFileTree(new CleaningPathVisitor(Counters.longPathCounters(), deleteOptions), directory) - .getPathCounters(); + public static PathCounters cleanDirectory(final Path directory, final DeleteOption... deleteOptions) throws IOException { + return visitFileTree(new CleaningPathVisitor(Counters.longPathCounters(), deleteOptions), directory).getPathCounters(); } /** @@ -228,12 +223,10 @@ public final class PathUtils { * @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 { + public static PathCounters copyDirectory(final Path sourceDirectory, final Path targetDirectory, final CopyOption... copyOptions) throws IOException { final Path absoluteSource = sourceDirectory.toAbsolutePath(); - return visitFileTree( - new CopyDirectoryVisitor(Counters.longPathCounters(), absoluteSource, targetDirectory, copyOptions), - absoluteSource).getPathCounters(); + return visitFileTree(new CopyDirectoryVisitor(Counters.longPathCounters(), absoluteSource, targetDirectory, copyOptions), absoluteSource) + .getPathCounters(); } /** @@ -246,8 +239,7 @@ public final class PathUtils { * @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 { + 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; @@ -264,8 +256,7 @@ public final class PathUtils { * @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 { + public static Path copyFileToDirectory(final Path sourceFile, final Path targetDirectory, final CopyOption... copyOptions) throws IOException { return Files.copy(sourceFile, targetDirectory.resolve(sourceFile.getFileName()), copyOptions); } @@ -279,8 +270,7 @@ public final class PathUtils { * @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 { + 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; @@ -333,8 +323,7 @@ public final class PathUtils { * </p> * <ul> * <li>A directory to delete does not have to be empty.</li> - * <li>You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a - * boolean. + * <li>You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a boolean. * </ul> * * @param path file or directory to delete, must not be {@code null} @@ -353,8 +342,7 @@ public final class PathUtils { * </p> * <ul> * <li>A directory to delete does not have to be empty.</li> - * <li>You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a - * boolean. + * <li>You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a boolean. * </ul> * * @param path file or directory to delete, must not be {@code null} @@ -366,8 +354,7 @@ public final class PathUtils { */ public static PathCounters delete(final Path path, final DeleteOption... deleteOptions) throws IOException { // File deletion through Files deletes links, not targets, so use LinkOption.NOFOLLOW_LINKS. - return Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS) ? deleteDirectory(path, deleteOptions) - : deleteFile(path, deleteOptions); + return Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS) ? deleteDirectory(path, deleteOptions) : deleteFile(path, deleteOptions); } /** @@ -377,8 +364,7 @@ public final class PathUtils { * </p> * <ul> * <li>A directory to delete does not have to be empty.</li> - * <li>You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a - * boolean. + * <li>You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a boolean. * </ul> * * @param path file or directory to delete, must not be {@code null} @@ -389,11 +375,9 @@ public final class PathUtils { * @throws IOException if an I/O error is thrown by a visitor method or if an I/O error occurs. * @since 2.9.0 */ - public static PathCounters delete(final Path path, final LinkOption[] linkOptions, - final DeleteOption... deleteOptions) throws IOException { + public static PathCounters delete(final Path path, final LinkOption[] linkOptions, final DeleteOption... deleteOptions) throws IOException { // File deletion through Files deletes links, not targets, so use LinkOption.NOFOLLOW_LINKS. - return Files.isDirectory(path, linkOptions) ? deleteDirectory(path, linkOptions, deleteOptions) - : deleteFile(path, linkOptions, deleteOptions); + return Files.isDirectory(path, linkOptions) ? deleteDirectory(path, linkOptions, deleteOptions) : deleteFile(path, linkOptions, deleteOptions); } /** @@ -416,11 +400,9 @@ public final class PathUtils { * @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... deleteOptions) - throws IOException { - return visitFileTree( - new DeletingPathVisitor(Counters.longPathCounters(), PathUtils.NOFOLLOW_LINK_OPTION_ARRAY, deleteOptions), - directory).getPathCounters(); + public static PathCounters deleteDirectory(final Path directory, final DeleteOption... deleteOptions) throws IOException { + return visitFileTree(new DeletingPathVisitor(Counters.longPathCounters(), PathUtils.NOFOLLOW_LINK_OPTION_ARRAY, deleteOptions), directory) + .getPathCounters(); } /** @@ -433,10 +415,8 @@ public final class PathUtils { * @throws IOException if an I/O error is thrown by a visitor method. * @since 2.9.0 */ - public static PathCounters deleteDirectory(final Path directory, final LinkOption[] linkOptions, - final DeleteOption... deleteOptions) throws IOException { - return visitFileTree(new DeletingPathVisitor(Counters.longPathCounters(), linkOptions, deleteOptions), - directory).getPathCounters(); + public static PathCounters deleteDirectory(final Path directory, final LinkOption[] linkOptions, final DeleteOption... deleteOptions) throws IOException { + return visitFileTree(new DeletingPathVisitor(Counters.longPathCounters(), linkOptions, deleteOptions), directory).getPathCounters(); } /** @@ -477,8 +457,8 @@ public final class PathUtils { * @throws NoSuchFileException if the file is a directory. * @since 2.9.0 */ - public static PathCounters deleteFile(final Path file, final LinkOption[] linkOptions, - final DeleteOption... deleteOptions) throws NoSuchFileException, IOException { + public static PathCounters deleteFile(final Path file, final LinkOption[] linkOptions, final DeleteOption... deleteOptions) + throws NoSuchFileException, IOException { if (Files.isDirectory(file, linkOptions)) { throw new NoSuchFileException(file.toString()); } @@ -505,8 +485,7 @@ public final class PathUtils { * @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); + return directoryAndFileContentEquals(path1, path2, EMPTY_LINK_OPTION_ARRAY, EMPTY_OPEN_OPTION_ARRAY, EMPTY_FILE_VISIT_OPTION_ARRAY); } /** @@ -521,9 +500,8 @@ public final class PathUtils { * @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 { + 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; @@ -534,8 +512,7 @@ public final class PathUtils { if (Files.notExists(path1) && Files.notExists(path2)) { return true; } - final RelativeSortedPaths relativeSortedPaths = new RelativeSortedPaths(path1, path2, Integer.MAX_VALUE, - linkOptions, fileVisitOption); + 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; @@ -565,8 +542,7 @@ public final class PathUtils { * @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); + return directoryContentEquals(path1, path2, Integer.MAX_VALUE, EMPTY_LINK_OPTION_ARRAY, EMPTY_FILE_VISIT_OPTION_ARRAY); } /** @@ -581,8 +557,8 @@ public final class PathUtils { * @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 { + 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; } @@ -618,8 +594,8 @@ public final class PathUtils { * @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 { + 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; } @@ -661,8 +637,8 @@ public final class PathUtils { /** * <p> - * Applies an {@link IOFileFilter} to the provided {@link File} objects. The resulting array is a subset of the - * original file list that matches the provided filter. + * Applies an {@link IOFileFilter} to the provided {@link File} objects. The resulting array is a subset of the original + * file list that matches the provided filter. * </p> * * <p> @@ -679,8 +655,7 @@ public final class PathUtils { * @param paths the array of files to apply the filter to. * * @return a subset of {@code files} that is accepted by the file filter. - * @throws IllegalArgumentException if the filter is {@code null} or {@code files} contains a {@code null} - * value. + * @throws IllegalArgumentException if the filter is {@code null} or {@code files} contains a {@code null} value. * * @since 2.9.0 */ @@ -692,8 +667,7 @@ public final class PathUtils { return filterPaths(filter, Stream.of(paths), Collectors.toList()).toArray(EMPTY_PATH_ARRAY); } - private static <R, A> R filterPaths(final PathFilter filter, final Stream<Path> stream, - final Collector<? super Path, A, R> collector) { + private static <R, A> R filterPaths(final PathFilter filter, final Stream<Path> stream, final Collector<? super Path, A, R> collector) { Objects.requireNonNull(filter, "filter"); Objects.requireNonNull(collector, "collector"); if (stream == null) { @@ -717,23 +691,20 @@ public final class PathUtils { * @since 2.8.0 */ public static List<AclEntry> getAclEntryList(final Path sourcePath) throws IOException { - final AclFileAttributeView fileAttributeView = Files.getFileAttributeView(sourcePath, - AclFileAttributeView.class); + final AclFileAttributeView fileAttributeView = Files.getFileAttributeView(sourcePath, AclFileAttributeView.class); return fileAttributeView == null ? null : fileAttributeView.getAcl(); } /** - * Tests whether the specified {@code Path} is a directory or not. Implemented as a - * null-safe delegate to {@code Files.isDirectory(Path path, LinkOption... options)}. - * - * @param path the path to the file. - * @param options options indicating how symbolic links are handled - * @return {@code true} if the file is a directory; {@code false} if - * the path is null, the file does not exist, is not a directory, or it cannot - * be determined if the file is a directory or not. - * @throws SecurityException In the case of the default provider, and a security manager is installed, the - * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read - * access to the directory. + * Tests whether the specified {@code Path} is a directory or not. Implemented as a null-safe delegate to + * {@code Files.isDirectory(Path path, LinkOption... options)}. + * + * @param path the path to the file. + * @param options options indicating how symbolic links are handled + * @return {@code true} if the file is a directory; {@code false} if the path is null, the file does not exist, is not a + * directory, or it cannot be determined if the file is a directory or not. + * @throws SecurityException In the case of the default provider, and a security manager is installed, the + * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read access to the directory. * @since 2.9.0 */ public static boolean isDirectory(final Path path, final LinkOption... options) { @@ -756,12 +727,11 @@ public final class PathUtils { * * @param directory the directory to query. * @return whether the directory is empty. - * @throws NotDirectoryException if the file could not otherwise be opened because it is not a directory - * <i>(optional specific exception)</i>. - * @throws IOException if an I/O error occurs. - * @throws SecurityException In the case of the default provider, and a security manager is installed, the - * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read - * access to the directory. + * @throws NotDirectoryException if the file could not otherwise be opened because it is not a directory <i>(optional + * specific exception)</i>. + * @throws IOException if an I/O error occurs. + * @throws SecurityException In the case of the default provider, and a security manager is installed, the + * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read access to the directory. */ public static boolean isEmptyDirectory(final Path directory) throws IOException { try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(directory)) { @@ -774,10 +744,9 @@ public final class PathUtils { * * @param file the file to query. * @return whether the file is empty. - * @throws IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * @throws SecurityException In the case of the default provider, and a security manager is installed, its - * {@link SecurityManager#checkRead(String) checkRead} method denies read access to the - * file. + * {@link SecurityManager#checkRead(String) checkRead} method denies read access to the file. */ public static boolean isEmptyFile(final Path file) throws IOException { return Files.size(file) <= 0; @@ -788,15 +757,14 @@ public final class PathUtils { * * @param file the {@code Path} of which the modification date must be compared * @param timeMillis the time reference measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970) - * @param options options indicating how symbolic links are handled * @return true if the {@code Path} exists and - * has been modified after the given time reference. + * @param options options indicating how symbolic links are handled * @return true if the {@code Path} exists and has + * been modified after the given time reference. * @return true if the {@code Path} exists and has been modified after the given time reference. * @throws IOException if an I/O error occurs. * @throws NullPointerException if the file is {@code null} * @since 2.9.0 */ - public static boolean isNewer(final Path file, final long timeMillis, final LinkOption... options) - throws IOException { + public static boolean isNewer(final Path file, final long timeMillis, final LinkOption... options) throws IOException { Objects.requireNonNull(file, "file"); if (Files.notExists(file)) { return false; @@ -805,17 +773,15 @@ public final class PathUtils { } /** - * Tests whether the specified {@code Path} is a regular file or not. Implemented as a - * null-safe delegate to {@code Files.isRegularFile(Path path, LinkOption... options)}. - * - * @param path the path to the file. - * @param options options indicating how symbolic links are handled - * @return {@code true} if the file is a regular file; {@code false} if - * the path is null, the file does not exist, is not a directory, or it cannot - * be determined if the file is a regular file or not. - * @throws SecurityException In the case of the default provider, and a security manager is installed, the - * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read - * access to the directory. + * Tests whether the specified {@code Path} is a regular file or not. Implemented as a null-safe delegate to + * {@code Files.isRegularFile(Path path, LinkOption... options)}. + * + * @param path the path to the file. + * @param options options indicating how symbolic links are handled + * @return {@code true} if the file is a regular file; {@code false} if the path is null, the file does not exist, is + * not a directory, or it cannot be determined if the file is a regular file or not. + * @throws SecurityException In the case of the default provider, and a security manager is installed, the + * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read access to the directory. * @since 2.9.0 */ public static boolean isRegularFile(final Path path, final LinkOption... options) { @@ -830,14 +796,14 @@ public final class PathUtils { * @return a new instance. * @throws IOException if an I/O error occurs. */ - public static DirectoryStream<Path> newDirectoryStream(final Path dir, final PathFilter pathFilter) - throws IOException { + public static DirectoryStream<Path> newDirectoryStream(final Path dir, final PathFilter pathFilter) throws IOException { return Files.newDirectoryStream(dir, new DirectoryStreamFilter(pathFilter)); } /** * Creates a new OutputStream by opening or creating a file, returning an output stream that may be used to write bytes * to the file. + * * @param path the Path. * @param append Whether or not to append. * @@ -847,9 +813,11 @@ public final class PathUtils { * @since 2.12.0 */ public static OutputStream newOutputStream(final Path path, final boolean append) throws IOException { + // @formatter:off return Files.newOutputStream(path, append ? - new OpenOption[] {StandardOpenOption.APPEND} : + new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.APPEND} : new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING}); + // @formatter:on } /** @@ -878,8 +846,8 @@ public final class PathUtils { } /** - * Shorthand for {@code Files.readAttributes(path, BasicFileAttributes.class)} while wrapping {@link IOException} - * as {@link UncheckedIOException}. + * Shorthand for {@code Files.readAttributes(path, BasicFileAttributes.class)} while wrapping {@link IOException} as + * {@link UncheckedIOException}. * * @param path the path to read. * @return the path attributes. @@ -917,8 +885,7 @@ public final class PathUtils { * @param comparator How to sort. * @return A collection of relativized paths, optionally sorted. */ - static List<Path> relativize(final Collection<Path> collection, final Path parent, final boolean sort, - final Comparator<? super Path> comparator) { + static List<Path> relativize(final Collection<Path> collection, final Path parent, final boolean sort, final Comparator<? super Path> comparator) { Stream<Path> stream = collection.stream().map(parent::relativize); if (sort) { stream = comparator == null ? stream.sorted() : stream.sorted(comparator); @@ -939,11 +906,9 @@ public final class PathUtils { * @throws IOException if an I/O error occurs. * @since 2.8.0 */ - public static Path setReadOnly(final Path path, final boolean readOnly, final LinkOption... linkOptions) - throws IOException { + public static Path setReadOnly(final Path path, final boolean readOnly, final LinkOption... linkOptions) throws IOException { final List<Exception> causeList = new ArrayList<>(2); - final DosFileAttributeView fileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class, - linkOptions); + final DosFileAttributeView fileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class, linkOptions); if (fileAttributeView != null) { try { fileAttributeView.setReadOnly(readOnly); @@ -953,8 +918,7 @@ public final class PathUtils { causeList.add(e); } } - final PosixFileAttributeView posixFileAttributeView = Files.getFileAttributeView(path, - PosixFileAttributeView.class, linkOptions); + final PosixFileAttributeView posixFileAttributeView = Files.getFileAttributeView(path, PosixFileAttributeView.class, linkOptions); if (posixFileAttributeView != null) { // Works on Windows but not on Ubuntu: // Files.setAttribute(path, "unix:readonly", readOnly, options); @@ -973,9 +937,7 @@ public final class PathUtils { if (!causeList.isEmpty()) { throw new IOExceptionList(path.toString(), causeList); } - throw new IOException( - String.format("No DosFileAttributeView or PosixFileAttributeView for '%s' (linkOptions=%s)", path, - Arrays.toString(linkOptions))); + throw new IOException(String.format("No DosFileAttributeView or PosixFileAttributeView for '%s' (linkOptions=%s)", path, Arrays.toString(linkOptions))); } /** @@ -985,8 +947,7 @@ public final class PathUtils { * @return a new Set. */ static Set<FileVisitOption> toFileVisitOptionSet(final FileVisitOption... fileVisitOptions) { - return fileVisitOptions == null ? EnumSet.noneOf(FileVisitOption.class) - : Stream.of(fileVisitOptions).collect(Collectors.toSet()); + return fileVisitOptions == null ? EnumSet.noneOf(FileVisitOption.class) : Stream.of(fileVisitOptions).collect(Collectors.toSet()); } /** @@ -1001,8 +962,7 @@ public final class PathUtils { * * @throws IOException if an I/O error is thrown by a visitor method */ - public static <T extends FileVisitor<? super Path>> T visitFileTree(final T visitor, final Path directory) - throws IOException { + public static <T extends FileVisitor<? super Path>> T visitFileTree(final T visitor, final Path directory) throws IOException { Files.walkFileTree(directory, visitor); return visitor; } @@ -1021,8 +981,8 @@ public final class PathUtils { * * @throws IOException if an I/O error is thrown by a visitor method */ - public static <T extends FileVisitor<? super Path>> T visitFileTree(final T visitor, final Path start, - final Set<FileVisitOption> options, final int maxDepth) throws IOException { + public static <T extends FileVisitor<? super Path>> T visitFileTree(final T visitor, final Path start, final Set<FileVisitOption> options, + final int maxDepth) throws IOException { Files.walkFileTree(start, options, maxDepth, visitor); return visitor; } @@ -1040,8 +1000,7 @@ public final class PathUtils { * * @throws IOException if an I/O error is thrown by a visitor method */ - public static <T extends FileVisitor<? super Path>> T visitFileTree(final T visitor, final String first, - final String... more) throws IOException { + public static <T extends FileVisitor<? super Path>> T visitFileTree(final T visitor, final String first, final String... more) throws IOException { return visitFileTree(visitor, Paths.get(first, more)); } @@ -1057,8 +1016,7 @@ public final class PathUtils { * * @throws IOException if an I/O error is thrown by a visitor method */ - public static <T extends FileVisitor<? super Path>> T visitFileTree(final T visitor, final URI uri) - throws IOException { + public static <T extends FileVisitor<? super Path>> T visitFileTree(final T visitor, final URI uri) throws IOException { return visitFileTree(visitor, Paths.get(uri)); } @@ -1074,10 +1032,10 @@ public final class PathUtils { * @throws IOException if an I/O error is thrown when accessing the starting file. * @since 2.9.0 */ - public static Stream<Path> walk(final Path start, final PathFilter pathFilter, final int maxDepth, - final boolean readAttributes, final FileVisitOption... options) throws IOException { - return Files.walk(start, maxDepth, options).filter(path -> pathFilter.accept(path, - readAttributes ? readBasicFileAttributesUnchecked(path) : null) == FileVisitResult.CONTINUE); + public static Stream<Path> walk(final Path start, final PathFilter pathFilter, final int maxDepth, final boolean readAttributes, + final FileVisitOption... options) throws IOException { + return Files.walk(start, maxDepth, options) + .filter(path -> pathFilter.accept(path, readAttributes ? readBasicFileAttributesUnchecked(path) : null) == FileVisitResult.CONTINUE); } /** diff --git a/src/test/java/org/apache/commons/io/file/PathUtilsTest.java b/src/test/java/org/apache/commons/io/file/PathUtilsTest.java index ef3e5b8..f90b267 100644 --- a/src/test/java/org/apache/commons/io/file/PathUtilsTest.java +++ b/src/test/java/org/apache/commons/io/file/PathUtilsTest.java @@ -17,11 +17,13 @@ package org.apache.commons.io.file; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; +import java.io.OutputStream; import java.net.URI; import java.nio.charset.StandardCharsets; import java.nio.file.DirectoryStream; @@ -35,6 +37,7 @@ import java.util.Iterator; import java.util.Map; import org.apache.commons.io.filefilter.NameFileFilter; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -44,6 +47,10 @@ import org.junit.jupiter.api.io.TempDir; */ public class PathUtilsTest extends TestArguments { + private static final String STRING_FIXTURE = "Hello World"; + + private static final byte[] BYTE_ARRAY_FIXTURE = STRING_FIXTURE.getBytes(StandardCharsets.UTF_8); + private static final String TEST_JAR_NAME = "test.jar"; private static final String TEST_JAR_PATH = "src/test/resources/org/apache/commons/io/test.jar"; @@ -190,6 +197,34 @@ public class PathUtilsTest extends TestArguments { } @Test + public void testNewOutputStreamExistingFileAppendFalse() throws IOException { + testNewOutputStreamNewFile(false); + testNewOutputStreamNewFile(false); + } + + @Test + public void testNewOutputStreamExistingFileAppendTrue() throws IOException { + testNewOutputStreamNewFile(true); + final Path file = writeToNewOutputStream(true); + assertArrayEquals(ArrayUtils.addAll(BYTE_ARRAY_FIXTURE, BYTE_ARRAY_FIXTURE), Files.readAllBytes(file)); + } + + public void testNewOutputStreamNewFile(final boolean append) throws IOException { + final Path file = writeToNewOutputStream(append); + assertArrayEquals(BYTE_ARRAY_FIXTURE, Files.readAllBytes(file)); + } + + @Test + public void testNewOutputStreamNewFileAppendFalse() throws IOException { + testNewOutputStreamNewFile(false); + } + + @Test + public void testNewOutputStreamNewFileAppendTrue() throws IOException { + testNewOutputStreamNewFile(true); + } + + @Test public void testReadStringEmptyFile() throws IOException { final Path path = Paths.get("src/test/resources/org/apache/commons/io/test-file-empty.bin"); assertEquals(StringUtils.EMPTY, PathUtils.readString(path, StandardCharsets.UTF_8)); @@ -204,4 +239,15 @@ public class PathUtilsTest extends TestArguments { assertEquals(expected, PathUtils.readString(path, null)); } + /** + * Tests newOutputStream() here and don't use Files.write obviously. + */ + private Path writeToNewOutputStream(final boolean append) throws IOException { + final Path file = tempDir.resolve("test1.txt"); + try (OutputStream os = PathUtils.newOutputStream(file, append)) { + os.write(BYTE_ARRAY_FIXTURE); + } + return file; + } + }