aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/apache/commons/io/ByteOrderMark.java7
-rw-r--r--src/main/java/org/apache/commons/io/CopyUtils.java2
-rw-r--r--src/main/java/org/apache/commons/io/EndianUtils.java2
-rw-r--r--src/main/java/org/apache/commons/io/FileUtils.java119
-rw-r--r--src/main/java/org/apache/commons/io/FilenameUtils.java4
-rw-r--r--src/main/java/org/apache/commons/io/HexDump.java2
-rw-r--r--src/main/java/org/apache/commons/io/IOIndexedException.java3
-rw-r--r--src/main/java/org/apache/commons/io/IOUtils.java22
-rw-r--r--src/main/java/org/apache/commons/io/RandomAccessFileMode.java3
-rw-r--r--src/main/java/org/apache/commons/io/RandomAccessFiles.java55
-rw-r--r--src/main/java/org/apache/commons/io/StreamIterator.java48
-rw-r--r--src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java5
-rw-r--r--src/main/java/org/apache/commons/io/channels/FileChannels.java87
-rw-r--r--src/main/java/org/apache/commons/io/channels/package-info.java23
-rw-r--r--src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java7
-rw-r--r--src/main/java/org/apache/commons/io/file/FilesUncheck.java60
-rw-r--r--src/main/java/org/apache/commons/io/file/PathUtils.java65
-rw-r--r--src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java18
-rw-r--r--src/main/java/org/apache/commons/io/filefilter/package-info.java2
-rw-r--r--src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java4
-rw-r--r--src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java3
-rw-r--r--src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java29
-rw-r--r--src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java193
-rw-r--r--src/main/java/org/apache/commons/io/input/ObservableInputStream.java2
-rw-r--r--src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java3
-rw-r--r--src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java2
-rw-r--r--src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.java30
-rw-r--r--src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java12
-rw-r--r--src/main/java/org/apache/commons/io/input/XmlStreamReader.java20
-rw-r--r--src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java47
-rw-r--r--src/main/java/org/apache/commons/io/output/LockableFileWriter.java3
-rw-r--r--src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java14
-rw-r--r--src/main/java/org/apache/commons/io/output/WriterOutputStream.java3
-rw-r--r--src/main/java/org/apache/commons/io/output/XmlStreamWriter.java3
-rw-r--r--src/main/java/org/apache/commons/io/package-info.java2
-rw-r--r--src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java52
36 files changed, 739 insertions, 217 deletions
diff --git a/src/main/java/org/apache/commons/io/ByteOrderMark.java b/src/main/java/org/apache/commons/io/ByteOrderMark.java
index 2e4f0305..c5ab57b1 100644
--- a/src/main/java/org/apache/commons/io/ByteOrderMark.java
+++ b/src/main/java/org/apache/commons/io/ByteOrderMark.java
@@ -115,7 +115,14 @@ public class ByteOrderMark implements Serializable {
*/
public static final char UTF_BOM = '\uFEFF';
+ /**
+ * Charset name.
+ */
private final String charsetName;
+
+ /**
+ * Bytes.
+ */
private final int[] bytes;
/**
diff --git a/src/main/java/org/apache/commons/io/CopyUtils.java b/src/main/java/org/apache/commons/io/CopyUtils.java
index b7e7829e..da01a987 100644
--- a/src/main/java/org/apache/commons/io/CopyUtils.java
+++ b/src/main/java/org/apache/commons/io/CopyUtils.java
@@ -103,7 +103,7 @@ import java.nio.charset.Charset;
* method variants to specify the encoding, each row may
* correspond to up to 2 methods.
* <p>
- * Origin of code: Excalibur.
+ * Provenance: Excalibur.
*
* @deprecated Use IOUtils. Will be removed in 3.0.
* Methods renamed to IOUtils.write() or IOUtils.copy().
diff --git a/src/main/java/org/apache/commons/io/EndianUtils.java b/src/main/java/org/apache/commons/io/EndianUtils.java
index acc95319..83c2ce25 100644
--- a/src/main/java/org/apache/commons/io/EndianUtils.java
+++ b/src/main/java/org/apache/commons/io/EndianUtils.java
@@ -34,7 +34,7 @@ import java.io.OutputStream;
* This class helps you solve this incompatibility.
* </p>
* <p>
- * Origin of code: Excalibur
+ * Provenance: Excalibur
* </p>
*
* @see org.apache.commons.io.input.SwappedDataInputStream
diff --git a/src/main/java/org/apache/commons/io/FileUtils.java b/src/main/java/org/apache/commons/io/FileUtils.java
index 807dc37c..80d100f1 100644
--- a/src/main/java/org/apache/commons/io/FileUtils.java
+++ b/src/main/java/org/apache/commons/io/FileUtils.java
@@ -36,6 +36,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.CopyOption;
+import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
@@ -108,7 +109,7 @@ import org.apache.commons.io.function.Uncheck;
* {@link SecurityException} are not documented in the Javadoc.
* </p>
* <p>
- * Origin of code: Excalibur, Alexandria, Commons-Utils
+ * Provenance: Excalibur, Alexandria, Commons-Utils
* </p>
*/
public class FileUtils {
@@ -352,16 +353,13 @@ public class FileUtils {
* This method checks to see if the two files are different lengths or if they point to the same file, before
* resorting to byte-by-byte comparison of the contents.
* </p>
- * <p>
- * Code origin: Avalon
- * </p>
*
* @param file1 the first file
* @param file2 the second file
* @return true if the content of the files are equal or they both don't exist, false otherwise
* @throws IllegalArgumentException when an input is not a file.
* @throws IOException If an I/O error occurs.
- * @see org.apache.commons.io.file.PathUtils#fileContentEquals(Path,Path,java.nio.file.LinkOption[],java.nio.file.OpenOption...)
+ * @see PathUtils#fileContentEquals(Path,Path)
*/
public static boolean contentEquals(final File file1, final File file2) throws IOException {
if (file1 == null && file2 == null) {
@@ -393,9 +391,7 @@ public class FileUtils {
return true;
}
- try (InputStream input1 = Files.newInputStream(file1.toPath()); InputStream input2 = Files.newInputStream(file2.toPath())) {
- return IOUtils.contentEquals(input1, input2);
- }
+ return PathUtils.fileContentEquals(file1.toPath(), file2.toPath());
}
/**
@@ -451,12 +447,12 @@ public class FileUtils {
}
/**
- * Converts a Collection containing java.io.File instances into array
+ * Converts a Collection containing {@link File} instances into array
* representation. This is to account for the difference between
* File.listFiles() and FileUtils.listFiles().
*
- * @param files a Collection containing java.io.File instances
- * @return an array of java.io.File
+ * @param files a Collection containing {@link File} instances
+ * @return an array of {@link File}
*/
public static File[] convertFileCollectionToFileArray(final Collection<File> files) {
return files.toArray(EMPTY_FILE_ARRAY);
@@ -1449,7 +1445,7 @@ public class FileUtils {
/**
* Returns a {@link File} representing the system temporary directory.
*
- * @return the system temporary directory.
+ * @return the system temporary directory as a File
* @since 2.0
*/
public static File getTempDirectory() {
@@ -1459,7 +1455,12 @@ public class FileUtils {
/**
* Returns the path to the system temporary directory.
*
- * @return the path to the system temporary directory.
+ * WARNING: this method relies on the Java system property 'java.io.tmpdir'
+ * which may or may not have a trailing file separator.
+ * This can affect code that uses String processing to manipulate pathnames rather
+ * than the standard libary methods in classes such as {@link java.io.File}
+ *
+ * @return the path to the system temporary directory as a String
* @since 2.0
*/
public static String getTempDirectoryPath() {
@@ -1971,7 +1972,7 @@ public class FileUtils {
* @param dirFilter optional filter to apply when finding subdirectories.
* If this parameter is {@code null}, subdirectories will not be included in the
* search. Use TrueFileFilter.INSTANCE to match all directories.
- * @return an iterator of java.io.File for the matching files
+ * @return an iterator of {@link File} for the matching files
* @see org.apache.commons.io.filefilter.FileFilterUtils
* @see org.apache.commons.io.filefilter.NameFileFilter
* @since 1.2
@@ -1988,14 +1989,14 @@ public class FileUtils {
* </p>
*
* @param directory the directory to search in
- * @param extensions an array of extensions, ex. {"java","xml"}. If this
+ * @param extensions an array of extensions, for example, {"java","xml"}. If this
* parameter is {@code null}, all files are returned.
* @param recursive if true all subdirectories are searched as well
- * @return an iterator of java.io.File with the matching files
+ * @return an iterator of {@link File} with the matching files
* @since 1.2
*/
public static Iterator<File> iterateFiles(final File directory, final String[] extensions, final boolean recursive) {
- return Uncheck.apply(d -> streamFiles(d, recursive, extensions).iterator(), directory);
+ return StreamIterator.iterator(Uncheck.get(() -> streamFiles(directory, recursive, extensions)));
}
/**
@@ -2016,7 +2017,7 @@ public class FileUtils {
* @param dirFilter optional filter to apply when finding subdirectories.
* If this parameter is {@code null}, subdirectories will not be included in the
* search. Use TrueFileFilter.INSTANCE to match all directories.
- * @return an iterator of java.io.File for the matching files
+ * @return an iterator of {@link File} for the matching files
* @see org.apache.commons.io.filefilter.FileFilterUtils
* @see org.apache.commons.io.filefilter.NameFileFilter
* @since 2.2
@@ -2216,28 +2217,30 @@ public class FileUtils {
* @param dirFilter optional filter to apply when finding subdirectories.
* If this parameter is {@code null}, subdirectories will not be included in the
* search. Use {@link TrueFileFilter#INSTANCE} to match all directories.
- * @return a collection of java.io.File with the matching files
+ * @return a collection of {@link File} with the matching files
* @see org.apache.commons.io.filefilter.FileFilterUtils
* @see org.apache.commons.io.filefilter.NameFileFilter
*/
public static Collection<File> listFiles(final File directory, final IOFileFilter fileFilter, final IOFileFilter dirFilter) {
final AccumulatorPathVisitor visitor = Uncheck
.apply(d -> listAccumulate(d, FileFileFilter.INSTANCE.and(fileFilter), dirFilter, FileVisitOption.FOLLOW_LINKS), directory);
- return visitor.getFileList().stream().map(Path::toFile).collect(Collectors.toList());
+ return toList(visitor.getFileList().stream().map(Path::toFile));
}
/**
- * Finds files within a given directory (and optionally its subdirectories)
+ * Lists files within a given directory (and optionally its subdirectories)
* which match an array of extensions.
*
* @param directory the directory to search in
- * @param extensions an array of extensions, ex. {"java","xml"}. If this
+ * @param extensions an array of extensions, for example, {"java","xml"}. If this
* parameter is {@code null}, all files are returned.
* @param recursive if true all subdirectories are searched as well
- * @return a collection of java.io.File with the matching files
+ * @return a collection of {@link File} with the matching files
*/
public static Collection<File> listFiles(final File directory, final String[] extensions, final boolean recursive) {
- return Uncheck.apply(d -> toList(streamFiles(d, recursive, extensions)), directory);
+ try (Stream<File> fileStream = Uncheck.get(() -> streamFiles(directory, recursive, extensions))) {
+ return toList(fileStream);
+ }
}
/**
@@ -2253,7 +2256,7 @@ public class FileUtils {
* @param dirFilter optional filter to apply when finding subdirectories.
* If this parameter is {@code null}, subdirectories will not be included in the
* search. Use TrueFileFilter.INSTANCE to match all directories.
- * @return a collection of java.io.File with the matching files
+ * @return a collection of {@link File} with the matching files
* @see org.apache.commons.io.FileUtils#listFiles
* @see org.apache.commons.io.filefilter.FileFilterUtils
* @see org.apache.commons.io.filefilter.NameFileFilter
@@ -2264,7 +2267,7 @@ public class FileUtils {
directory);
final List<Path> list = visitor.getFileList();
list.addAll(visitor.getDirList());
- return list.stream().map(Path::toFile).collect(Collectors.toList());
+ return toList(list.stream().map(Path::toFile));
}
/**
@@ -2570,9 +2573,8 @@ public class FileUtils {
* @param file the file to read, must not be {@code null}
* @return the file contents, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @since 1.1
*/
public static byte[] readFileToByteArray(final File file) throws IOException {
@@ -2587,9 +2589,8 @@ public class FileUtils {
* @param file the file to read, must not be {@code null}
* @return the file contents, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @since 1.3.1
* @deprecated 2.5 use {@link #readFileToString(File, Charset)} instead (and specify the appropriate encoding)
*/
@@ -2606,9 +2607,8 @@ public class FileUtils {
* @param charsetName the name of the requested charset, {@code null} means platform default
* @return the file contents, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @since 2.3
*/
public static String readFileToString(final File file, final Charset charsetName) throws IOException {
@@ -2622,9 +2622,8 @@ public class FileUtils {
* @param charsetName the name of the requested charset, {@code null} means platform default
* @return the file contents, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io
* .UnsupportedEncodingException} in version 2.2 if the named charset is unavailable.
* @since 2.3
@@ -2640,9 +2639,8 @@ public class FileUtils {
* @param file the file to read, must not be {@code null}
* @return the list of Strings representing each line in the file, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @since 1.3
* @deprecated 2.5 use {@link #readLines(File, Charset)} instead (and specify the appropriate encoding)
*/
@@ -2659,9 +2657,8 @@ public class FileUtils {
* @param charset the charset to use, {@code null} means platform default
* @return the list of Strings representing each line in the file, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @since 2.3
*/
public static List<String> readLines(final File file, final Charset charset) throws IOException {
@@ -2675,9 +2672,8 @@ public class FileUtils {
* @param charsetName the name of the requested charset, {@code null} means platform default
* @return the list of Strings representing each line in the file, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io
* .UnsupportedEncodingException} in version 2.2 if the named charset is unavailable.
* @since 1.1
@@ -2861,9 +2857,8 @@ public class FileUtils {
* {@code false} otherwise
* @throws NullPointerException if sourceFile is {@code null}.
* @throws NullPointerException if targetFile is {@code null}.
- * @throws IOException if setting the last-modified time failed.
*/
- private static boolean setTimes(final File sourceFile, final File targetFile) throws IOException {
+ private static boolean setTimes(final File sourceFile, final File targetFile) {
Objects.requireNonNull(sourceFile, "sourceFile");
Objects.requireNonNull(targetFile, "targetFile");
try {
@@ -2967,14 +2962,17 @@ public class FileUtils {
}
/**
- * Streams over the files in a given directory (and optionally
- * its subdirectories) which match an array of extensions.
+ * Streams over the files in a given directory (and optionally its subdirectories) which match an array of extensions.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a
+ * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
* @param directory the directory to search in
* @param recursive if true all subdirectories are searched as well
- * @param extensions an array of extensions, ex. {"java","xml"}. If this
- * parameter is {@code null}, all files are returned.
- * @return an iterator of java.io.File with the matching files
+ * @param extensions an array of extensions, for example, {"java","xml"}. If this parameter is {@code null}, all files are returned.
+ * @return a Stream of {@link File} for matching files.
* @throws IOException if an I/O error is thrown when accessing the starting file.
* @since 2.9.0
*/
@@ -3006,8 +3004,8 @@ public class FileUtils {
if (url == null || !"file".equalsIgnoreCase(url.getProtocol())) {
return null;
}
- final String filename = url.getFile().replace('/', File.separatorChar);
- return new File(decodeUrl(filename));
+ final String fileName = url.getFile().replace('/', File.separatorChar);
+ return new File(decodeUrl(fileName));
}
/**
@@ -3048,6 +3046,15 @@ public class FileUtils {
return files;
}
+ /**
+ * Consumes all of the given stream.
+ * <p>
+ * When called from a FileTreeWalker, the walker <em>closes</em> the stream because {@link FileTreeWalker#next()} calls {@code top.stream().close()}.
+ * </p>
+ *
+ * @param stream The stream to consume.
+ * @return a new List.
+ */
private static List<File> toList(final Stream<File> stream) {
return stream.collect(Collectors.toList());
}
diff --git a/src/main/java/org/apache/commons/io/FilenameUtils.java b/src/main/java/org/apache/commons/io/FilenameUtils.java
index 09c62f71..049c3a71 100644
--- a/src/main/java/org/apache/commons/io/FilenameUtils.java
+++ b/src/main/java/org/apache/commons/io/FilenameUtils.java
@@ -90,7 +90,7 @@ import java.util.stream.Stream;
* currently running on.
* </p>
* <p>
- * Origin of code: Excalibur, Alexandria, Tomcat, Commons-Utils.
+ * Provenance: Excalibur, Alexandria, Tomcat, Commons-Utils.
* </p>
*
* @since 1.1
@@ -846,7 +846,7 @@ public class FilenameUtils {
* ~user --&gt; 6 --&gt; named user (slash added)
* //server/a/b/c.txt --&gt; 9
* ///a/b/c.txt --&gt; -1 --&gt; error
- * C: --&gt; 0 --&gt; valid filename as only null character and / are reserved characters
+ * C: --&gt; 0 --&gt; valid file name as only null character and / are reserved characters
* </pre>
* <p>
* The output will be the same irrespective of the machine that the code is running on.
diff --git a/src/main/java/org/apache/commons/io/HexDump.java b/src/main/java/org/apache/commons/io/HexDump.java
index d7e5abdc..0a53e3d6 100644
--- a/src/main/java/org/apache/commons/io/HexDump.java
+++ b/src/main/java/org/apache/commons/io/HexDump.java
@@ -31,7 +31,7 @@ import org.apache.commons.io.output.CloseShieldOutputStream;
* in hexadecimal form.
* </p>
* <p>
- * Origin of code: POI.
+ * Provenance: POI.
* </p>
*/
public class HexDump {
diff --git a/src/main/java/org/apache/commons/io/IOIndexedException.java b/src/main/java/org/apache/commons/io/IOIndexedException.java
index 9a85328e..1893509f 100644
--- a/src/main/java/org/apache/commons/io/IOIndexedException.java
+++ b/src/main/java/org/apache/commons/io/IOIndexedException.java
@@ -42,6 +42,9 @@ public class IOIndexedException extends IOException {
return String.format("%s #%,d: %s", name, index, msg);
}
+ /**
+ * Index.
+ */
private final int index;
/**
diff --git a/src/main/java/org/apache/commons/io/IOUtils.java b/src/main/java/org/apache/commons/io/IOUtils.java
index b6b6f137..dfb4c19e 100644
--- a/src/main/java/org/apache/commons/io/IOUtils.java
+++ b/src/main/java/org/apache/commons/io/IOUtils.java
@@ -45,6 +45,7 @@ import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.Selector;
import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Collection;
@@ -118,7 +119,7 @@ import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
* closing streams after use.
* </p>
* <p>
- * Origin of code: Excalibur.
+ * Provenance: Excalibur.
* </p>
*/
public class IOUtils {
@@ -893,7 +894,6 @@ public class IOUtils {
* @param input2 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
*/
public static boolean contentEquals(final InputStream input1, final InputStream input2) throws IOException {
@@ -3827,28 +3827,36 @@ public class IOUtils {
* Writes the {@link #toString()} value of each item in a collection to
* an {@link OutputStream} line by line, using the specified character
* encoding and the specified line ending.
+ * <p>
+ * UTF-16 is written big-endian with no byte order mark.
+ * For little endian, use UTF-16LE. For a BOM, write it to the stream
+ * before calling this method.
+ * </p>
*
* @param lines the lines to write, null entries produce blank lines
* @param lineEnding the line separator to use, null is system default
* @param output the {@link OutputStream} to write to, not null, not closed
* @param charset the charset to use, null means platform default
- * @throws NullPointerException if the output is null
+ * @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static void writeLines(final Collection<?> lines, String lineEnding, final OutputStream output,
- final Charset charset) throws IOException {
+ Charset charset) throws IOException {
if (lines == null) {
return;
}
if (lineEnding == null) {
lineEnding = System.lineSeparator();
}
- final Charset cs = Charsets.toCharset(charset);
- final byte[] eolBytes = lineEnding.getBytes(cs);
+ if (StandardCharsets.UTF_16.equals(charset)) {
+ // don't write a BOM
+ charset = StandardCharsets.UTF_16BE;
+ }
+ final byte[] eolBytes = lineEnding.getBytes(charset);
for (final Object line : lines) {
if (line != null) {
- write(line.toString(), output, cs);
+ write(line.toString(), output, charset);
}
output.write(eolBytes);
}
diff --git a/src/main/java/org/apache/commons/io/RandomAccessFileMode.java b/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
index 54061588..8b51e439 100644
--- a/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
+++ b/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
@@ -20,6 +20,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.nio.file.Path;
+import java.util.Objects;
/**
* Access modes and factory methods for {@link RandomAccessFile}.
@@ -77,7 +78,7 @@ public enum RandomAccessFileMode {
* @throws FileNotFoundException See {@link RandomAccessFile#RandomAccessFile(File, String)}.
*/
public RandomAccessFile create(final Path file) throws FileNotFoundException {
- return create(file.toFile());
+ return create(Objects.requireNonNull(file.toFile(), "file"));
}
/**
diff --git a/src/main/java/org/apache/commons/io/RandomAccessFiles.java b/src/main/java/org/apache/commons/io/RandomAccessFiles.java
index 2fc071fc..0e0140b6 100644
--- a/src/main/java/org/apache/commons/io/RandomAccessFiles.java
+++ b/src/main/java/org/apache/commons/io/RandomAccessFiles.java
@@ -19,15 +19,55 @@ package org.apache.commons.io;
import java.io.IOException;
import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.util.Objects;
+
+import org.apache.commons.io.channels.FileChannels;
/**
- * Works on RandomAccessFile.
+ * Works with {@link RandomAccessFile}.
*
* @since 2.13.0
*/
public class RandomAccessFiles {
/**
+ * Tests if two RandomAccessFile contents are equal.
+ *
+ * @param raf1 A RandomAccessFile.
+ * @param raf2 Another RandomAccessFile.
+ * @return true if the contents of both RandomAccessFiles are equal, false otherwise.
+ * @throws IOException if an I/O error occurs.
+ * @since 2.15.0
+ */
+ @SuppressWarnings("resource") // See comments
+ public static boolean contentEquals(final RandomAccessFile raf1, final RandomAccessFile raf2) throws IOException {
+ // Short-circuit test
+ if (Objects.equals(raf1, raf2)) {
+ return true;
+ }
+ // Short-circuit test
+ final long length1 = length(raf1);
+ final long length2 = length(raf2);
+ if (length1 != length2) {
+ return false;
+ }
+ if (length1 == 0 && length2 == 0) {
+ return true;
+ }
+ // Dig in and to the work
+ // We do not close FileChannels because that closes the owning RandomAccessFile.
+ // Instead, the caller is assumed to manage the given RandomAccessFile objects.
+ final FileChannel channel1 = raf1.getChannel();
+ final FileChannel channel2 = raf2.getChannel();
+ return FileChannels.contentEquals(channel1, channel2, IOUtils.DEFAULT_BUFFER_SIZE);
+ }
+
+ private static long length(final RandomAccessFile raf) throws IOException {
+ return raf != null ? raf.length() : 0;
+ }
+
+ /**
* Reads a byte array starting at "position" for "length" bytes.
*
* @param input The source RandomAccessFile.
@@ -42,4 +82,17 @@ public class RandomAccessFiles {
return IOUtils.toByteArray(input::read, length);
}
+ /**
+ * Resets the given file to position 0.
+ *
+ * @param raf The RandomAccessFile to reset.
+ * @return The given RandomAccessFile.
+ * @throws IOException If {@code pos} is less than {@code 0} or if an I/O error occurs.
+ * @since 2.15.0
+ */
+ public static RandomAccessFile reset(final RandomAccessFile raf) throws IOException {
+ raf.seek(0);
+ return raf;
+ }
+
}
diff --git a/src/main/java/org/apache/commons/io/StreamIterator.java b/src/main/java/org/apache/commons/io/StreamIterator.java
index 3a321681..23465657 100644
--- a/src/main/java/org/apache/commons/io/StreamIterator.java
+++ b/src/main/java/org/apache/commons/io/StreamIterator.java
@@ -17,42 +17,55 @@
package org.apache.commons.io;
-import java.io.Closeable;
import java.util.Iterator;
import java.util.Objects;
import java.util.stream.Stream;
/**
- * Wraps and presents a stream as a closable iterator resource that automatically closes itself when reaching the end
- * of stream.
+ * Wraps and presents a {@link Stream} as a {@link AutoCloseable} {@link Iterator} resource that automatically closes itself when reaching the end of stream.
*
- * @param <E> The stream and iterator type.
- * @since 2.9.0
+ * <h2>Warning</h2>
+ * <p>
+ * In order to close the stream, the call site MUST either close the stream it allocated OR call this iterator until the end.
+ * </p>
+ *
+ * @param <E> The {@link Stream} and {@link Iterator} type.
+ * @since 2.15.0
*/
-final class StreamIterator<E> implements Iterator<E>, Closeable {
+public final class StreamIterator<E> implements Iterator<E>, AutoCloseable {
/**
- * Wraps and presents a stream as a closable resource that automatically closes itself when reaching the end of
- * stream.
- * <h2>Warning</h2>
+ * Wraps and presents a stream as a closable resource that automatically closes itself when reaching the end of stream.
+ * <p>
+ * <b>Warning</b>
+ * </p>
* <p>
- * In order to close the stream, the call site MUST either close the stream it allocated OR call the iterator until
- * the end.
+ * In order to close the stream, the call site MUST either close the stream it allocated OR call this iterator until the end.
* </p>
*
- * @param <T> The stream and iterator type.
+ * @param <T> The stream and iterator type.
* @param stream The stream iterate.
* @return A new iterator.
*/
- @SuppressWarnings("resource") // Caller MUST close or iterate to the end.
- public static <T> Iterator<T> iterator(final Stream<T> stream) {
- return new StreamIterator<>(stream).iterator;
+ public static <T> StreamIterator<T> iterator(final Stream<T> stream) {
+ return new StreamIterator<>(stream);
}
+ /**
+ * The given stream's Iterator.
+ */
private final Iterator<E> iterator;
+ /**
+ * The given stream.
+ */
private final Stream<E> stream;
+ /**
+ * Whether {@link #close()} has been called.
+ */
+ private boolean closed;
+
private StreamIterator(final Stream<E> stream) {
this.stream = Objects.requireNonNull(stream, "stream");
this.iterator = stream.iterator();
@@ -63,11 +76,16 @@ final class StreamIterator<E> implements Iterator<E>, Closeable {
*/
@Override
public void close() {
+ closed = true;
stream.close();
}
@Override
public boolean hasNext() {
+ if (closed) {
+ // Calling Iterator#hasNext() on a closed java.nio.file.FileTreeIterator causes an IllegalStateException.
+ return false;
+ }
final boolean hasNext = iterator.hasNext();
if (!hasNext) {
close();
diff --git a/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java b/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
index d94638ac..e0f9ba66 100644
--- a/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
+++ b/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
@@ -154,6 +154,11 @@ public abstract class AbstractStreamBuilder<T, B extends AbstractStreamBuilder<T
return checkOrigin().getInputStream(getOpenOptions());
}
+ /**
+ * Gets the OpenOption.
+ *
+ * @return the OpenOption.
+ */
protected OpenOption[] getOpenOptions() {
return openOptions;
}
diff --git a/src/main/java/org/apache/commons/io/channels/FileChannels.java b/src/main/java/org/apache/commons/io/channels/FileChannels.java
new file mode 100644
index 00000000..468c85b4
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FileChannels.java
@@ -0,0 +1,87 @@
+/*
+ * 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.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.Objects;
+
+import org.apache.commons.io.IOUtils;
+
+/**
+ * Works with {@link FileChannel}.
+ *
+ * @since 2.15.0
+ */
+public final class FileChannels {
+
+ /**
+ * Tests if two RandomAccessFiles contents are equal.
+ *
+ * @param channel1 A FileChannel.
+ * @param channel2 Another FileChannel.
+ * @param byteBufferSize The two internal buffer capacities, in bytes.
+ * @return true if the contents of both RandomAccessFiles are equal, false otherwise.
+ * @throws IOException if an I/O error occurs.
+ */
+ public static boolean contentEquals(final FileChannel channel1, final FileChannel channel2, final int byteBufferSize) throws IOException {
+ // Short-circuit test
+ if (Objects.equals(channel1, channel2)) {
+ return true;
+ }
+ // Short-circuit test
+ final long size1 = size(channel1);
+ final long size2 = size(channel2);
+ if (size1 != size2) {
+ return false;
+ }
+ if (size1 == 0 && size2 == 0) {
+ return true;
+ }
+ // Dig in and do the work
+ final ByteBuffer byteBuffer1 = ByteBuffer.allocateDirect(byteBufferSize);
+ final ByteBuffer byteBuffer2 = ByteBuffer.allocateDirect(byteBufferSize);
+ while (true) {
+ final int read1 = channel1.read(byteBuffer1);
+ final int read2 = channel2.read(byteBuffer2);
+ if (read1 == IOUtils.EOF && read2 == IOUtils.EOF) {
+ return byteBuffer1.equals(byteBuffer2);
+ }
+ if (read1 != read2) {
+ return false;
+ }
+ if (!byteBuffer1.equals(byteBuffer2)) {
+ return false;
+ }
+ byteBuffer1.clear();
+ byteBuffer2.clear();
+ }
+ }
+
+ private static long size(final FileChannel channel) throws IOException {
+ return channel != null ? channel.size() : 0;
+ }
+
+ /**
+ * Don't instantiate.
+ */
+ private FileChannels() {
+ // no-op
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/channels/package-info.java b/src/main/java/org/apache/commons/io/channels/package-info.java
new file mode 100644
index 00000000..51a7ca28
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Provides classes to work with {@link java.nio.channels}.
+ *
+ * @since 2.15.0
+ */
+package org.apache.commons.io.channels;
diff --git a/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java b/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
index 0f57a833..d50f3252 100644
--- a/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
@@ -19,6 +19,7 @@ package org.apache.commons.io.comparator;
import java.io.File;
import java.io.Serializable;
import java.util.Comparator;
+import java.util.function.IntFunction;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@@ -48,6 +49,9 @@ public class CompositeFileComparator extends AbstractFileComparator implements S
private static final Comparator<?>[] EMPTY_COMPARATOR_ARRAY = {};
private static final long serialVersionUID = -2224170307287243428L;
+ /**
+ * Delegates.
+ */
private final Comparator<File>[] delegates;
/**
@@ -65,7 +69,8 @@ public class CompositeFileComparator extends AbstractFileComparator implements S
* @param delegates The delegate file comparators
*/
public CompositeFileComparator(final Iterable<Comparator<File>> delegates) {
- this.delegates = delegates == null ? emptyArray() : StreamSupport.stream(delegates.spliterator(), false).toArray(Comparator[]::new);
+ this.delegates = delegates == null ? emptyArray()
+ : StreamSupport.stream(delegates.spliterator(), false).toArray((IntFunction<Comparator<File>[]>) Comparator[]::new);
}
/**
diff --git a/src/main/java/org/apache/commons/io/file/FilesUncheck.java b/src/main/java/org/apache/commons/io/file/FilesUncheck.java
index 02a1febb..02688cac 100644
--- a/src/main/java/org/apache/commons/io/file/FilesUncheck.java
+++ b/src/main/java/org/apache/commons/io/file/FilesUncheck.java
@@ -22,6 +22,7 @@ import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.Reader;
import java.io.UncheckedIOException;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.Charset;
@@ -244,6 +245,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#find(Path, int, BiPredicate, FileVisitOption...)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link DirectoryStream}. When you require timely disposal of file system resources, use a {@code try}-with-resources
+ * block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed.
+ * </p>
*
* @param start See delegate.
* @param maxDepth See delegate.
@@ -348,6 +353,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#lines(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link Reader}. When you require timely disposal of file system resources, use a {@code try}-with-resources block to
+ * ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed.
+ * </p>
*
* @param path See delegate.
* @return See delegate.
@@ -359,6 +368,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#lines(Path, Charset)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link Reader}. When you require timely disposal of file system resources, use a {@code try}-with-resources block to
+ * ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed.
+ * </p>
*
* @param path See delegate.
* @param cs See delegate.
@@ -371,6 +384,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#list(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link DirectoryStream}. When you require timely disposal of file system resources, use a {@code try}-with-resources
+ * block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed.
+ * </p>
*
* @param dir See delegate.
* @return See delegate.
@@ -474,8 +491,11 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#newDirectoryStream(Path)} throwing {@link UncheckedIOException} instead of
- * {@link IOException}.
+ * Delegates to {@link Files#newDirectoryStream(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * If you don't use the try-with-resources construct, then you must call the stream's {@link Stream#close()} method after iteration is complete to free any
+ * resources held for the open directory.
+ * </p>
*
* @param dir See delegate.
* @return See delegate.
@@ -485,10 +505,14 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#newDirectoryStream(Path, java.nio.file.DirectoryStream.Filter)} throwing
- * {@link UncheckedIOException} instead of {@link IOException}.
+ * Delegates to {@link Files#newDirectoryStream(Path, java.nio.file.DirectoryStream.Filter)} throwing {@link UncheckedIOException} instead of
+ * {@link IOException}.
+ * <p>
+ * If you don't use the try-with-resources construct, then you must call the stream's {@link Stream#close()} method after iteration is complete to free any
+ * resources held for the open directory.
+ * </p>
*
- * @param dir See delegate.
+ * @param dir See delegate.
* @param filter See delegate.
* @return See delegate.
*/
@@ -499,6 +523,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#newDirectoryStream(Path, String)} throwing {@link UncheckedIOException} instead of
* {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link DirectoryStream}. When you require timely disposal of file system resources, use a {@code try}-with-resources
+ * block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed.
+ * </p>
*
* @param dir See delegate.
* @param glob See delegate.
@@ -674,10 +702,14 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#walk(Path, FileVisitOption...)} throwing {@link UncheckedIOException} instead of
- * {@link IOException}.
+ * Delegates to {@link Files#walk(Path, FileVisitOption...)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a
+ * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
- * @param start See delegate.
+ * @param start See delegate.
* @param options See delegate.
* @return See delegate.
*/
@@ -686,12 +718,16 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#walk(Path, int, FileVisitOption...)} throwing {@link UncheckedIOException} instead of
- * {@link IOException}.
+ * Delegates to {@link Files#walk(Path, int, FileVisitOption...)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a
+ * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
- * @param start See delegate.
+ * @param start See delegate.
* @param maxDepth See delegate.
- * @param options See delegate.
+ * @param options See delegate.
* @return See delegate.
*/
public static Stream<Path> walk(final Path start, final int maxDepth, final FileVisitOption... options) {
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 56b2a05c..d85fdb67 100644
--- a/src/main/java/org/apache/commons/io/file/PathUtils.java
+++ b/src/main/java/org/apache/commons/io/file/PathUtils.java
@@ -21,7 +21,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.UncheckedIOException;
+import java.io.RandomAccessFile;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
@@ -70,14 +70,14 @@ import java.util.stream.Stream;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.RandomAccessFileMode;
+import org.apache.commons.io.RandomAccessFiles;
import org.apache.commons.io.ThreadUtils;
import org.apache.commons.io.file.Counters.PathCounters;
import org.apache.commons.io.file.attribute.FileTimes;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.function.IOFunction;
import org.apache.commons.io.function.IOSupplier;
-import org.apache.commons.io.function.Uncheck;
/**
* NIO Path utilities.
@@ -90,7 +90,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 {
+ private static final class RelativeSortedPaths {
final boolean equals;
// final List<Path> relativeDirList1; // might need later?
@@ -365,7 +365,7 @@ public final class PathUtils {
* Creates the parent directories for the given {@code path}.
* <p>
* If the parent directory already exists, then return it.
- * <p>
+ * </p>
*
* @param path The path to a file (or directory).
* @param attrs An optional list of file attributes to set atomically when creating the directories.
@@ -381,7 +381,7 @@ public final class PathUtils {
* Creates the parent directories for the given {@code path}.
* <p>
* If the parent directory already exists, then return it.
- * <p>
+ * </p>
*
* @param path The path to a file (or directory).
* @param linkOption A {@link LinkOption} or null.
@@ -719,20 +719,20 @@ public final class PathUtils {
/**
* Compares the file contents of two Paths to determine if they are equal or not.
* <p>
- * File content is accessed through {@link Files#newInputStream(Path,OpenOption...)}.
+ * File content is accessed through {@link RandomAccessFileMode#create(Path)}.
* </p>
*
* @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.
+ * @param openOptions ignored.
* @return true if the content of the streams are equal or they both don't exist, false otherwise.
* @throws NullPointerException if openOptions 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 {
+ throws IOException {
if (path1 == null && path2 == null) {
return true;
}
@@ -766,9 +766,9 @@ public final class PathUtils {
// same file
return true;
}
- try (InputStream inputStream1 = Files.newInputStream(nPath1, openOptions);
- InputStream inputStream2 = Files.newInputStream(nPath2, openOptions)) {
- return IOUtils.contentEquals(inputStream1, inputStream2);
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(path1.toRealPath(linkOptions));
+ RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(path2.toRealPath(linkOptions))) {
+ return RandomAccessFiles.contentEquals(raf1, raf2);
}
}
@@ -1182,8 +1182,12 @@ public final class PathUtils {
/**
* Creates a new DirectoryStream for Paths rooted at the given directory.
+ * <p>
+ * If you don't use the try-with-resources construct, then you must call the stream's {@link Stream#close()} method after iteration is complete to free any
+ * resources held for the open directory.
+ * </p>
*
- * @param dir the path to the directory to stream.
+ * @param dir the path to the directory to stream.
* @param pathFilter the directory stream filter.
* @return a new instance.
* @throws IOException if an I/O error occurs.
@@ -1243,21 +1247,20 @@ public final class PathUtils {
}
/**
- * Reads the BasicFileAttributes from the given path. Returns null instead of throwing
- * {@link UnsupportedOperationException}. Throws {@link Uncheck} instead of {@link IOException}.
+ * Reads the BasicFileAttributes from the given path. Returns null if the attributes can't be read.
*
* @param <A> The {@link BasicFileAttributes} type
* @param path The Path to test.
* @param type the {@link Class} of the file attributes required to read.
* @param options options indicating how to handle symbolic links.
- * @return the file attributes.
+ * @return the file attributes or null if the attributes can't be read.
* @see Files#readAttributes(Path, Class, LinkOption...)
* @since 2.12.0
*/
public static <A extends BasicFileAttributes> A readAttributes(final Path path, final Class<A> type, final LinkOption... options) {
try {
- return path == null ? null : Uncheck.apply(Files::readAttributes, path, type, options);
- } catch (final UnsupportedOperationException e) {
+ return path == null ? null : Files.readAttributes(path, type, options);
+ } catch (final UnsupportedOperationException | IOException e) {
// For example, on Windows.
return null;
}
@@ -1270,16 +1273,14 @@ public final class PathUtils {
* @return the path attributes.
* @throws IOException if an I/O error occurs.
* @since 2.9.0
- * @deprecated Will be removed in 3.0.0 in favor of {@link #readBasicFileAttributes(Path, LinkOption...)}.
*/
- @Deprecated
public static BasicFileAttributes readBasicFileAttributes(final Path path) throws IOException {
return Files.readAttributes(path, BasicFileAttributes.class);
}
/**
- * Reads the BasicFileAttributes from the given path. Returns null instead of throwing
- * {@link UnsupportedOperationException}.
+ * Reads the BasicFileAttributes from the given path. Returns null if the attributes
+ * can't be read.
*
* @param path the path to read.
* @param options options indicating how to handle symbolic links.
@@ -1291,12 +1292,11 @@ public final class PathUtils {
}
/**
- * Reads the BasicFileAttributes from the given path. Returns null instead of throwing
- * {@link UnsupportedOperationException}.
+ * Reads the BasicFileAttributes from the given path. Returns null if the attributes
+ * can't be read.
*
* @param path the path to read.
* @return the path attributes.
- * @throws UncheckedIOException if an I/O error occurs
* @since 2.9.0
* @deprecated Use {@link #readBasicFileAttributes(Path, LinkOption...)}.
*/
@@ -1306,8 +1306,8 @@ public final class PathUtils {
}
/**
- * Reads the DosFileAttributes from the given path. Returns null instead of throwing
- * {@link UnsupportedOperationException}.
+ * Reads the DosFileAttributes from the given path. Returns null if the attributes
+ * can't be read.
*
* @param path the path to read.
* @param options options indicating how to handle symbolic links.
@@ -1323,8 +1323,8 @@ public final class PathUtils {
}
/**
- * Reads the PosixFileAttributes or DosFileAttributes from the given path. Returns null instead of throwing
- * {@link UnsupportedOperationException}.
+ * Reads the PosixFileAttributes or DosFileAttributes from the given path. Returns null if the attributes
+ * can't be read.
*
* @param path The Path to read.
* @param options options indicating how to handle symbolic links.
@@ -1751,6 +1751,11 @@ public final class PathUtils {
/**
* Returns a stream of filtered paths.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a
+ * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
* @param start the start path
* @param pathFilter the path filter
@@ -1801,7 +1806,7 @@ public final class PathUtils {
}
/**
- * Does allow to instantiate.
+ * Prevents instantiation.
*/
private PathUtils() {
// do not instantiate.
diff --git a/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java
index 14c99566..ee2bb02b 100644
--- a/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java
@@ -39,7 +39,7 @@ public class DelegateFileFilter extends AbstractFileFilter implements Serializab
/** The File filter */
private final FileFilter fileFilter;
/** The Filename filter */
- private final FilenameFilter filenameFilter;
+ private final FilenameFilter fileNameFilter;
/**
* Constructs a delegate file filter around an existing FileFilter.
@@ -49,17 +49,17 @@ public class DelegateFileFilter extends AbstractFileFilter implements Serializab
public DelegateFileFilter(final FileFilter fileFilter) {
Objects.requireNonNull(fileFilter, "filter");
this.fileFilter = fileFilter;
- this.filenameFilter = null;
+ this.fileNameFilter = null;
}
/**
* Constructs a delegate file filter around an existing FilenameFilter.
*
- * @param filenameFilter the filter to decorate
+ * @param fileNameFilter the filter to decorate
*/
- public DelegateFileFilter(final FilenameFilter filenameFilter) {
- Objects.requireNonNull(filenameFilter, "filter");
- this.filenameFilter = filenameFilter;
+ public DelegateFileFilter(final FilenameFilter fileNameFilter) {
+ Objects.requireNonNull(fileNameFilter, "filter");
+ this.fileNameFilter = fileNameFilter;
this.fileFilter = null;
}
@@ -86,8 +86,8 @@ public class DelegateFileFilter extends AbstractFileFilter implements Serializab
*/
@Override
public boolean accept(final File dir, final String name) {
- if (filenameFilter != null) {
- return filenameFilter.accept(dir, name);
+ if (fileNameFilter != null) {
+ return fileNameFilter.accept(dir, name);
}
return super.accept(dir, name);
}
@@ -99,7 +99,7 @@ public class DelegateFileFilter extends AbstractFileFilter implements Serializab
*/
@Override
public String toString() {
- final String delegate = fileFilter != null ? fileFilter.toString() : filenameFilter.toString();
+ final String delegate = fileFilter != null ? fileFilter.toString() : fileNameFilter.toString();
return super.toString() + "(" + delegate + ")";
}
diff --git a/src/main/java/org/apache/commons/io/filefilter/package-info.java b/src/main/java/org/apache/commons/io/filefilter/package-info.java
index a374fb0d..3bf71238 100644
--- a/src/main/java/org/apache/commons/io/filefilter/package-info.java
+++ b/src/main/java/org/apache/commons/io/filefilter/package-info.java
@@ -40,7 +40,7 @@
* </tr>
* <tr>
* <td><a href="NameFileFilter.html">NameFileFilter</a></td>
- * <td>Filter based on a filename</td>
+ * <td>Filter based on a file name</td>
* </tr>
* <tr>
* <td><a href="WildcardFileFilter.html">WildcardFileFilter</a></td>
diff --git a/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java b/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
index fc334e96..72b1b1e8 100644
--- a/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
+++ b/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
@@ -38,7 +38,7 @@ class ByteBufferCleaner {
void clean(ByteBuffer buffer) throws ReflectiveOperationException;
}
- private static class Java8Cleaner implements Cleaner {
+ private static final class Java8Cleaner implements Cleaner {
private final Method cleanerMethod;
private final Method cleanMethod;
@@ -57,7 +57,7 @@ class ByteBufferCleaner {
}
}
- private static class Java9Cleaner implements Cleaner {
+ private static final class Java9Cleaner implements Cleaner {
private final Object theUnsafe;
private final Method invokeCleaner;
diff --git a/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java b/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
index 89114be9..3d03f8ce 100644
--- a/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
@@ -87,6 +87,9 @@ public final class MemoryMappedFileInputStream extends InputStream {
*/
public static class Builder extends AbstractStreamBuilder<MemoryMappedFileInputStream, Builder> {
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
setBufferSizeDefault(DEFAULT_BUFFER_SIZE);
setBufferSize(DEFAULT_BUFFER_SIZE);
diff --git a/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java b/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
index 7aed4185..97d7ff59 100644
--- a/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
@@ -21,12 +21,13 @@ import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
+import java.util.Objects;
import org.apache.commons.io.build.AbstractStreamBuilder;
/**
* This class is an example for using an {@link ObservableInputStream}. It creates its own {@link org.apache.commons.io.input.ObservableInputStream.Observer},
- * which calculates a checksum using a MessageDigest, for example an MD5 sum.
+ * which calculates a checksum using a {@link MessageDigest}, for example, a SHA-512 sum.
* <p>
* To build an instance, see {@link Builder}.
* </p>
@@ -35,12 +36,11 @@ import org.apache.commons.io.build.AbstractStreamBuilder;
* Cryptography Architecture Standard Algorithm Name Documentation</a> for information about standard algorithm names.
* </p>
* <p>
- * <em>Note</em>: Neither {@link ObservableInputStream}, nor {@link MessageDigest}, are thread safe. So is {@link MessageDigestCalculatingInputStream}.
- * </p>
- * <p>
- * TODO Rename to MessageDigestInputStream in 3.0.
+ * <em>Note</em>: Neither {@link ObservableInputStream}, nor {@link MessageDigest}, are thread safe, so is {@link MessageDigestCalculatingInputStream}.
* </p>
+ * @deprecated Use {@link MessageDigestInputStream}.
*/
+@Deprecated
public class MessageDigestCalculatingInputStream extends ObservableInputStream {
/**
@@ -61,6 +61,9 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
private MessageDigest messageDigest;
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
try {
this.messageDigest = getDefaultMessageDigest();
@@ -92,6 +95,9 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
/**
* Sets the message digest.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
*
* @param messageDigest the message digest.
*/
@@ -101,6 +107,9 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
/**
* Sets the name of the name of the message digest algorithm.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
*
* @param algorithm the name of the algorithm. See the MessageDigest section in the
* <a href= "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> Java Cryptography
@@ -123,9 +132,10 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
* Constructs an MessageDigestMaintainingObserver for the given MessageDigest.
*
* @param messageDigest the message digest to use
+ * @throws NullPointerException if messageDigest is null.
*/
public MessageDigestMaintainingObserver(final MessageDigest messageDigest) {
- this.messageDigest = messageDigest;
+ this.messageDigest = Objects.requireNonNull(messageDigest, "messageDigest");
}
@Override
@@ -187,9 +197,13 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
/**
* Constructs a new instance, which calculates a signature on the given stream, using the given {@link MessageDigest}.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
*
* @param inputStream the stream to calculate the message digest for
* @param messageDigest the message digest to use
+ * @throws NullPointerException if messageDigest is null.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
@@ -200,6 +214,9 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
/**
* Constructs a new instance, which calculates a signature on the given stream, using a {@link MessageDigest} with the given algorithm.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
*
* @param inputStream the stream to calculate the message digest for
* @param algorithm the name of the algorithm requested. See the MessageDigest section in the
diff --git a/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java b/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java
new file mode 100644
index 00000000..d822256b
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java
@@ -0,0 +1,193 @@
+/*
+ * 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.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
+
+import org.apache.commons.io.build.AbstractStreamBuilder;
+
+/**
+ * This class is an example for using an {@link ObservableInputStream}. It creates its own {@link org.apache.commons.io.input.ObservableInputStream.Observer},
+ * which calculates a checksum using a {@link MessageDigest}, for example, a SHA-512 sum.
+ * <p>
+ * To build an instance, see {@link Builder}.
+ * </p>
+ * <p>
+ * See the MessageDigest section in the <a href= "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> Java
+ * Cryptography Architecture Standard Algorithm Name Documentation</a> for information about standard algorithm names.
+ * </p>
+ * <p>
+ * You must specify a message digest algorithm name or instance.
+ * </p>
+ * <p>
+ * <em>Note</em>: Neither {@link ObservableInputStream}, nor {@link MessageDigest}, are thread safe, so is {@link MessageDigestInputStream}.
+ * </p>
+ *
+ * @since 2.15.0
+ */
+public final class MessageDigestInputStream extends ObservableInputStream {
+
+ /**
+ * Builds new {@link MessageDigestInputStream} instances.
+ * <p>
+ * For example:
+ * </p>
+ * <pre>{@code
+ * MessageDigestInputStream s = MessageDigestInputStream.builder()
+ * .setPath(path)
+ * .setMessageDigest("SHA-512")
+ * .get();}
+ * </pre>
+ * <p>
+ * You must specify a message digest algorithm name or instance.
+ * </p>
+ */
+ public static class Builder extends AbstractStreamBuilder<MessageDigestInputStream, Builder> {
+
+ private MessageDigest messageDigest;
+
+ /**
+ * Constructs a new Builder.
+ */
+ public Builder() {
+ // empty
+ }
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspects InputStream, OpenOption[], and MessageDigest.
+ * </p>
+ * <p>
+ * You must provide an origin that can be converted to an InputStream by this builder, otherwise, this call will throw an
+ * {@link UnsupportedOperationException}.
+ * </p>
+ *
+ * @return a new instance.
+ * @throws UnsupportedOperationException if the origin cannot provide an InputStream.
+ * @see #getInputStream()
+ */
+ @SuppressWarnings("resource")
+ @Override
+ public MessageDigestInputStream get() throws IOException {
+ return new MessageDigestInputStream(getInputStream(), messageDigest);
+ }
+
+ /**
+ * Sets the message digest.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
+ *
+ * @param messageDigest the message digest.
+ * @return this
+ */
+ public Builder setMessageDigest(final MessageDigest messageDigest) {
+ this.messageDigest = messageDigest;
+ return this;
+ }
+
+ /**
+ * Sets the name of the name of the message digest algorithm.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
+ *
+ * @param algorithm the name of the algorithm. See the MessageDigest section in the
+ * <a href= "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> Java Cryptography
+ * Architecture Standard Algorithm Name Documentation</a> for information about standard algorithm names.
+ * @return this
+ * @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation for the specified algorithm.
+ */
+ public Builder setMessageDigest(final String algorithm) throws NoSuchAlgorithmException {
+ this.messageDigest = MessageDigest.getInstance(algorithm);
+ return this;
+ }
+
+ }
+
+ /**
+ * Maintains the message digest.
+ */
+ public static class MessageDigestMaintainingObserver extends Observer {
+
+ private final MessageDigest messageDigest;
+
+ /**
+ * Constructs an MessageDigestMaintainingObserver for the given MessageDigest.
+ *
+ * @param messageDigest the message digest to use
+ * @throws NullPointerException if messageDigest is null.
+ */
+ public MessageDigestMaintainingObserver(final MessageDigest messageDigest) {
+ this.messageDigest = Objects.requireNonNull(messageDigest, "messageDigest");
+ }
+
+ @Override
+ public void data(final byte[] input, final int offset, final int length) throws IOException {
+ messageDigest.update(input, offset, length);
+ }
+
+ @Override
+ public void data(final int input) throws IOException {
+ messageDigest.update((byte) input);
+ }
+ }
+
+ /**
+ * Constructs a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ private final MessageDigest messageDigest;
+
+ /**
+ * Constructs a new instance, which calculates a signature on the given stream, using the given {@link MessageDigest}.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
+ *
+ * @param inputStream the stream to calculate the message digest for
+ * @param messageDigest the message digest to use
+ * @throws NullPointerException if messageDigest is null.
+ */
+ private MessageDigestInputStream(final InputStream inputStream, final MessageDigest messageDigest) {
+ super(inputStream, new MessageDigestMaintainingObserver(messageDigest));
+ this.messageDigest = messageDigest;
+ }
+
+ /**
+ * Gets the {@link MessageDigest}, which is being used for generating the checksum.
+ * <p>
+ * <em>Note</em>: The checksum will only reflect the data, which has been read so far. This is probably not, what you expect. Make sure, that the complete
+ * data has been read, if that is what you want. The easiest way to do so is by invoking {@link #consume()}.
+ * </p>
+ *
+ * @return the message digest used
+ */
+ public MessageDigest getMessageDigest() {
+ return messageDigest;
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/input/ObservableInputStream.java b/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
index ee080f06..a97702fb 100644
--- a/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
@@ -39,7 +39,7 @@ import org.apache.commons.io.function.IOConsumer;
* be used.
* </p>
*
- * @see MessageDigestCalculatingInputStream
+ * @see MessageDigestInputStream
*/
public class ObservableInputStream extends ProxyInputStream {
diff --git a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
index 04c9cf91..7ef620fe 100644
--- a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
+++ b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
@@ -66,6 +66,9 @@ public class ReversedLinesFileReader implements Closeable {
*/
public static class Builder extends AbstractStreamBuilder<ReversedLinesFileReader, Builder> {
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
setBufferSizeDefault(DEFAULT_BLOCK_SIZE);
setBufferSize(DEFAULT_BLOCK_SIZE);
diff --git a/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java b/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java
index 31600f58..9239b520 100644
--- a/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java
@@ -29,7 +29,7 @@ import org.apache.commons.io.EndianUtils;
* DataInput for systems relying on little endian data formats. When read, values will be changed from little endian to
* big endian formats for internal usage.
* <p>
- * <b>Origin of code: </b>Avalon Excalibur (IO)
+ * Provenance: Avalon Excalibur (IO)
* </p>
*/
public class SwappedDataInputStream extends ProxyInputStream implements DataInput {
diff --git a/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.java b/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.java
index ffd456df..b33a1187 100644
--- a/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.java
@@ -105,7 +105,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
protected volatile byte[] buffer;
/**
- * The total number of bytes inside the byte array {@code buf}.
+ * The total number of bytes inside the byte array {@code buffer}.
*/
protected int count;
@@ -120,7 +120,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
protected int markPos = IOUtils.EOF;
/**
- * The current position within the byte array {@code buf}.
+ * The current position within the byte array {@code buffer}.
*/
protected int pos;
@@ -190,8 +190,8 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
}
final byte[] newbuf = new byte[newLength];
System.arraycopy(localBuf, 0, newbuf, 0, localBuf.length);
- // Reassign buf, which will invalidate any local references
- // FIXME: what if buf was null?
+ // Reassign buffer, which will invalidate any local references
+ // FIXME: what if buffer was null?
localBuf = buffer = newbuf;
} else if (markPos > 0) {
System.arraycopy(localBuf, markPos, localBuf, 0, localBuf.length - markPos);
@@ -276,7 +276,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
* set and the requested number of bytes is larger than the receiver's buffer size, this implementation bypasses the buffer and simply places the results
* directly into {@code buffer}.
*
- * @param buffer the byte array in which to store the bytes read.
+ * @param dest the byte array in which to store the bytes read.
* @param offset the initial position in {@code buffer} to store the bytes read from this stream.
* @param length the maximum number of bytes to store in {@code buffer}.
* @return the number of bytes actually read or -1 if end of stream.
@@ -284,7 +284,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
* @throws IOException if the stream is already closed or another IOException occurs.
*/
@Override
- public int read(final byte[] buffer, int offset, final int length) throws IOException {
+ public int read(final byte[] dest, int offset, final int length) throws IOException {
// Use local ref since buf may be invalidated by an unsynchronized
// close()
byte[] localBuf = buffer;
@@ -292,7 +292,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
throw new IOException("Stream is closed");
}
// avoid int overflow
- if (offset > buffer.length - length || offset < 0 || length < 0) {
+ if (offset > dest.length - length || offset < 0 || length < 0) {
throw new IndexOutOfBoundsException();
}
if (length == 0) {
@@ -307,7 +307,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
if (pos < count) {
/* There are bytes available in the buffer. */
final int copylength = count - pos >= length ? length : count - pos;
- System.arraycopy(localBuf, pos, buffer, offset, copylength);
+ System.arraycopy(localBuf, pos, dest, offset, copylength);
pos += copylength;
if (copylength == length || localIn.available() == 0) {
return copylength;
@@ -324,7 +324,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
* If we're not marked and the required size is greater than the buffer, simply read the bytes directly bypassing the buffer.
*/
if (markPos == IOUtils.EOF && required >= localBuf.length) {
- read = localIn.read(buffer, offset, required);
+ read = localIn.read(dest, offset, required);
if (read == IOUtils.EOF) {
return required == length ? IOUtils.EOF : length - required;
}
@@ -341,7 +341,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
}
read = count - pos >= required ? required : count - pos;
- System.arraycopy(localBuf, pos, buffer, offset, read);
+ System.arraycopy(localBuf, pos, dest, offset, read);
pos += read;
}
required -= read;
@@ -397,10 +397,12 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
}
if (count - pos >= amount) {
- pos += amount;
+ // (int count - int pos) here is always an int so amount is also in the int range if the above test is true.
+ // We can safely cast to int and avoid static analysis warnings.
+ pos += (int) amount;
return amount;
}
- long read = count - pos;
+ int read = count - pos;
pos = count;
if (markPos != IOUtils.EOF && amount <= markLimit) {
@@ -408,7 +410,9 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
return read;
}
if (count - pos >= amount - read) {
- pos += amount - read;
+ // (int count - int pos) here is always an int so (amount - read) is also in the int range if the above test is true.
+ // We can safely cast to int and avoid static analysis warnings.
+ pos += (int) amount - read;
return amount;
}
// Couldn't get all the bytes, skip what we read
diff --git a/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java b/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java
index a4fc696c..f10c1120 100644
--- a/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java
@@ -106,6 +106,12 @@ public class UnsynchronizedByteArrayInputStream extends InputStream {
return super.setByteArray(origin);
}
+ /**
+ * Sets the length.
+ *
+ * @param length Must be greater or equal to 0.
+ * @return this.
+ */
public Builder setLength(final int length) {
if (length < 0) {
throw new IllegalArgumentException("length cannot be negative");
@@ -114,6 +120,12 @@ public class UnsynchronizedByteArrayInputStream extends InputStream {
return this;
}
+ /**
+ * Sets the offset.
+ *
+ * @param offset Must be greater or equal to 0.
+ * @return this.
+ */
public Builder setOffset(final int offset) {
if (offset < 0) {
throw new IllegalArgumentException("offset cannot be negative");
diff --git a/src/main/java/org/apache/commons/io/input/XmlStreamReader.java b/src/main/java/org/apache/commons/io/input/XmlStreamReader.java
index a38ef807..290e5360 100644
--- a/src/main/java/org/apache/commons/io/input/XmlStreamReader.java
+++ b/src/main/java/org/apache/commons/io/input/XmlStreamReader.java
@@ -157,11 +157,23 @@ public class XmlStreamReader extends Reader {
return super.setCharset(Charsets.toCharset(charset, getCharsetDefault()));
}
+ /**
+ * Sets the HTTP content type.
+ *
+ * @param httpContentType the HTTP content type.
+ * @return this.
+ */
public Builder setHttpContentType(final String httpContentType) {
this.httpContentType = httpContentType;
return this;
}
+ /**
+ * Sets the lenient toggle.
+ *
+ * @param lenient the lenient toggle.
+ * @return this.
+ */
public Builder setLenient(final boolean lenient) {
this.lenient = lenient;
return this;
@@ -209,8 +221,14 @@ public class XmlStreamReader extends Reader {
// @formatter:off
"^<\\?xml\\s+"
+ "version\\s*=\\s*(?:(?:\"1\\.[0-9]+\")|(?:'1.[0-9]+'))\\s+"
- + "encoding\\s*=\\s*((?:\"[A-Za-z]([A-Za-z0-9\\._]|-)*\")|(?:'[A-Za-z]([A-Za-z0-9\\\\._]|-)*'))",
+ + "encoding\\s*=\\s*"
+ + "((?:\"[A-Za-z0-9][A-Za-z0-9._+:-]*\")" // double-quoted
+ + "|(?:'[A-Za-z0-9][A-Za-z0-9._+:-]*'))", // single-quoted
Pattern.MULTILINE);
+ // N.B. the documented pattern is
+ // EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+ // However this does not match all the aliases that are supported by Java.
+ // e.g. '437', 'ISO_8859-1:1987' and 'ebcdic-de-273+euro'
// @formatter:on
private static final String RAW_EX_1 = "Illegal encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] encoding mismatch";
diff --git a/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java b/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
index d4dc19e9..3382bdcd 100644
--- a/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
@@ -70,6 +70,9 @@ public class DeferredFileOutputStream extends ThresholdingOutputStream {
private String suffix;
private Path directory;
+ /**
+ * Constructs a new builder.
+ */
public Builder() {
setBufferSizeDefault(AbstractByteArrayOutputStream.DEFAULT_SIZE);
setBufferSize(AbstractByteArrayOutputStream.DEFAULT_SIZE);
@@ -265,28 +268,6 @@ public class DeferredFileOutputStream extends ThresholdingOutputStream {
}
/**
- * Constructs an instance of this class which will trigger an event at the specified threshold, and save data either to a file beyond that point.
- *
- * @param threshold The number of bytes at which to trigger an event.
- * @param outputFile The file to which data is saved beyond the threshold.
- * @param prefix Prefix to use for the temporary file.
- * @param suffix Suffix to use for the temporary file.
- * @param directory Temporary file directory.
- * @param initialBufferSize The initial size of the in memory buffer.
- * @throws IllegalArgumentException if initialBufferSize &lt; 0.
- */
- private DeferredFileOutputStream(final int threshold, final Path outputFile, final String prefix, final String suffix, final Path directory,
- final int initialBufferSize) {
- super(threshold);
- this.outputPath = toPath(outputFile, null);
- this.prefix = prefix;
- this.suffix = suffix;
- this.directory = toPath(directory, PathUtils::getTempDirectory);
- this.memoryOutputStream = new ByteArrayOutputStream(checkBufferSize(initialBufferSize));
- this.currentOutputStream = memoryOutputStream;
- }
-
- /**
* Constructs an instance of this class which will trigger an event at the specified threshold, and save data to a file beyond that point.
*
* @param threshold The number of bytes at which to trigger an event.
@@ -317,6 +298,28 @@ public class DeferredFileOutputStream extends ThresholdingOutputStream {
}
/**
+ * Constructs an instance of this class which will trigger an event at the specified threshold, and save data either to a file beyond that point.
+ *
+ * @param threshold The number of bytes at which to trigger an event.
+ * @param outputFile The file to which data is saved beyond the threshold.
+ * @param prefix Prefix to use for the temporary file.
+ * @param suffix Suffix to use for the temporary file.
+ * @param directory Temporary file directory.
+ * @param initialBufferSize The initial size of the in memory buffer.
+ * @throws IllegalArgumentException if initialBufferSize &lt; 0.
+ */
+ private DeferredFileOutputStream(final int threshold, final Path outputFile, final String prefix, final String suffix, final Path directory,
+ final int initialBufferSize) {
+ super(threshold);
+ this.outputPath = toPath(outputFile, null);
+ this.prefix = prefix;
+ this.suffix = suffix;
+ this.directory = toPath(directory, PathUtils::getTempDirectory);
+ this.memoryOutputStream = new ByteArrayOutputStream(checkBufferSize(initialBufferSize));
+ this.currentOutputStream = memoryOutputStream;
+ }
+
+ /**
* Constructs an instance of this class which will trigger an event at the specified threshold, and save data to a temporary file beyond that point. The
* initial buffer size will default to 32 bytes which is ByteArrayOutputStream's default buffer size.
*
diff --git a/src/main/java/org/apache/commons/io/output/LockableFileWriter.java b/src/main/java/org/apache/commons/io/output/LockableFileWriter.java
index 064de220..b33abc81 100644
--- a/src/main/java/org/apache/commons/io/output/LockableFileWriter.java
+++ b/src/main/java/org/apache/commons/io/output/LockableFileWriter.java
@@ -70,6 +70,9 @@ public class LockableFileWriter extends Writer {
private boolean append;
private AbstractOrigin<?, ?> lockDirectory = AbstractOriginSupplier.newFileOrigin(FileUtils.getTempDirectoryPath());
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
setBufferSizeDefault(AbstractByteArrayOutputStream.DEFAULT_SIZE);
setBufferSize(AbstractByteArrayOutputStream.DEFAULT_SIZE);
diff --git a/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java b/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
index 1d8a3a03..8102eb58 100644
--- a/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
@@ -149,11 +149,10 @@ public class ThresholdingOutputStream extends OutputStream {
*
* @return The underlying output stream.
* @throws IOException if an error occurs.
- * @deprecated Use {@link #getOutputStream()}.
+ * @since 2.14.0
*/
- @Deprecated
- protected OutputStream getStream() throws IOException {
- return getOutputStream();
+ protected OutputStream getOutputStream() throws IOException {
+ return outputStreamGetter.apply(this);
}
/**
@@ -162,10 +161,11 @@ public class ThresholdingOutputStream extends OutputStream {
*
* @return The underlying output stream.
* @throws IOException if an error occurs.
- * @since 2.14.0
+ * @deprecated Use {@link #getOutputStream()}.
*/
- protected OutputStream getOutputStream() throws IOException {
- return outputStreamGetter.apply(this);
+ @Deprecated
+ protected OutputStream getStream() throws IOException {
+ return getOutputStream();
}
/**
diff --git a/src/main/java/org/apache/commons/io/output/WriterOutputStream.java b/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
index dc4cd6fd..bc2c5c21 100644
--- a/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
@@ -99,6 +99,9 @@ public class WriterOutputStream extends OutputStream {
private CharsetDecoder charsetDecoder;
private boolean writeImmediately;
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
this.charsetDecoder = getCharset().newDecoder();
}
diff --git a/src/main/java/org/apache/commons/io/output/XmlStreamWriter.java b/src/main/java/org/apache/commons/io/output/XmlStreamWriter.java
index b40a2aca..6f732a72 100644
--- a/src/main/java/org/apache/commons/io/output/XmlStreamWriter.java
+++ b/src/main/java/org/apache/commons/io/output/XmlStreamWriter.java
@@ -62,6 +62,9 @@ public class XmlStreamWriter extends Writer {
*/
public static class Builder extends AbstractStreamBuilder<XmlStreamWriter, Builder> {
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
setCharsetDefault(StandardCharsets.UTF_8);
setCharset(StandardCharsets.UTF_8);
diff --git a/src/main/java/org/apache/commons/io/package-info.java b/src/main/java/org/apache/commons/io/package-info.java
index 29464fe9..6633c106 100644
--- a/src/main/java/org/apache/commons/io/package-info.java
+++ b/src/main/java/org/apache/commons/io/package-info.java
@@ -24,7 +24,7 @@
* <b>FileUtils</b> provides operations based around the JDK File class. These include reading, writing, copying, comparing and deleting.
* </p>
* <p>
- * <b>FilenameUtils</b> provides utilities based on filenames. This utility class manipulates filenames without using File objects. It aims to simplify the
+ * <b>FilenameUtils</b> provides utilities based on filenames. This utility class manipulates file names without using File objects. It aims to simplify the
* transition between Windows and Unix. Before using this class however, you should consider whether you should be using File objects.
* </p>
* <p>
diff --git a/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java b/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java
index bde163c7..6e60f32e 100644
--- a/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java
+++ b/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java
@@ -110,6 +110,32 @@ public class ValidatingObjectInputStream extends ObjectInputStream {
}
/**
+ * Checks that the class name conforms to requirements.
+ *
+ * @param name The class name
+ * @throws InvalidClassException when a non-accepted class is encountered
+ */
+ private void checkClassName(final String name) throws InvalidClassException {
+ // Reject has precedence over accept
+ for (final ClassNameMatcher m : rejectMatchers) {
+ if (m.matches(name)) {
+ invalidClassNameFound(name);
+ }
+ }
+
+ boolean ok = false;
+ for (final ClassNameMatcher m : acceptMatchers) {
+ if (m.matches(name)) {
+ ok = true;
+ break;
+ }
+ }
+ if (!ok) {
+ invalidClassNameFound(name);
+ }
+ }
+
+ /**
* Called to throw {@link InvalidClassException} if an invalid
* class name is found during deserialization. Can be overridden, for example
* to log those class names.
@@ -172,31 +198,7 @@ public class ValidatingObjectInputStream extends ObjectInputStream {
@Override
protected Class<?> resolveClass(final ObjectStreamClass osc) throws IOException, ClassNotFoundException {
- validateClassName(osc.getName());
+ checkClassName(osc.getName());
return super.resolveClass(osc);
}
-
- /** Check that the classname conforms to requirements.
- * @param name The class name
- * @throws InvalidClassException when a non-accepted class is encountered
- */
- private void validateClassName(final String name) throws InvalidClassException {
- // Reject has precedence over accept
- for (final ClassNameMatcher m : rejectMatchers) {
- if (m.matches(name)) {
- invalidClassNameFound(name);
- }
- }
-
- boolean ok = false;
- for (final ClassNameMatcher m : acceptMatchers) {
- if (m.matches(name)) {
- ok = true;
- break;
- }
- }
- if (!ok) {
- invalidClassNameFound(name);
- }
- }
} \ No newline at end of file