diff --git a/.asf.yaml b/.asf.yaml
index 5ea25ac8897..33a8dd8c4ff 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -23,7 +23,8 @@ notifications:
pullrequests: issues@commons.apache.org
jira_options: link label
jobs: notifications@commons.apache.org
- issues_bot_dependabot: notifications@commons.apache.org
- pullrequests_bot_dependabot: notifications@commons.apache.org
+ # commits_bot_dependabot: dependabot@commons.apache.org
+ issues_bot_dependabot: dependabot@commons.apache.org
+ pullrequests_bot_dependabot: dependabot@commons.apache.org
issues_bot_codecov-commenter: notifications@commons.apache.org
pullrequests_bot_codecov-commenter: notifications@commons.apache.org
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 00079caf1bc..90ec55f742e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -18,10 +18,8 @@ updates:
- package-ecosystem: "maven"
directory: "/"
schedule:
- interval: "weekly"
- day: "friday"
+ interval: "quarterly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
- interval: "weekly"
- day: "friday"
+ interval: "quarterly"
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 7578b4da036..9ff35c83e79 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -23,8 +23,8 @@ Before you push a pull request, review this list:
- [ ] Read the [contribution guidelines](CONTRIBUTING.md) for this project.
- [ ] Read the [ASF Generative Tooling Guidance](https://www.apache.org/legal/generative-tooling.html) if you use Artificial Intelligence (AI).
-- [ ] I used AI to create any part of, or all of, this pull request.
+- [ ] I used AI to create any part of, or all of, this pull request. Which AI tool was used to create this pull request, and to what extent did it contribute?
- [ ] Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself.
-- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best-practice.
+- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best practice.
- [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
- [ ] Each commit in the pull request should have a meaningful subject line and body. Note that a maintainer may squash commits during the merge process.
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index fcc16fe390a..32fe63cd78f 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -42,6 +42,7 @@ jobs:
security-events: write
strategy:
+ max-parallel: 20
fail-fast: false
matrix:
language: [ 'java' ]
@@ -50,10 +51,10 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
+ - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
@@ -62,7 +63,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5
+ uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -73,7 +74,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5
+ uses: github/codeql-action/autobuild@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -87,4 +88,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5
+ uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index 1e043924237..f0d8ca94e32 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -26,6 +26,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: 'Dependency Review PR'
- uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # v4.7.3
+ uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 7d0f0892434..ee9557cf46a 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -37,9 +37,10 @@ jobs:
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.experimental }}
strategy:
+ max-parallel: 20
matrix:
- os: [ubuntu-latest, windows-latest, macos-13]
- java: [ 8, 11, 17, 21 ]
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ java: [ 8, 11, 17, 21, 25 ]
experimental: [false]
# Keep the same parameter order as the matrix above
include:
@@ -48,16 +49,6 @@ jobs:
java: 21
experimental: false
deploy: true
- # Experimental builds: Java 25-ea
- - os: ubuntu-latest
- java: 25
- experimental: true
- - os: windows-latest
- java: 25
- experimental: true
- - os: macos-latest
- java: 25
- experimental: true
# Experimental builds: Java 26-ea
- os: ubuntu-latest
java: 26-ea
@@ -70,19 +61,19 @@ jobs:
experimental: true
fail-fast: false
steps:
- - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
+ - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Set up JDK ${{ matrix.java }}
- uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
- distribution: 'temurin'
+ distribution: ${{ runner.os == 'macOS' && matrix.java == '8' && 'zulu' || 'temurin' }}
java-version: ${{ matrix.java }}
# these values cause the plugin to set up the Maven settings.xml file
server-id: apache.snapshots.https # Value of the distributionManagement/repository/id field of the pom.xml
diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml
index cf4d6ba87b0..715e03fcf97 100644
--- a/.github/workflows/scorecards-analysis.yml
+++ b/.github/workflows/scorecards-analysis.yml
@@ -42,12 +42,12 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: "Run analysis"
- uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # 2.4.2
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # 2.4.3
with:
results_file: results.sarif
results_format: sarif
@@ -59,13 +59,13 @@ jobs:
publish_results: true
- name: "Upload artifact"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: SARIF file
path: results.sarif
retention-days: 5
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5
+ uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
with:
sarif_file: results.sarif
diff --git a/.gitignore b/.gitignore
index f43fea02686..91824e5be73 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,3 @@
-### https://raw.github.com/github/gitignore/14b7566ce157ce95b07006466bacee160f242284/maven.gitignore
-
target/
pom.xml.tag
pom.xml.releaseBackup
@@ -7,16 +5,19 @@ pom.xml.versionsBackup
pom.xml.next
release.properties
-
site-content
/.classpath
/.project
/.settings/
-### Ignore IntelliJ files
+# Ignore IntelliJ files
/.idea/
*.iml
/bin/
-### Ignore Visual Studio code files
+# Ignore Visual Studio code files
/.vscode/
+
+# NetBeans files
+nb-configuration.xml
+nbactions.xml
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f708680735d..e924b4ac04e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -69,7 +69,7 @@ Making Changes
+ Respect the original code style:
+ Only use spaces for indentation; you can check for unnecessary whitespace with `git diff` before committing.
+ Create minimal diffs - disable _On Save_ actions like _Reformat Source Code_ or _Organize Imports_. If you feel the source code should be reformatted create a separate PR for this change first.
-+ Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible but is a best-practice.
++ Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible but is a best practice.
Unit tests are typically in the `src/test/java` directory.
+ Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself.
+ Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
@@ -110,7 +110,6 @@ Additional Resources
+ [Contributor License Agreement][cla]
+ [General GitHub documentation](https://help.github.com/)
+ [GitHub pull request documentation](https://help.github.com/articles/creating-a-pull-request/)
-+ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
[cla]:https://www.apache.org/licenses/#clas
[jira]:https://issues.apache.org/jira/browse/IO
diff --git a/NOTICE.txt b/NOTICE.txt
index 2a4682551b1..b9fb860712d 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,5 +1,5 @@
Apache Commons IO
-Copyright 2002-2025 The Apache Software Foundation
+Copyright 2002-2026 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (https://www.apache.org/).
diff --git a/README.md b/README.md
index bb31ce854a6..8e4ae6db426 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ Apache Commons IO
[](https://github.com/apache/commons-io/actions/workflows/maven.yml)
[](https://search.maven.org/artifact/commons-io/commons-io)
-[](https://javadoc.io/doc/commons-io/commons-io/2.20.0)
+[](https://javadoc.io/doc/commons-io/commons-io/2.22.0)
[](https://github.com/apache/commons-io/actions/workflows/codeql-analysis.yml)
[](https://api.securityscorecards.dev/projects/github.com/apache/commons-io)
@@ -69,7 +69,7 @@ Alternatively, you can pull it from the central Maven repositories:
+ * Clears this buffer. The position is set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ * Invoke this method before using a sequence of channel-read or put operations to fill this buffer. For example:
+ *
+ * This method does not actually erase the data in the buffer, but it is named as if it did because it will most often be used in situations in which that
+ * might as well be the case.
+ *
+ * If the given buffer is a not direct buffer, nothing happens to that buffer.
+ *
+ * If the buffer is read-only, then nothing happens to that buffer.
+ *
+ * buf.clear(); // Prepare buffer for reading
+ * in.read(buf); // Read data
+ *
+ *
+ *
| Charset | + *Description | + *
|---|---|
| {@code US-ASCII} | + *Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set. | + *
| {@code ISO-8859-1} | + *ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1. | + *
| {@code UTF-8} | + *Eight-bit Unicode Transformation Format. | + *
| {@code UTF-16BE} | + *Sixteen-bit Unicode Transformation Format, big-endian byte order. | + *
| {@code UTF-16LE} | + *Sixteen-bit Unicode Transformation Format, little-endian byte order. | + *
| {@code UTF-16} | + *Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order + * accepted on input, big-endian used on output.) | + *
* For byte-to-char methods, a {@code copy} variant allows the encoding @@ -115,9 +117,10 @@ public class CopyUtils { /** * Copies bytes from a {@code byte[]} to an {@link OutputStream}. - * @param input the byte array to read from - * @param output the {@link OutputStream} to write to - * @throws IOException In case of an I/O problem + * + * @param input the byte array to read from. + * @param output the {@link OutputStream} to write to. + * @throws IOException In case of an I/O problem. */ public static void copy(final byte[] input, final OutputStream output) throws IOException { output.write(input); @@ -128,10 +131,10 @@ public static void copy(final byte[] input, final OutputStream output) throws IO * {@link Writer}. * The platform's default encoding is used for the byte-to-char conversion. * - * @param input the byte array to read from - * @param output the {@link Writer} to write to - * @throws IOException In case of an I/O problem - * @deprecated Use {@link #copy(byte[], Writer, String)} instead + * @param input the byte array to read from. + * @param output the {@link Writer} to write to. + * @throws IOException In case of an I/O problem. + * @deprecated Use {@link #copy(byte[], Writer, String)} instead. */ @Deprecated public static void copy(final byte[] input, final Writer output) throws IOException { @@ -143,12 +146,12 @@ public static void copy(final byte[] input, final Writer output) throws IOExcept * Copies and convert bytes from a {@code byte[]} to chars on a * {@link Writer}, using the specified encoding. * - * @param input the byte array to read from - * @param output the {@link Writer} to write to + * @param input the byte array to read from. + * @param output the {@link Writer} to write to. * @param encoding The name of a supported character encoding. See the - * IANA + * IANA * Charset Registry for a list of valid encoding types. - * @throws IOException In case of an I/O problem + * @throws IOException In case of an I/O problem. */ public static void copy(final byte[] input, final Writer output, final String encoding) throws IOException { final ByteArrayInputStream inputStream = new ByteArrayInputStream(input); @@ -159,10 +162,10 @@ public static void copy(final byte[] input, final Writer output, final String en * Copies bytes from an {@link InputStream} to an * {@link OutputStream}. * - * @param input the {@link InputStream} to read from - * @param output the {@link OutputStream} to write to - * @return the number of bytes copied - * @throws IOException In case of an I/O problem + * @param input the {@link InputStream} to read from. + * @param output the {@link OutputStream} to write to. + * @return the number of bytes copied. + * @throws IOException In case of an I/O problem. */ public static int copy(final InputStream input, final OutputStream output) throws IOException { final byte[] buffer = IOUtils.byteArray(); @@ -179,13 +182,13 @@ public static int copy(final InputStream input, final OutputStream output) throw * Copies and convert bytes from an {@link InputStream} to chars on a * {@link Writer}. *
- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset} for byte-to-char conversion. + * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion. *
* - * @param input the {@link InputStream} to read from - * @param output the {@link Writer} to write to - * @throws IOException In case of an I/O problem - * @deprecated Use {@link #copy(InputStream, Writer, String)} instead + * @param input the {@link InputStream} to read from. + * @param output the {@link Writer} to write to. + * @throws IOException In case of an I/O problem. + * @deprecated Use {@link #copy(InputStream, Writer, String)} instead. */ @Deprecated public static void copy( @@ -201,12 +204,12 @@ public static void copy( * Copies and convert bytes from an {@link InputStream} to chars on a * {@link Writer}, using the specified encoding. * - * @param input the {@link InputStream} to read from - * @param output the {@link Writer} to write to + * @param input the {@link InputStream} to read from. + * @param output the {@link Writer} to write to. * @param encoding The name of a supported character encoding. See the - * IANA + * IANA * Charset Registry for a list of valid encoding types. - * @throws IOException In case of an I/O problem + * @throws IOException In case of an I/O problem. */ public static void copy( final InputStream input, @@ -221,13 +224,13 @@ public static void copy( * Serialize chars from a {@link Reader} to bytes on an * {@link OutputStream}, and flush the {@link OutputStream}. *- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset} for byte-to-char conversion. + * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion. *
* - * @param input the {@link Reader} to read from - * @param output the {@link OutputStream} to write to - * @throws IOException In case of an I/O problem - * @deprecated Use {@link #copy(Reader, OutputStream, String)} instead + * @param input the {@link Reader} to read from. + * @param output the {@link OutputStream} to write to. + * @throws IOException In case of an I/O problem. + * @deprecated Use {@link #copy(Reader, OutputStream, String)} instead. */ @Deprecated public static void copy( @@ -246,12 +249,12 @@ public static void copy( * Serialize chars from a {@link Reader} to bytes on an * {@link OutputStream}, and flush the {@link OutputStream}. * - * @param input the {@link Reader} to read from - * @param output the {@link OutputStream} to write to + * @param input the {@link Reader} to read from. + * @param output the {@link OutputStream} to write to. * @param encoding The name of a supported character encoding. See the - * IANA + * IANA * Charset Registry for a list of valid encoding types. - * @throws IOException In case of an I/O problem + * @throws IOException In case of an I/O problem. * @since 2.5 */ public static void copy( @@ -269,23 +272,25 @@ public static void copy( /** * Copies chars from a {@link Reader} to a {@link Writer}. * - * @param input the {@link Reader} to read from - * @param output the {@link Writer} to write to - * @return the number of characters copied - * @throws IOException In case of an I/O problem + * @param input the {@link Reader} to read from. + * @param output the {@link Writer} to write to. + * @return the number of characters copied. + * @throws IOException In case of an I/O problem. */ public static int copy( final Reader input, final Writer output) throws IOException { - final char[] buffer = IOUtils.getScratchCharArray(); - int count = 0; - int n; - while (EOF != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; + try (ScratchChars scratch = IOUtils.ScratchChars.get()) { + final char[] buffer = scratch.array(); + int count = 0; + int n; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; } - return count; } /** @@ -293,13 +298,13 @@ public static int copy( * {@link OutputStream}, and * flush the {@link OutputStream}. *- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset} for byte-to-char conversion. + * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion. *
* - * @param input the {@link String} to read from - * @param output the {@link OutputStream} to write to - * @throws IOException In case of an I/O problem - * @deprecated Use {@link #copy(String, OutputStream, String)} instead + * @param input the {@link String} to read from. + * @param output the {@link OutputStream} to write to. + * @throws IOException In case of an I/O problem. + * @deprecated Use {@link #copy(String, OutputStream, String)} instead. */ @Deprecated public static void copy( @@ -320,12 +325,12 @@ public static void copy( * {@link OutputStream}, and * flush the {@link OutputStream}. * - * @param input the {@link String} to read from - * @param output the {@link OutputStream} to write to + * @param input the {@link String} to read from. + * @param output the {@link OutputStream} to write to. * @param encoding The name of a supported character encoding. See the - * IANA + * IANA * Charset Registry for a list of valid encoding types. - * @throws IOException In case of an I/O problem + * @throws IOException In case of an I/O problem. * @since 2.5 */ public static void copy( @@ -344,9 +349,9 @@ public static void copy( /** * Copies chars from a {@link String} to a {@link Writer}. * - * @param input the {@link String} to read from - * @param output the {@link Writer} to write to - * @throws IOException In case of an I/O problem + * @param input the {@link String} to read from. + * @param output the {@link Writer} to write to. + * @throws IOException In case of an I/O problem. */ public static void copy(final String input, final Writer output) throws IOException { diff --git a/src/main/java/org/apache/commons/io/DirectoryWalker.java b/src/main/java/org/apache/commons/io/DirectoryWalker.java index ac3d8bd5fd7..1d2a7678fd4 100644 --- a/src/main/java/org/apache/commons/io/DirectoryWalker.java +++ b/src/main/java/org/apache/commons/io/DirectoryWalker.java @@ -167,7 +167,7 @@ ** Two possible scenarios are envisaged for cancellation: @@ -196,14 +196,14 @@ *
* public class FooDirectoryWalker extends DirectoryWalker {
*
- * private volatile boolean cancelled = false;
+ * private volatile boolean canceled = false;
*
* public void cancel() {
- * cancelled = true;
+ * canceled = true;
* }
*
* protected boolean handleIsCancelled(File file, int depth, Collection results) {
- * return cancelled;
+ * return canceled;
* }
*
* protected void handleCancelled(File startDirectory, Collection results, CancelException cancel) {
@@ -265,6 +265,7 @@ public static class CancelException extends IOException {
/** The file being processed when the exception was thrown. */
private final File file;
+
/** The file depth when the exception was thrown. */
private final int depth;
@@ -272,8 +273,8 @@ public static class CancelException extends IOException {
* Constructs a {@link CancelException} with
* the file and depth when cancellation occurred.
*
- * @param file the file when the operation was cancelled, may be null
- * @param depth the depth when the operation was cancelled, may be null
+ * @param file the file when the operation was canceled, may be null.
+ * @param depth the depth when the operation was canceled, may be null.
*/
public CancelException(final File file, final int depth) {
this("Operation Cancelled", file, depth);
@@ -284,9 +285,9 @@ public CancelException(final File file, final int depth) {
* an appropriate message and the file and depth when
* cancellation occurred.
*
- * @param message the detail message
- * @param file the file when the operation was cancelled
- * @param depth the depth when the operation was cancelled
+ * @param message the detail message.
+ * @param file the file when the operation was canceled.
+ * @param depth the depth when the operation was canceled.
*/
public CancelException(final String message, final File file, final int depth) {
super(message);
@@ -295,23 +296,24 @@ public CancelException(final String message, final File file, final int depth) {
}
/**
- * Returns the depth when the operation was cancelled.
+ * Returns the depth when the operation was canceled.
*
- * @return the depth when the operation was cancelled
+ * @return the depth when the operation was canceled.
*/
public int getDepth() {
return depth;
}
/**
- * Returns the file when the operation was cancelled.
+ * Returns the file when the operation was canceled.
*
- * @return the file when the operation was cancelled
+ * @return the file when the operation was canceled.
*/
public File getFile() {
return file;
}
}
+
/**
* The file filter to use to filter files and directories.
*/
@@ -338,9 +340,9 @@ protected DirectoryWalker() {
* filtering should occur and all files and directories will be visited.
*
*
- * @param filter the filter to apply, null means visit all files
+ * @param filter the filter to apply, null means visit all files.
* @param depthLimit controls how deep the hierarchy is
- * navigated to (less than 0 means unlimited)
+ * navigated to (less than 0 means unlimited).
*/
protected DirectoryWalker(final FileFilter filter, final int depthLimit) {
this.filter = filter;
@@ -357,10 +359,10 @@ protected DirectoryWalker(final FileFilter filter, final int depthLimit) {
* A {@code null} filter means that no filtering should occur.
*
*
- * @param directoryFilter the filter to apply to directories, null means visit all directories
- * @param fileFilter the filter to apply to files, null means visit all files
+ * @param directoryFilter the filter to apply to directories, null means visit all directories.
+ * @param fileFilter the filter to apply to files, null means visit all files.
* @param depthLimit controls how deep the hierarchy is
- * navigated to (less than 0 means unlimited)
+ * navigated to (less than 0 means unlimited).
*/
protected DirectoryWalker(IOFileFilter directoryFilter, IOFileFilter fileFilter, final int depthLimit) {
if (directoryFilter == null && fileFilter == null) {
@@ -376,7 +378,7 @@ protected DirectoryWalker(IOFileFilter directoryFilter, IOFileFilter fileFilter,
}
/**
- * Checks whether the walk has been cancelled by calling {@link #handleIsCancelled},
+ * Checks whether the walk has been canceled by calling {@link #handleIsCancelled},
* throwing a {@link CancelException} if it has.
*
* Writers of subclasses should not normally call this method as it is called
@@ -385,10 +387,10 @@ protected DirectoryWalker(IOFileFilter directoryFilter, IOFileFilter fileFilter,
* you may wish to check for cancellation by calling this method.
*
*
- * @param file the current file being processed
- * @param depth the current file level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param file the current file being processed.
+ * @param depth the current file level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
protected final void checkIfCancelled(final File file, final int depth, final Collection results) throws
IOException {
@@ -403,11 +405,11 @@ protected final void checkIfCancelled(final File file, final int depth, final Co
* This implementation returns the files unchanged
*
*
- * @param directory the current directory being processed
- * @param depth the current directory level (starting directory = 0)
+ * @param directory the current directory being processed.
+ * @param depth the current directory level (starting directory = 0).
* @param files the files (possibly filtered) in the directory, may be {@code null}
- * @return the filtered list of files
- * @throws IOException if an I/O Error occurs
+ * @return the filtered list of files.
+ * @throws IOException if an I/O Error occurs.
* @since 2.0
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
@@ -417,18 +419,18 @@ protected File[] filterDirectoryContents(final File directory, final int depth,
}
/**
- * Overridable callback method invoked when the operation is cancelled.
+ * Overridable callback method invoked when the operation is canceled.
* The file being processed when the cancellation occurred can be
* obtained from the exception.
*
* This implementation just re-throws the {@link CancelException}.
*
*
- * @param startDirectory the directory that the walk started from
- * @param results the collection of result objects, may be updated
+ * @param startDirectory the directory that the walk started from.
+ * @param results the collection of result objects, may be updated.
* @param cancel the exception throw to cancel further processing
* containing details at the point of cancellation.
- * @throws IOException if an I/O Error occurs
+ * @throws IOException if an I/O Error occurs.
*/
protected void handleCancelled(final File startDirectory, final Collection results,
final CancelException cancel) throws IOException {
@@ -447,11 +449,11 @@ protected void handleCancelled(final File startDirectory, final Collection re
* This implementation does nothing and returns true.
*
*
- * @param directory the current directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @return true to process this directory, false to skip this directory
- * @throws IOException if an I/O Error occurs
+ * @param directory the current directory being processed.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @return true to process this directory, false to skip this directory.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected boolean handleDirectory(final File directory, final int depth, final Collection results) throws
@@ -466,10 +468,10 @@ protected boolean handleDirectory(final File directory, final int depth, final C
* This implementation does nothing.
*
*
- * @param directory the directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param directory the directory being processed.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleDirectoryEnd(final File directory, final int depth, final Collection results) throws
@@ -483,10 +485,10 @@ protected void handleDirectoryEnd(final File directory, final int depth, final C
* This implementation does nothing.
*
*
- * @param directory the current directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param directory the current directory being processed.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleDirectoryStart(final File directory, final int depth, final Collection results) throws
@@ -500,8 +502,8 @@ protected void handleDirectoryStart(final File directory, final int depth, final
* This implementation does nothing.
*
*
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleEnd(final Collection results) throws IOException {
@@ -514,10 +516,10 @@ protected void handleEnd(final Collection results) throws IOException {
* This implementation does nothing.
*
*
- * @param file the current file being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param file the current file being processed.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleFile(final File file, final int depth, final Collection results) throws IOException {
@@ -526,7 +528,7 @@ protected void handleFile(final File file, final int depth, final Collection
/**
* Overridable callback method invoked to determine if the entire walk
- * operation should be immediately cancelled.
+ * operation should be immediately canceled.
*
* This method should be implemented by those subclasses that want to
* provide a public {@code cancel()} method available from another
@@ -534,13 +536,13 @@ protected void handleFile(final File file, final int depth, final Collection
*
*
* public class FooDirectoryWalker extends DirectoryWalker {
- * private volatile boolean cancelled = false;
+ * private volatile boolean canceled = false;
*
* public void cancel() {
- * cancelled = true;
+ * canceled = true;
* }
* private void handleIsCancelled(File file, int depth, Collection results) {
- * return cancelled;
+ * return canceled;
* }
* protected void handleCancelled(File startDirectory,
* Collection results, CancelException cancel) {
@@ -550,23 +552,23 @@ protected void handleFile(final File file, final int depth, final Collection
*
*
* If this method returns true, then the directory walk is immediately
- * cancelled. The next callback method will be {@link #handleCancelled}.
+ * canceled. The next callback method will be {@link #handleCancelled}.
*
*
* This implementation returns false.
*
*
- * @param file the file or directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @return true if the walk has been cancelled
- * @throws IOException if an I/O Error occurs
+ * @param file the file or directory being processed.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @return true if the walk has been canceled.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected boolean handleIsCancelled(
final File file, final int depth, final Collection results) throws IOException {
// do nothing - overridable by subclass
- return false; // not cancelled
+ return false; // not canceled
}
/**
@@ -575,10 +577,10 @@ protected boolean handleIsCancelled(
* This implementation does nothing.
*
*
- * @param directory the restricted directory
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param directory the restricted directory.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleRestricted(final File directory, final int depth, final Collection results) throws
@@ -592,9 +594,9 @@ protected void handleRestricted(final File directory, final int depth, final Col
* This implementation does nothing.
*
*
- * @param startDirectory the directory to start from
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param startDirectory the directory to start from.
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleStart(final File startDirectory, final Collection results) throws IOException {
@@ -613,10 +615,10 @@ protected void handleStart(final File startDirectory, final Collection result
* The event methods have the prefix {@code handle}.
*
*
- * @param startDirectory the directory to start from, not null
- * @param results the collection of result objects, may be updated
- * @throws NullPointerException if the start directory is null
- * @throws IOException if an I/O Error occurs
+ * @param startDirectory the directory to start from, not null.
+ * @param results the collection of result objects, may be updated.
+ * @throws NullPointerException if the start directory is null.
+ * @throws IOException if an I/O Error occurs.
*/
protected final void walk(final File startDirectory, final Collection results) throws IOException {
Objects.requireNonNull(startDirectory, "startDirectory");
@@ -632,10 +634,10 @@ protected final void walk(final File startDirectory, final Collection results
/**
* Main recursive method to examine the directory hierarchy.
*
- * @param directory the directory to examine, not null
- * @param depth the directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param directory the directory to examine, not null.
+ * @param depth the directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
private void walk(final File directory, final int depth, final Collection results) throws IOException {
checkIfCancelled(directory, depth, results);
diff --git a/src/main/java/org/apache/commons/io/EndianUtils.java b/src/main/java/org/apache/commons/io/EndianUtils.java
index 6b4d58eeba3..b6cb2ebd83a 100644
--- a/src/main/java/org/apache/commons/io/EndianUtils.java
+++ b/src/main/java/org/apache/commons/io/EndianUtils.java
@@ -50,9 +50,10 @@ public class EndianUtils {
/**
* Reads the next byte from the input stream.
- * @param input the stream
- * @return the byte
- * @throws IOException if the end of file is reached
+ *
+ * @param input the stream.
+ * @return the byte.
+ * @throws IOException if the end of file is reached.
*/
private static int read(final InputStream input) throws IOException {
final int value = input.read();
@@ -65,10 +66,10 @@ private static int read(final InputStream input) throws IOException {
/**
* Reads a little-endian {@code double} value from a byte array at a given offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes.
*/
public static double readSwappedDouble(final byte[] data, final int offset) {
return Double.longBitsToDouble(readSwappedLong(data, offset));
@@ -77,9 +78,9 @@ public static double readSwappedDouble(final byte[] data, final int offset) {
/**
* Reads a little-endian {@code double} value from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static double readSwappedDouble(final InputStream input) throws IOException {
return Double.longBitsToDouble(readSwappedLong(input));
@@ -88,10 +89,10 @@ public static double readSwappedDouble(final InputStream input) throws IOExcepti
/**
* Reads a little-endian {@code float} value from a byte array at a given offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes.
*/
public static float readSwappedFloat(final byte[] data, final int offset) {
return Float.intBitsToFloat(readSwappedInteger(data, offset));
@@ -100,9 +101,9 @@ public static float readSwappedFloat(final byte[] data, final int offset) {
/**
* Reads a little-endian {@code float} value from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static float readSwappedFloat(final InputStream input) throws IOException {
return Float.intBitsToFloat(readSwappedInteger(input));
@@ -111,14 +112,15 @@ public static float readSwappedFloat(final InputStream input) throws IOException
/**
* Reads a little-endian {@code int} value from a byte array at a given offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes.
*/
public static int readSwappedInteger(final byte[] data, final int offset) {
validateByteArrayOffset(data, offset, Integer.SIZE / Byte.SIZE);
- return ((data[offset + 0] & 0xff) << 0) +
+ return
+ ((data[offset + 0] & 0xff) << 0) +
((data[offset + 1] & 0xff) << 8) +
((data[offset + 2] & 0xff) << 16) +
((data[offset + 3] & 0xff) << 24);
@@ -127,25 +129,29 @@ public static int readSwappedInteger(final byte[] data, final int offset) {
/**
* Reads a little-endian {@code int} value from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static int readSwappedInteger(final InputStream input) throws IOException {
final int value1 = read(input);
final int value2 = read(input);
final int value3 = read(input);
final int value4 = read(input);
- return ((value1 & 0xff) << 0) + ((value2 & 0xff) << 8) + ((value3 & 0xff) << 16) + ((value4 & 0xff) << 24);
+ return
+ ((value1 & 0xff) << 0) +
+ ((value2 & 0xff) << 8) +
+ ((value3 & 0xff) << 16) +
+ ((value4 & 0xff) << 24);
}
/**
* Reads a little-endian {@code long} value from a byte array at a given offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes.
*/
public static long readSwappedLong(final byte[] data, final int offset) {
validateByteArrayOffset(data, offset, Long.SIZE / Byte.SIZE);
@@ -157,9 +163,9 @@ public static long readSwappedLong(final byte[] data, final int offset) {
/**
* Reads a little-endian {@code long} value from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static long readSwappedLong(final InputStream input) throws IOException {
final byte[] bytes = new byte[8];
@@ -172,41 +178,47 @@ public static long readSwappedLong(final InputStream input) throws IOException {
/**
* Reads a little-endian {@code short} value from a byte array at a given offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes.
*/
public static short readSwappedShort(final byte[] data, final int offset) {
validateByteArrayOffset(data, offset, Short.SIZE / Byte.SIZE);
- return (short) (((data[offset + 0] & 0xff) << 0) + ((data[offset + 1] & 0xff) << 8));
+ return (short) (
+ ((data[offset + 0] & 0xff) << 0) +
+ ((data[offset + 1] & 0xff) << 8)
+ );
}
/**
* Reads a little-endian {@code short} value from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static short readSwappedShort(final InputStream input) throws IOException {
- return (short) (((read(input) & 0xff) << 0) + ((read(input) & 0xff) << 8));
+ return (short) (
+ ((read(input) & 0xff) << 0) +
+ ((read(input) & 0xff) << 8)
+ );
}
/**
* Reads a little-endian unsigned integer (32-bit) value from a byte array at a given
* offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes.
*/
public static long readSwappedUnsignedInteger(final byte[] data, final int offset) {
validateByteArrayOffset(data, offset, Integer.SIZE / Byte.SIZE);
final long low = ((data[offset + 0] & 0xff) << 0) +
- ((data[offset + 1] & 0xff) << 8) +
- ((data[offset + 2] & 0xff) << 16);
+ ((data[offset + 1] & 0xff) << 8) +
+ ((data[offset + 2] & 0xff) << 16);
final long high = data[offset + 3] & 0xff;
return (high << 24) + (0xffffffffL & low);
}
@@ -214,16 +226,18 @@ public static long readSwappedUnsignedInteger(final byte[] data, final int offse
/**
* Reads a little-endian unsigned integer (32-bit) from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static long readSwappedUnsignedInteger(final InputStream input) throws IOException {
final int value1 = read(input);
final int value2 = read(input);
final int value3 = read(input);
final int value4 = read(input);
- final long low = ((value1 & 0xff) << 0) + ((value2 & 0xff) << 8) + ((value3 & 0xff) << 16);
+ final long low = ((value1 & 0xff) << 0) +
+ ((value2 & 0xff) << 8) +
+ ((value3 & 0xff) << 16);
final long high = value4 & 0xff;
return (high << 24) + (0xffffffffL & low);
}
@@ -232,28 +246,30 @@ public static long readSwappedUnsignedInteger(final InputStream input) throws IO
* Reads an unsigned short (16-bit) value from a byte array in little-endian order at a given
* offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes.
*/
public static int readSwappedUnsignedShort(final byte[] data, final int offset) {
validateByteArrayOffset(data, offset, Short.SIZE / Byte.SIZE);
- return ((data[offset + 0] & 0xff) << 0) + ((data[offset + 1] & 0xff) << 8);
+ return ((data[offset + 0] & 0xff) << 0) +
+ ((data[offset + 1] & 0xff) << 8);
}
/**
* Reads an unsigned short (16-bit) from an InputStream in little-endian order.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static int readSwappedUnsignedShort(final InputStream input) throws IOException {
final int value1 = read(input);
final int value2 = read(input);
- return ((value1 & 0xff) << 0) + ((value2 & 0xff) << 8);
+ return ((value1 & 0xff) << 0) +
+ ((value2 & 0xff) << 8);
}
/**
@@ -263,8 +279,8 @@ public static int readSwappedUnsignedShort(final InputStream input) throws IOExc
* This can be useful if you have a number that was read from the
* underlying source in the wrong endianness.
*
- * @param value value to convert
- * @return the converted value
+ * @param value value to convert.
+ * @return the converted value.
*/
public static double swapDouble(final double value) {
return Double.longBitsToDouble(swapLong(Double.doubleToLongBits(value)));
@@ -273,8 +289,8 @@ public static double swapDouble(final double value) {
/**
* Converts a {@code float} value from big-endian to little-endian and vice versa.
*
- * @param value value to convert
- * @return the converted value
+ * @param value value to convert.
+ * @return the converted value.
*/
public static float swapFloat(final float value) {
return Float.intBitsToFloat(swapInteger(Float.floatToIntBits(value)));
@@ -283,8 +299,8 @@ public static float swapFloat(final float value) {
/**
* Converts an {@code int} value from big-endian to little-endian and vice versa.
*
- * @param value value to convert
- * @return the converted value
+ * @param value value to convert.
+ * @return the converted value.
*/
public static int swapInteger(final int value) {
return
@@ -297,8 +313,8 @@ public static int swapInteger(final int value) {
/**
* Converts a {@code long} value from big-endian to little-endian and vice versa.
*
- * @param value value to convert
- * @return the converted value
+ * @param value value to convert.
+ * @return the converted value.
*/
public static long swapLong(final long value) {
return
@@ -315,21 +331,23 @@ public static long swapLong(final long value) {
/**
* Converts a {@code short} value from big-endian to little-endian and vice versa.
*
- * @param value value to convert
- * @return the converted value
+ * @param value value to convert.
+ * @return the converted value.
*/
public static short swapShort(final short value) {
- return (short) (((value >> 0 & 0xff) << 8) +
- ((value >> 8 & 0xff) << 0));
+ return (short) (
+ ((value >> 0 & 0xff) << 8) +
+ ((value >> 8 & 0xff) << 0)
+ );
}
/**
* Validates if the provided byte array has enough data.
*
- * @param data the input byte array
- * @param offset the input offset
- * @param byteNeeded the needed number of bytes
- * @throws IllegalArgumentException if the byte array does not have enough data
+ * @param data the input byte array.
+ * @param offset the input offset.
+ * @param byteNeeded the needed number of bytes.
+ * @throws IllegalArgumentException if the byte array does not have enough data.
*/
private static void validateByteArrayOffset(final byte[] data, final int offset, final int byteNeeded) {
if (data.length < offset + byteNeeded) {
@@ -340,10 +358,10 @@ private static void validateByteArrayOffset(final byte[] data, final int offset,
/**
* Writes the 8 bytes of a {@code double} to a byte array at a given offset in little-endian order.
*
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes
+ * @param data target byte array.
+ * @param offset starting offset in the byte array.
+ * @param value value to write.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes.
*/
public static void writeSwappedDouble(final byte[] data, final int offset, final double value) {
writeSwappedLong(data, offset, Double.doubleToLongBits(value));
@@ -352,9 +370,9 @@ public static void writeSwappedDouble(final byte[] data, final int offset, final
/**
* Writes the 8 bytes of a {@code double} to an output stream in little-endian order.
*
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
+ * @param output target OutputStream.
+ * @param value value to write.
+ * @throws IOException in case of an I/O problem.
*/
public static void writeSwappedDouble(final OutputStream output, final double value) throws IOException {
writeSwappedLong(output, Double.doubleToLongBits(value));
@@ -363,10 +381,10 @@ public static void writeSwappedDouble(final OutputStream output, final double va
/**
* Writes the 4 bytes of a {@code float} to a byte array at a given offset in little-endian order.
*
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes
+ * @param data target byte array.
+ * @param offset starting offset in the byte array.
+ * @param value value to write.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes.
*/
public static void writeSwappedFloat(final byte[] data, final int offset, final float value) {
writeSwappedInteger(data, offset, Float.floatToIntBits(value));
@@ -375,9 +393,9 @@ public static void writeSwappedFloat(final byte[] data, final int offset, final
/**
* Writes the 4 bytes of a {@code float} to an output stream in little-endian order.
*
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
+ * @param output target OutputStream.
+ * @param value value to write.
+ * @throws IOException in case of an I/O problem.
*/
public static void writeSwappedFloat(final OutputStream output, final float value) throws IOException {
writeSwappedInteger(output, Float.floatToIntBits(value));
@@ -386,10 +404,10 @@ public static void writeSwappedFloat(final OutputStream output, final float valu
/**
* Writes the 4 bytes of an {@code int} to a byte array at a given offset in little-endian order.
*
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes
+ * @param data target byte array.
+ * @param offset starting offset in the byte array.
+ * @param value value to write.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes.
*/
public static void writeSwappedInteger(final byte[] data, final int offset, final int value) {
validateByteArrayOffset(data, offset, Integer.SIZE / Byte.SIZE);
@@ -402,9 +420,9 @@ public static void writeSwappedInteger(final byte[] data, final int offset, fina
/**
* Writes the 4 bytes of an {@code int} to an output stream in little-endian order.
*
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
+ * @param output target OutputStream.
+ * @param value value to write.
+ * @throws IOException in case of an I/O problem.
*/
public static void writeSwappedInteger(final OutputStream output, final int value) throws IOException {
output.write((byte) (value >> 0 & 0xff));
@@ -416,10 +434,10 @@ public static void writeSwappedInteger(final OutputStream output, final int valu
/**
* Writes the 8 bytes of a {@code long} to a byte array at a given offset in little-endian order.
*
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes
+ * @param data target byte array.
+ * @param offset starting offset in the byte array.
+ * @param value value to write.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes.
*/
public static void writeSwappedLong(final byte[] data, final int offset, final long value) {
validateByteArrayOffset(data, offset, Long.SIZE / Byte.SIZE);
@@ -436,9 +454,9 @@ public static void writeSwappedLong(final byte[] data, final int offset, final l
/**
* Writes the 8 bytes of a {@code long} to an output stream in little-endian order.
*
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
+ * @param output target OutputStream.
+ * @param value value to write.
+ * @throws IOException in case of an I/O problem.
*/
public static void writeSwappedLong(final OutputStream output, final long value) throws IOException {
output.write((byte) (value >> 0 & 0xff));
@@ -454,10 +472,10 @@ public static void writeSwappedLong(final OutputStream output, final long value)
/**
* Writes the 2 bytes of a {@code short} to a byte array at a given offset in little-endian order.
*
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes
+ * @param data target byte array.
+ * @param offset starting offset in the byte array.
+ * @param value value to write.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes.
*/
public static void writeSwappedShort(final byte[] data, final int offset, final short value) {
validateByteArrayOffset(data, offset, Short.SIZE / Byte.SIZE);
@@ -468,9 +486,9 @@ public static void writeSwappedShort(final byte[] data, final int offset, final
/**
* Writes the 2 bytes of a {@code short} to an output stream using little-endian encoding.
*
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
+ * @param output target OutputStream.
+ * @param value value to write.
+ * @throws IOException in case of an I/O problem.
*/
public static void writeSwappedShort(final OutputStream output, final short value) throws IOException {
output.write((byte) (value >> 0 & 0xff));
diff --git a/src/main/java/org/apache/commons/io/FileCleaner.java b/src/main/java/org/apache/commons/io/FileCleaner.java
index 5ffdd7db219..df9bc924f49 100644
--- a/src/main/java/org/apache/commons/io/FileCleaner.java
+++ b/src/main/java/org/apache/commons/io/FileCleaner.java
@@ -53,7 +53,7 @@ public class FileCleaner {
* loader it was started from terminates. This can constitute a memory leak.
*
* For example, suppose that you have developed a web application, which
- * contains the commons-io jar file in your WEB-INF/lib directory. In other
+ * contains the Commons IO jar file in your WEB-INF/lib directory. In other
* words, the FileCleaner class is loaded through the class loader of your
* web application. If the web application is terminated, but the servlet
* container is still running, then the file cleaner thread will still exist,
@@ -63,6 +63,7 @@ public class FileCleaner {
* in the resource cleanup code, such as
* {@code javax.servlet.ServletContextListener.contextDestroyed(javax.servlet.ServletContextEvent)}.
* One called, no new objects can be tracked by the file cleaner.
+ *
* @deprecated Use {@link FileCleaningTracker#exitWhenFinished()}.
*/
@Deprecated
@@ -76,7 +77,7 @@ public static synchronized void exitWhenFinished() {
* {@link FileCleaningTracker} class while maintain compatibility with the
* deprecated {@link FileCleaner}.
*
- * @return the singleton instance
+ * @return the singleton instance.
*/
public static FileCleaningTracker getInstance() {
return INSTANCE;
@@ -86,7 +87,7 @@ public static FileCleaningTracker getInstance() {
* Gets the number of files currently being tracked, and therefore
* awaiting deletion.
*
- * @return the number of files being tracked
+ * @return the number of files being tracked.
* @deprecated Use {@link FileCleaningTracker#getTrackCount()}.
*/
@Deprecated
@@ -99,9 +100,9 @@ public static int getTrackCount() {
* when the marker instance is garbage collected.
* The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @throws NullPointerException if the file is null.
* @deprecated Use {@link FileCleaningTracker#track(File, Object)}.
*/
@Deprecated
@@ -114,10 +115,10 @@ public static void track(final File file, final Object marker) {
* when the marker instance is garbage collected.
* The specified deletion strategy is used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @param deleteStrategy the strategy to delete the file, null means normal.
+ * @throws NullPointerException if the file is null.
* @deprecated Use {@link FileCleaningTracker#track(File, Object, FileDeleteStrategy)}.
*/
@Deprecated
@@ -130,9 +131,9 @@ public static void track(final File file, final Object marker, final FileDeleteS
* when the marker instance is garbage collected.
* The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
*
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the path is null
+ * @param path the full path to the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @throws NullPointerException if the path is null.
* @deprecated Use {@link FileCleaningTracker#track(String, Object)}.
*/
@Deprecated
@@ -145,10 +146,10 @@ public static void track(final String path, final Object marker) {
* when the marker instance is garbage collected.
* The specified deletion strategy is used.
*
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the path is null
+ * @param path the full path to the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @param deleteStrategy the strategy to delete the file, null means normal.
+ * @throws NullPointerException if the path is null.
* @deprecated Use {@link FileCleaningTracker#track(String, Object, FileDeleteStrategy)}.
*/
@Deprecated
diff --git a/src/main/java/org/apache/commons/io/FileCleaningTracker.java b/src/main/java/org/apache/commons/io/FileCleaningTracker.java
index 98edebc518e..be2746b66be 100644
--- a/src/main/java/org/apache/commons/io/FileCleaningTracker.java
+++ b/src/main/java/org/apache/commons/io/FileCleaningTracker.java
@@ -21,14 +21,14 @@
import java.lang.ref.ReferenceQueue;
import java.nio.file.Path;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
- * Keeps track of files awaiting deletion, and deletes them when an associated
+ * Tracks files awaiting deletion, and deletes them when an associated
* marker object is reclaimed by the garbage collector.
*
* This utility creates a background thread to handle file deletion.
@@ -51,9 +51,10 @@ public class FileCleaningTracker {
* The reaper thread.
*/
private final class Reaper extends Thread {
+
/** Constructs a new Reaper */
Reaper() {
- super("File Reaper");
+ super("commons-io-FileCleaningTracker-Reaper");
setPriority(MAX_PRIORITY);
setDaemon(true);
}
@@ -65,16 +66,18 @@ private final class Reaper extends Thread {
@Override
public void run() {
// thread exits when exitWhenFinished is true and there are no more tracked objects
- while (!exitWhenFinished || !trackers.isEmpty()) {
+ while (!(exitWhenFinished && trackers.isEmpty())) {
try {
// Wait for a tracker to remove.
- final Tracker tracker = (Tracker) q.remove(); // cannot return null
+ final Tracker tracker = (Tracker) refQueue.remove(); // cannot return null
trackers.remove(tracker);
if (!tracker.delete()) {
deleteFailures.add(tracker.getPath());
}
tracker.clear();
} catch (final InterruptedException e) {
+ // interrupted removing from the queue.
+ interrupt();
continue;
}
}
@@ -99,15 +102,14 @@ private static final class Tracker extends PhantomReference
*
* For example, suppose that you have developed a web application, which
- * contains the commons-io jar file in your WEB-INF/lib directory. In other
+ * contains the Commons IO JAR file in your WEB-INF/lib directory. In other
* words, the FileCleaner class is loaded through the class loader of your
* web application. If the web application is terminated, but the servlet
* container is still running, then the file cleaner thread will still exist,
* posing a memory leak.
+ *
*
* This method allows the thread to be terminated. Simply call this method
* in the resource cleanup code, such as
* {@code javax.servlet.ServletContextListener.contextDestroyed(javax.servlet.ServletContextEvent)}.
* Once called, no new objects can be tracked by the file cleaner.
+ *
*/
public synchronized void exitWhenFinished() {
- // synchronized block protects reaper
+ // synchronized method guards reaper
exitWhenFinished = true;
if (reaper != null) {
synchronized (reaper) {
@@ -218,7 +223,7 @@ public synchronized void exitWhenFinished() {
/**
* Gets a copy of the file paths that failed to delete.
*
- * @return a copy of the file paths that failed to delete
+ * @return a copy of the file paths that failed to delete.
* @since 2.0
*/
public List getDeleteFailures() {
@@ -229,7 +234,7 @@ public List getDeleteFailures() {
* Gets the number of files currently being tracked, and therefore
* awaiting deletion.
*
- * @return the number of files being tracked
+ * @return the number of files being tracked.
*/
public int getTrackCount() {
return trackers.size();
@@ -240,9 +245,9 @@ public int getTrackCount() {
* when the marker instance is garbage collected.
* The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @throws NullPointerException if the file is null.
*/
public void track(final File file, final Object marker) {
track(file, marker, null);
@@ -253,10 +258,10 @@ public void track(final File file, final Object marker) {
* when the marker instance is garbage collected.
* The specified deletion strategy is used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @param deleteStrategy the strategy to delete the file, null means normal.
+ * @throws NullPointerException if the file is null.
*/
public void track(final File file, final Object marker, final FileDeleteStrategy deleteStrategy) {
Objects.requireNonNull(file, "file");
@@ -268,9 +273,9 @@ public void track(final File file, final Object marker, final FileDeleteStrategy
* when the marker instance is garbage collected.
* The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @throws NullPointerException if the file is null.
* @since 2.14.0
*/
public void track(final Path file, final Object marker) {
@@ -282,10 +287,10 @@ public void track(final Path file, final Object marker) {
* when the marker instance is garbage collected.
* The specified deletion strategy is used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @param deleteStrategy the strategy to delete the file, null means normal.
+ * @throws NullPointerException if the file is null.
* @since 2.14.0
*/
public void track(final Path file, final Object marker, final FileDeleteStrategy deleteStrategy) {
@@ -298,9 +303,9 @@ public void track(final Path file, final Object marker, final FileDeleteStrategy
* when the marker instance is garbage collected.
* The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
*
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the path is null
+ * @param path the full path to the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @throws NullPointerException if the path is null.
*/
public void track(final String path, final Object marker) {
track(path, marker, null);
@@ -311,13 +316,12 @@ public void track(final String path, final Object marker) {
* when the marker instance is garbage collected.
* The specified deletion strategy is used.
*
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the path is null
+ * @param path the full path to the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @param deleteStrategy the strategy to delete the file, null means normal.
+ * @throws NullPointerException Thrown if the path is null.
*/
public void track(final String path, final Object marker, final FileDeleteStrategy deleteStrategy) {
- Objects.requireNonNull(path, "path");
addTracker(path, marker, deleteStrategy);
}
diff --git a/src/main/java/org/apache/commons/io/FileDeleteStrategy.java b/src/main/java/org/apache/commons/io/FileDeleteStrategy.java
index 62cf28c1631..a73ea719a75 100644
--- a/src/main/java/org/apache/commons/io/FileDeleteStrategy.java
+++ b/src/main/java/org/apache/commons/io/FileDeleteStrategy.java
@@ -37,7 +37,7 @@ public class FileDeleteStrategy {
/**
* Force file deletion strategy.
*/
- static class ForceFileDeleteStrategy extends FileDeleteStrategy {
+ static final class ForceFileDeleteStrategy extends FileDeleteStrategy {
/** Default Constructor */
ForceFileDeleteStrategy() {
@@ -51,10 +51,10 @@ static class ForceFileDeleteStrategy extends FileDeleteStrategy {
* if the file exists.
*
*
- * @param fileToDelete the file to delete, not null
+ * @param fileToDelete the file to delete, not null.
* @return Always returns {@code true}
- * @throws NullPointerException if the file is null
- * @throws IOException if an error occurs during file deletion
+ * @throws NullPointerException if the file is null.
+ * @throws IOException if an error occurs during file deletion.
*/
@Override
protected boolean doDelete(final File fileToDelete) throws IOException {
@@ -81,7 +81,7 @@ protected boolean doDelete(final File fileToDelete) throws IOException {
/**
* Restricted constructor.
*
- * @param name the name by which the strategy is known
+ * @param name the name by which the strategy is known.
*/
protected FileDeleteStrategy(final String name) {
this.name = name;
@@ -94,9 +94,9 @@ protected FileDeleteStrategy(final String name) {
* Subclass writers should override {@link #doDelete(File)}, not this method.
*
*
- * @param fileToDelete the file to delete, not null
- * @throws NullPointerException if the file is null
- * @throws IOException if an error occurs during file deletion
+ * @param fileToDelete the file to delete, not null.
+ * @throws NullPointerException if the file is null.
+ * @throws IOException if an error occurs during file deletion.
*/
public void delete(final File fileToDelete) throws IOException {
if (fileToDelete.exists() && !doDelete(fileToDelete)) {
@@ -112,8 +112,8 @@ public void delete(final File fileToDelete) throws IOException {
* Subclass writers should override {@link #doDelete(File)}, not this method.
*
*
- * @param fileToDelete the file to delete, null returns true
- * @return true if the file was deleted, or there was no such file
+ * @param fileToDelete the file to delete, null returns true.
+ * @return true if the file was deleted, or there was no such file.
*/
public boolean deleteQuietly(final File fileToDelete) {
if (fileToDelete == null || !fileToDelete.exists()) {
@@ -139,10 +139,10 @@ public boolean deleteQuietly(final File fileToDelete) {
* This implementation uses {@link FileUtils#delete(File)}.
*
*
- * @param file the file to delete, exists, not null
- * @return true if the file was deleted
- * @throws NullPointerException if the file is null
- * @throws IOException if an error occurs during file deletion
+ * @param file the file to delete, exists, not null.
+ * @return true if the file was deleted.
+ * @throws NullPointerException if the file is null.
+ * @throws IOException if an error occurs during file deletion.
*/
protected boolean doDelete(final File file) throws IOException {
FileUtils.delete(file);
@@ -152,7 +152,7 @@ protected boolean doDelete(final File file) throws IOException {
/**
* Gets a string describing the delete strategy.
*
- * @return a string describing the delete strategy
+ * @return a string describing the delete strategy.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/FileExistsException.java b/src/main/java/org/apache/commons/io/FileExistsException.java
index 1f733cf11ae..2028ddc5ebd 100644
--- a/src/main/java/org/apache/commons/io/FileExistsException.java
+++ b/src/main/java/org/apache/commons/io/FileExistsException.java
@@ -40,7 +40,7 @@ public FileExistsException() {
/**
* Constructs an instance with the specified file.
*
- * @param file The file that exists
+ * @param file The file that exists.
*/
public FileExistsException(final File file) {
super("File " + file + " exists");
@@ -49,7 +49,7 @@ public FileExistsException(final File file) {
/**
* Constructs an instance with the specified message.
*
- * @param message The error message
+ * @param message The error message.
*/
public FileExistsException(final String message) {
super(message);
diff --git a/src/main/java/org/apache/commons/io/FileSystem.java b/src/main/java/org/apache/commons/io/FileSystem.java
index 4169e1a53b1..11d3673f213 100644
--- a/src/main/java/org/apache/commons/io/FileSystem.java
+++ b/src/main/java/org/apache/commons/io/FileSystem.java
@@ -32,11 +32,10 @@
import java.util.Objects;
/**
- * Abstracts an OS' file system details, currently supporting the single use case of converting a file name String to a
- * legal file name with {@link #toLegalFileName(String, char)}.
+ * Enumerates file system details for operating systems, currently supporting the single use case of converting a file name String to a legal file name with
+ * {@link #toLegalFileName(String, char)}.
*
- * The starting point of any operation is {@link #getCurrent()} which gets you the enum for the file system that matches
- * the OS hosting the running JVM.
+ * The starting point of any operation is {@link #getCurrent()} which gets you the enum for the file system that matches the OS hosting the running JVM.
*
*
* @since 2.7
@@ -118,6 +117,7 @@ public enum FileSystem {
* Implementations measure length and can truncate to a specified limit.
*/
enum NameLengthStrategy {
+
/** Length measured as encoded bytes. */
BYTES {
@Override
@@ -266,7 +266,7 @@ final boolean isWithinLimit(final CharSequence value, final int limit, final Cha
/**
* Gets the current file system.
*
- * @return the current file system
+ * @return the current file system.
*/
private static FileSystem current() {
if (IS_OS_LINUX) {
@@ -284,7 +284,7 @@ private static FileSystem current() {
/**
* Gets the current file system.
*
- * @return the current file system
+ * @return the current file system.
*/
public static FileSystem getCurrent() {
return CURRENT;
@@ -294,8 +294,8 @@ public static FileSystem getCurrent() {
* Decides if the operating system matches.
*
* @param osNamePrefix
- * the prefix for the os name
- * @return true if matches, or false if not or can't determine
+ * the prefix for the operating system name.
+ * @return true if matches, or false if not or can't determine.
*/
private static boolean getOsMatchesName(final String osNamePrefix) {
return isOsNameMatch(getSystemProperty("os.name"), osNamePrefix);
@@ -309,8 +309,8 @@ private static boolean getOsMatchesName(final String osNamePrefix) {
*
*
* @param property
- * the system property name
- * @return the system property value or {@code null} if a security problem occurs
+ * the system property name.
+ * @return the system property value or {@code null} if a security problem occurs.
*/
private static String getSystemProperty(final String property) {
try {
@@ -345,10 +345,10 @@ private static int indexOfFirstDot(final CharSequence cs) {
*
*
* @param osName
- * the actual OS name
+ * the actual OS name.
* @param osNamePrefix
- * the prefix for the expected OS name
- * @return true if matches, or false if not or can't determine
+ * the prefix for the expected OS name.
+ * @return true if matches, or false if not or can't determine.
*/
private static boolean isOsNameMatch(final String osName, final String osNamePrefix) {
if (osName == null) {
diff --git a/src/main/java/org/apache/commons/io/FileSystemUtils.java b/src/main/java/org/apache/commons/io/FileSystemUtils.java
index 4c0af0d3671..7455dca8d09 100644
--- a/src/main/java/org/apache/commons/io/FileSystemUtils.java
+++ b/src/main/java/org/apache/commons/io/FileSystemUtils.java
@@ -53,12 +53,12 @@ public class FileSystemUtils {
* FileSystemUtils.freeSpace("/volume"); // *nix
*
*
- * @param path the path to get free space for, not null, not empty on Unix
- * @return the amount of free drive space on the drive or volume
+ * @param path the path to get free space for, not null, not empty on Unix.
+ * @return the amount of free drive space on the drive or volume.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
* @since 1.1, enhanced OS support in 1.2 and 1.3
- * @deprecated Use freeSpaceKb(String) Deprecated from 1.3, may be removed in 2.0
+ * @deprecated Use freeSpaceKb(String) Deprecated from 1.3, may be removed in 2.0.
*/
@Deprecated
public static long freeSpace(final String path) throws IOException {
@@ -75,7 +75,7 @@ public static long freeSpace(final String path) throws IOException {
* freeSpaceKb(FileUtils.current().getAbsolutePath())
*
*
- * @return the amount of free drive space on the drive or volume in kilobytes
+ * @return the amount of free drive space on the drive or volume in kilobytes.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
* @since 2.0
@@ -97,7 +97,7 @@ public static long freeSpaceKb() throws IOException {
*
*
* @param timeout ignored.
- * @return the amount of free drive space on the drive or volume in kilobytes
+ * @return the amount of free drive space on the drive or volume in kilobytes.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
* @since 2.0
@@ -116,8 +116,8 @@ public static long freeSpaceKb(final long timeout) throws IOException {
* FileSystemUtils.freeSpaceKb("/volume"); // *nix
*
*
- * @param path the path to get free space for, not null, not empty on Unix
- * @return the amount of free drive space on the drive or volume in kilobytes
+ * @param path the path to get free space for, not null, not empty on Unix.
+ * @return the amount of free drive space on the drive or volume in kilobytes.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
* @since 1.2, enhanced OS support in 1.3
@@ -136,9 +136,9 @@ public static long freeSpaceKb(final String path) throws IOException {
* FileSystemUtils.freeSpaceKb("/volume"); // *nix
*
*
- * @param path the path to get free space for, not null, not empty on Unix
+ * @param path the path to get free space for, not null, not empty on Unix.
* @param timeout ignored.
- * @return the amount of free drive space on the drive or volume in kilobytes
+ * @return the amount of free drive space on the drive or volume in kilobytes.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
* @since 2.0
@@ -157,8 +157,8 @@ public static long freeSpaceKb(final String path, final long timeout) throws IOE
* FileSystemUtils.freeSpace("/volume"); // *nix
*
*
- * @param pathStr the path to get free space for, not null, not empty on Unix
- * @return the amount of free drive space on the drive or volume
+ * @param pathStr the path to get free space for, not null, not empty on Unix.
+ * @return the amount of free drive space on the drive or volume.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
*/
diff --git a/src/main/java/org/apache/commons/io/FileUtils.java b/src/main/java/org/apache/commons/io/FileUtils.java
index 203fe84bfc5..11afd3f5d62 100644
--- a/src/main/java/org/apache/commons/io/FileUtils.java
+++ b/src/main/java/org/apache/commons/io/FileUtils.java
@@ -93,16 +93,16 @@
* Facilities are provided in the following areas:
*
* * Note that a specific charset should be specified whenever possible. Relying on the platform default means that the @@ -112,7 +112,7 @@ * {@link SecurityException} are not documented in the Javadoc. *
*- * Provenance: Excalibur, Alexandria, Commons-Utils + * Provenance: Excalibur, Alexandria, Commons-Utils. *
*/ public class FileUtils { @@ -230,8 +230,8 @@ public class FileUtils { * Similarly for the 1MB and 1KB boundaries. * * - * @param size the number of bytes - * @return a human-readable display value (includes units - QB, RB, YB, ZB, EB, PB, TB, GB, MB, KB or bytes) + * @param size the number of bytes. + * @return a human-readable display value (includes units - QB, RB, YB, ZB, EB, PB, TB, GB, MB, KB or bytes). * @throws NullPointerException if the given {@link BigInteger} is {@code null}. * @see IO-226 - should the rounding be changed? * @since 2.4 @@ -276,8 +276,8 @@ public static String byteCountToDisplaySize(final BigInteger size) { * Similarly for the 1MB and 1KB boundaries. * * - * @param size the number of bytes - * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes) + * @param size the number of bytes. + * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes). * @see IO-226 - should the rounding be changed? */ // See https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed? @@ -295,8 +295,8 @@ public static String byteCountToDisplaySize(final long size) { * Similarly for the 1MB and 1KB boundaries. * * - * @param size the number of bytes - * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes) + * @param size the number of bytes. + * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes). * @see IO-226 - should the rounding be changed? * @since 2.12.0 */ @@ -357,11 +357,11 @@ private static File checkIsFile(final File file, final String name) { * * @param file the file to checksum, must not be {@code null} * @param checksum the checksum object to be used, must not be {@code null} - * @return the checksum specified, updated with the content of the file + * @return the checksum specified, updated with the content of the file. * @throws NullPointerException if the given {@link File} is {@code null}. * @throws NullPointerException if the given {@link Checksum} is {@code null}. * @throws IllegalArgumentException if the given {@link File} is not a file. - * @throws FileNotFoundException if the file does not exist + * @throws FileNotFoundException if the file does not exist. * @throws IOException if an IO error occurs reading the file. * @since 1.3 */ @@ -379,7 +379,7 @@ public static Checksum checksum(final File file, final Checksum checksum) throws * The value of the checksum is returned. * * @param file the file to checksum, must not be {@code null} - * @return the checksum value + * @return the checksum value. * @throws NullPointerException if the {@code file} is {@code null}. * @throws IllegalArgumentException if the {@code file} does not exist or is not a file. * @throws IOException if an IO error occurs reading the file. @@ -392,7 +392,7 @@ public static long checksumCRC32(final File file) throws IOException { /** * Cleans a directory without deleting it. * - * @param directory directory to clean + * @param directory directory to clean. * @throws NullPointerException if the given {@link File} is {@code null}. * @throws IllegalArgumentException if the {@code directory} does not exist or is not a directory. * @throws IOException if an I/O error occurs. @@ -422,9 +422,9 @@ private static void cleanDirectoryOnExit(final File directory) throws IOExceptio * resorting to byte-by-byte comparison of the contents. * * - * @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 + * @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 PathUtils#fileContentEquals(Path,Path) @@ -464,12 +464,12 @@ public static boolean contentEquals(final File file1, final File file2) throws I * before resorting to line-by-line comparison of the contents. * * - * @param file1 the first file - * @param file2 the second file + * @param file1 the first file. + * @param file2 the second file. * @param charsetName the name of the requested charset. - * May be null, in which case the platform default is used + * May be null, in which case the platform default is used. * @return true if the content of the files are equal or neither exists, - * false otherwise + * false otherwise. * @throws IllegalArgumentException when an input is not a file. * @throws IOException in case of an I/O error. * @throws UnsupportedCharsetException If the named charset is unavailable (unchecked exception). @@ -509,7 +509,7 @@ public static boolean contentEqualsIgnoreEOL(final File file1, final File file2, * representation. This is to account for the difference between * File.listFiles() and FileUtils.listFiles(). * - * @param files a Collection containing {@link File} instances + * @param files a Collection containing {@link File} instances. * @return an array of {@link File} */ public static File[] convertFileCollectionToFileArray(final Collection+ * WARNING: This method reads the Java system property {@code 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 library methods in classes such as {@link File}. + *
* - * @return the path to the system temporary directory as a String + * @return the path to the system temporary directory as a String. * @since 2.0 */ public static String getTempDirectoryPath() { @@ -1565,7 +1564,7 @@ public static String getTempDirectoryPath() { } /** - * Gets a {@link File} representing the user's home directory. + * Gets a {@link File} representing the user's home directory based on the Java system property {@code user.home}. * * @return the user's home directory. * @since 2.0 @@ -1575,7 +1574,7 @@ public static File getUserDirectory() { } /** - * Gets the path to the user's home directory. + * Gets the path to the user's home directory based on the Java system property {@code user.home}. * * @return the path to the user's home directory. * @since 2.0 @@ -1589,7 +1588,7 @@ public static String getUserDirectoryPath() { * null-safe delegate to {@link Files#isDirectory(Path path, LinkOption... options)}. * * @param file the path to the file. - * @param options options indicating how symbolic links are handled + * @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. @@ -1632,7 +1631,7 @@ public static boolean isEmptyDirectory(final File directory) throws IOException * @param chronoLocalDate the date reference. * @return true if the {@link File} exists and has been modified after the given * {@link ChronoLocalDate} at the current time. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @throws NullPointerException if the file or local date is {@code null}. * @since 2.8.0 */ @@ -1656,7 +1655,7 @@ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoL * @param localTime the time reference. * @return true if the {@link File} exists and has been modified after the given * {@link ChronoLocalDate} at the given time. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @throws NullPointerException if the file, local date or zone ID is {@code null}. * @since 2.8.0 */ @@ -1670,13 +1669,13 @@ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoL * Tests if the specified {@link File} is newer than the specified {@link ChronoLocalDate} at the specified * {@link OffsetTime}. * - * @param file the {@link File} of which the modification date must be compared - * @param chronoLocalDate the date reference - * @param offsetTime the time reference + * @param file the {@link File} of which the modification date must be compared. + * @param chronoLocalDate the date reference. + * @param offsetTime the time reference. * @return true if the {@link File} exists and has been modified after the given {@link ChronoLocalDate} at the given * {@link OffsetTime}. - * @throws UncheckedIOException if an I/O error occurs - * @throws NullPointerException if the file, local date or zone ID is {@code null} + * @throws UncheckedIOException if an I/O error occurs. + * @throws NullPointerException if the file, local date or zone ID is {@code null}. * @since 2.12.0 */ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoLocalDate, final OffsetTime offsetTime) { @@ -1700,7 +1699,7 @@ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoL * @param chronoLocalDateTime the date reference. * @return true if the {@link File} exists and has been modified after the given * {@link ChronoLocalDateTime} at the system-default time zone. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @throws NullPointerException if the file or local date time is {@code null}. * @since 2.8.0 */ @@ -1717,7 +1716,7 @@ public static boolean isFileNewer(final File file, final ChronoLocalDateTime> * @param zoneId the time zone. * @return true if the {@link File} exists and has been modified after the given * {@link ChronoLocalDateTime} at the given {@link ZoneId}. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @throws NullPointerException if the file, local date time or zone ID is {@code null}. * @since 2.8.0 */ @@ -1735,7 +1734,7 @@ public static boolean isFileNewer(final File file, final ChronoLocalDateTime> * @return true if the {@link File} exists and has been modified after the given * {@link ChronoZonedDateTime}. * @throws NullPointerException if the file or zoned date time is {@code null}. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @since 2.8.0 */ public static boolean isFileNewer(final File file, final ChronoZonedDateTime> chronoZonedDateTime) { @@ -1751,7 +1750,7 @@ public static boolean isFileNewer(final File file, final ChronoZonedDateTime> * @param date the date reference. * @return true if the {@link File} exists and has been modified * after the given {@link Date}. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @throws NullPointerException if the file or date is {@code null}. */ public static boolean isFileNewer(final File file, final Date date) { @@ -1795,7 +1794,7 @@ public static boolean isFileNewer(final File file, final FileTime fileTime) thro * @param instant the date reference. * @return true if the {@link File} exists and has been modified after the given {@link Instant}. * @throws NullPointerException if the file or instant is {@code null}. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @since 2.8.0 */ public static boolean isFileNewer(final File file, final Instant instant) { @@ -1810,7 +1809,7 @@ public static boolean isFileNewer(final File file, final Instant instant) { * @param timeMillis the time reference measured in milliseconds since the * epoch (00:00:00 GMT, January 1, 1970). * @return true if the {@link File} exists and has been modified after the given time reference. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @throws NullPointerException if the file is {@code null}. */ public static boolean isFileNewer(final File file, final long timeMillis) { @@ -1821,11 +1820,11 @@ public static boolean isFileNewer(final File file, final long timeMillis) { /** * Tests if the specified {@link File} is newer than the specified {@link OffsetDateTime}. * - * @param file the {@link File} of which the modification date must be compared - * @param offsetDateTime the date reference + * @param file the {@link File} of which the modification date must be compared. + * @param offsetDateTime the date reference. * @return true if the {@link File} exists and has been modified before the given {@link OffsetDateTime}. - * @throws UncheckedIOException if an I/O error occurs - * @throws NullPointerException if the file or zoned date time is {@code null} + * @throws UncheckedIOException if an I/O error occurs. + * @throws NullPointerException if the file or zoned date time is {@code null}. * @since 2.12.0 */ public static boolean isFileNewer(final File file, final OffsetDateTime offsetDateTime) { @@ -1850,7 +1849,7 @@ public static boolean isFileNewer(final File file, final OffsetDateTime offsetDa * @return true if the {@link File} exists and has been modified before the given * {@link ChronoLocalDate} at the current time. * @throws NullPointerException if the file or local date is {@code null}. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @see ZoneId#systemDefault() * @see LocalTime#now() * @since 2.8.0 @@ -1875,7 +1874,7 @@ public static boolean isFileOlder(final File file, final ChronoLocalDate chronoL * @param localTime the time reference. * @return true if the {@link File} exists and has been modified before the * given {@link ChronoLocalDate} at the specified time. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @throws NullPointerException if the file, local date or local time is {@code null}. * @see ZoneId#systemDefault() * @since 2.8.0 @@ -1890,13 +1889,13 @@ public static boolean isFileOlder(final File file, final ChronoLocalDate chronoL * Tests if the specified {@link File} is older than the specified {@link ChronoLocalDate} at the specified * {@link OffsetTime}. * - * @param file the {@link File} of which the modification date must be compared - * @param chronoLocalDate the date reference - * @param offsetTime the time reference + * @param file the {@link File} of which the modification date must be compared. + * @param chronoLocalDate the date reference. + * @param offsetTime the time reference. * @return true if the {@link File} exists and has been modified after the given {@link ChronoLocalDate} at the given * {@link OffsetTime}. - * @throws NullPointerException if the file, local date or zone ID is {@code null} - * @throws UncheckedIOException if an I/O error occurs + * @throws NullPointerException if the file, local date or zone ID is {@code null}. + * @throws UncheckedIOException if an I/O error occurs. * @since 2.12.0 */ public static boolean isFileOlder(final File file, final ChronoLocalDate chronoLocalDate, final OffsetTime offsetTime) { @@ -1921,7 +1920,7 @@ public static boolean isFileOlder(final File file, final ChronoLocalDate chronoL * @return true if the {@link File} exists and has been modified before the given * {@link ChronoLocalDateTime} at the system-default time zone. * @throws NullPointerException if the file or local date time is {@code null}. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @see ZoneId#systemDefault() * @since 2.8.0 */ @@ -1939,7 +1938,7 @@ public static boolean isFileOlder(final File file, final ChronoLocalDateTime> * @return true if the {@link File} exists and has been modified before the given * {@link ChronoLocalDateTime} at the given {@link ZoneId}. * @throws NullPointerException if the file, local date time or zone ID is {@code null}. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @since 2.8.0 */ public static boolean isFileOlder(final File file, final ChronoLocalDateTime> chronoLocalDateTime, final ZoneId zoneId) { @@ -1956,7 +1955,7 @@ public static boolean isFileOlder(final File file, final ChronoLocalDateTime> * @return true if the {@link File} exists and has been modified before the given * {@link ChronoZonedDateTime}. * @throws NullPointerException if the file or zoned date time is {@code null}. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. * @since 2.8.0 */ public static boolean isFileOlder(final File file, final ChronoZonedDateTime> chronoZonedDateTime) { @@ -1971,7 +1970,7 @@ public static boolean isFileOlder(final File file, final ChronoZonedDateTime> * @param date the date reference. * @return true if the {@link File} exists and has been modified before the given {@link Date}. * @throws NullPointerException if the file or date is {@code null}. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. */ public static boolean isFileOlder(final File file, final Date date) { Objects.requireNonNull(date, "date"); @@ -1986,7 +1985,7 @@ public static boolean isFileOlder(final File file, final Date date) { * @return true if the {@link File} exists and has been modified before the reference {@link File}. * @throws NullPointerException if the file or reference file is {@code null}. * @throws FileNotFoundException if the reference file doesn't exist. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. */ public static boolean isFileOlder(final File file, final File reference) throws FileNotFoundException { return Uncheck.getAsBoolean(() -> PathUtils.isOlder(file.toPath(), reference.toPath())); @@ -2029,7 +2028,7 @@ public static boolean isFileOlder(final File file, final Instant instant) { * epoch (00:00:00 GMT, January 1, 1970). * @return true if the {@link File} exists and has been modified before the given time reference. * @throws NullPointerException if the file is {@code null}. - * @throws UncheckedIOException if an I/O error occurs + * @throws UncheckedIOException if an I/O error occurs. */ public static boolean isFileOlder(final File file, final long timeMillis) { Objects.requireNonNull(file, PROTOCOL_FILE); @@ -2039,8 +2038,8 @@ public static boolean isFileOlder(final File file, final long timeMillis) { /** * Tests if the specified {@link File} is older than the specified {@link OffsetDateTime}. * - * @param file the {@link File} of which the modification date must be compared - * @param offsetDateTime the date reference + * @param file the {@link File} of which the modification date must be compared. + * @param offsetDateTime the date reference. * @return true if the {@link File} exists and has been modified before the given {@link OffsetDateTime}. * @throws NullPointerException if the file or zoned date time is {@code null} * @since 2.12.0 @@ -2065,7 +2064,7 @@ private static boolean isFileProtocol(final URL url) { * null-safe delegate to {@link Files#isRegularFile(Path path, LinkOption... options)}. * * @param file the path to the file. - * @param options options indicating how symbolic links are handled + * @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 regular file, or it cannot * be determined if the file is a regular file or not. @@ -2290,7 +2289,7 @@ public static LineIterator lineIterator(final File file, final String charsetNam inputStream = Files.newInputStream(file.toPath()); return IOUtils.lineIterator(inputStream, charsetName); } catch (final IOException | RuntimeException ex) { - IOUtils.closeQuietly(inputStream, ex::addSuppressed); + IOUtils.closeQuietlySuppress(inputStream, ex); throw ex; } } @@ -2693,9 +2692,9 @@ public static FileInputStream openInputStream(final File file) throws IOExceptio * * * @param file the file to open for output, must not be {@code null}. - * @return a new {@link FileOutputStream} for the specified file + * @return a new {@link FileOutputStream} for the specified file. * @throws NullPointerException if the file object is {@code null}. - * @throws IllegalArgumentException if the file object is a directory + * @throws IllegalArgumentException if the file object is a directory. * @throws IllegalArgumentException if the file is not writable. * @throws IOException if the directories could not be created. * @since 1.3 @@ -2755,7 +2754,7 @@ public static byte[] readFileToByteArray(final File file) throws IOException { } /** - * Reads the contents of a file into a String using the virtual machine's {@link Charset#defaultCharset() default charset}. The + * Reads the contents of a file into a String using the virtual machine's {@linkplain Charset#defaultCharset() default charset}. The * file is always closed. * * @param file the file to read, must not be {@code null}. @@ -2804,7 +2803,7 @@ public static String readFileToString(final File file, final String charsetName) } /** - * Reads the contents of a file line by line to a List of Strings using the virtual machine's {@link Charset#defaultCharset() default charset}. + * Reads the contents of a file line by line to a List of Strings using the virtual machine's {@linkplain Charset#defaultCharset() default charset}. * The file is always closed. * * @param file the file to read, must not be {@code null}. @@ -3212,7 +3211,7 @@ public static boolean waitFor(final File file, final int seconds) { } /** - * Writes a CharSequence to a file creating the file if it does not exist using the virtual machine's {@link Charset#defaultCharset() default charset}. + * Writes a CharSequence to a file creating the file if it does not exist using the virtual machine's {@linkplain Charset#defaultCharset() default charset}. * * @param file the file to write. * @param data the content to write to the file. @@ -3226,7 +3225,7 @@ public static void write(final File file, final CharSequence data) throws IOExce } /** - * Writes a CharSequence to a file creating the file if it does not exist using the virtual machine's {@link Charset#defaultCharset() default charset}. + * Writes a CharSequence to a file creating the file if it does not exist using the virtual machine's {@linkplain Charset#defaultCharset() default charset}. * * @param file the file to write. * @param data the content to write to the file. @@ -3271,11 +3270,11 @@ public static void write(final File file, final CharSequence data, final Charset /** * Writes a CharSequence to a file creating the file if it does not exist. * - * @param file the file to write - * @param data the content to write to the file - * @param charsetName the name of the requested charset, {@code null} means platform default - * @throws IOException in case of an I/O error - * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM + * @param file the file to write. + * @param data the content to write to the file. + * @param charsetName the name of the requested charset, {@code null} means platform default. + * @throws IOException in case of an I/O error. + * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM. * @since 2.0 */ public static void write(final File file, final CharSequence data, final String charsetName) throws IOException { @@ -3285,13 +3284,13 @@ public static void write(final File file, final CharSequence data, final String /** * Writes a CharSequence to a file creating the file if it does not exist. * - * @param file the file to write - * @param data the content to write to the file - * @param charsetName the name of the requested charset, {@code null} means platform default + * @param file the file to write. + * @param data the content to write to the file. + * @param charsetName the name of the requested charset, {@code null} means platform default. * @param append if {@code true}, then the data will be added to the - * end of the file rather than overwriting - * @throws IOException in case of an I/O error - * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported by the VM + * end of the file rather than overwriting. + * @throws IOException in case of an I/O error. + * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported by the VM. * @since 2.1 */ public static void write(final File file, final CharSequence data, final String charsetName, final boolean append) throws IOException { @@ -3304,9 +3303,9 @@ public static void write(final File file, final CharSequence data, final String * Writes a byte array to a file creating the file if it does not exist. * The parent directories of the file will be created if they do not exist. * - * @param file the file to write to - * @param data the content to write to the file - * @throws IOException in case of an I/O error + * @param file the file to write to. + * @param data the content to write to the file. + * @throws IOException in case of an I/O error. * @since 1.1 */ public static void writeByteArrayToFile(final File file, final byte[] data) throws IOException { @@ -3316,11 +3315,11 @@ public static void writeByteArrayToFile(final File file, final byte[] data) thro /** * Writes a byte array to a file creating the file if it does not exist. * - * @param file the file to write to - * @param data the content to write to the file + * @param file the file to write to. + * @param data the content to write to the file. * @param append if {@code true}, then bytes will be added to the - * end of the file rather than overwriting - * @throws IOException in case of an I/O error + * end of the file rather than overwriting. + * @throws IOException in case of an I/O error. * @since 2.1 */ public static void writeByteArrayToFile(final File file, final byte[] data, final boolean append) throws IOException { @@ -3332,11 +3331,11 @@ public static void writeByteArrayToFile(final File file, final byte[] data, fina * at offset {@code off} to a file, creating the file if it does * not exist. * - * @param file the file to write to - * @param data the content to write to the file - * @param off the start offset in the data - * @param len the number of bytes to write - * @throws IOException in case of an I/O error + * @param file the file to write to. + * @param data the content to write to the file. + * @param off the start offset in the data. + * @param len the number of bytes to write. + * @throws IOException in case of an I/O error. * @since 2.5 */ public static void writeByteArrayToFile(final File file, final byte[] data, final int off, final int len) throws IOException { @@ -3348,13 +3347,13 @@ public static void writeByteArrayToFile(final File file, final byte[] data, fina * at offset {@code off} to a file, creating the file if it does * not exist. * - * @param file the file to write to - * @param data the content to write to the file - * @param off the start offset in the data - * @param len the number of bytes to write + * @param file the file to write to. + * @param data the content to write to the file. + * @param off the start offset in the data. + * @param len the number of bytes to write. * @param append if {@code true}, then bytes will be added to the - * end of the file rather than overwriting - * @throws IOException in case of an I/O error + * end of the file rather than overwriting. + * @throws IOException in case of an I/O error. * @since 2.5 */ public static void writeByteArrayToFile(final File file, final byte[] data, final int off, final int len, final boolean append) throws IOException { @@ -3368,9 +3367,9 @@ public static void writeByteArrayToFile(final File file, final byte[] data, fina * the specified {@link File} line by line. * The default VM encoding and the default line ending will be used. * - * @param file the file to write to - * @param lines the lines to write, {@code null} entries produce blank lines - * @throws IOException in case of an I/O error + * @param file the file to write to. + * @param lines the lines to write, {@code null} entries produce blank lines. + * @throws IOException in case of an I/O error. * @since 1.3 */ public static void writeLines(final File file, final Collection> lines) throws IOException { @@ -3382,11 +3381,11 @@ public static void writeLines(final File file, final Collection> lines) throws * the specified {@link File} line by line. * The default VM encoding and the default line ending will be used. * - * @param file the file to write to - * @param lines the lines to write, {@code null} entries produce blank lines + * @param file the file to write to. + * @param lines the lines to write, {@code null} entries produce blank lines. * @param append if {@code true}, then the lines will be added to the - * end of the file rather than overwriting - * @throws IOException in case of an I/O error + * end of the file rather than overwriting. + * @throws IOException in case of an I/O error. * @since 2.1 */ public static void writeLines(final File file, final Collection> lines, final boolean append) throws IOException { @@ -3398,10 +3397,10 @@ public static void writeLines(final File file, final Collection> lines, final * the specified {@link File} line by line. * The default VM encoding and the specified line ending will be used. * - * @param file the file to write to - * @param lines the lines to write, {@code null} entries produce blank lines - * @param lineEnding the line separator to use, {@code null} is system default - * @throws IOException in case of an I/O error + * @param file the file to write to. + * @param lines the lines to write, {@code null} entries produce blank lines. + * @param lineEnding the line separator to use, {@code null} is system default. + * @throws IOException in case of an I/O error. * @since 1.3 */ public static void writeLines(final File file, final Collection> lines, final String lineEnding) throws IOException { @@ -3413,12 +3412,12 @@ public static void writeLines(final File file, final Collection> lines, final * the specified {@link File} line by line. * The default VM encoding and the specified line ending will be used. * - * @param file the file to write to - * @param lines the lines to write, {@code null} entries produce blank lines - * @param lineEnding the line separator to use, {@code null} is system default + * @param file the file to write to. + * @param lines the lines to write, {@code null} entries produce blank lines. + * @param lineEnding the line separator to use, {@code null} is system default. * @param append if {@code true}, then the lines will be added to the - * end of the file rather than overwriting - * @throws IOException in case of an I/O error + * end of the file rather than overwriting. + * @throws IOException in case of an I/O error. * @since 2.1 */ public static void writeLines(final File file, final Collection> lines, final String lineEnding, final boolean append) throws IOException { @@ -3431,11 +3430,11 @@ public static void writeLines(final File file, final Collection> lines, final * The specified character encoding and the default line ending will be used. * The parent directories of the file will be created if they do not exist. * - * @param file the file to write to - * @param charsetName the name of the requested charset, {@code null} means platform default - * @param lines the lines to write, {@code null} entries produce blank lines - * @throws IOException in case of an I/O error - * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM + * @param file the file to write to. + * @param charsetName the name of the requested charset, {@code null} means platform default. + * @param lines the lines to write, {@code null} entries produce blank lines. + * @throws IOException in case of an I/O error. + * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM. * @since 1.1 */ public static void writeLines(final File file, final String charsetName, final Collection> lines) throws IOException { @@ -3447,13 +3446,13 @@ public static void writeLines(final File file, final String charsetName, final C * the specified {@link File} line by line, optionally appending. * The specified character encoding and the default line ending will be used. * - * @param file the file to write to - * @param charsetName the name of the requested charset, {@code null} means platform default - * @param lines the lines to write, {@code null} entries produce blank lines + * @param file the file to write to. + * @param charsetName the name of the requested charset, {@code null} means platform default. + * @param lines the lines to write, {@code null} entries produce blank lines. * @param append if {@code true}, then the lines will be added to the - * end of the file rather than overwriting - * @throws IOException in case of an I/O error - * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM + * end of the file rather than overwriting. + * @throws IOException in case of an I/O error. + * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM. * @since 2.1 */ public static void writeLines(final File file, final String charsetName, final Collection> lines, final boolean append) throws IOException { @@ -3466,12 +3465,12 @@ public static void writeLines(final File file, final String charsetName, final C * The specified character encoding and the line ending will be used. * The parent directories of the file will be created if they do not exist. * - * @param file the file to write to - * @param charsetName the name of the requested charset, {@code null} means platform default - * @param lines the lines to write, {@code null} entries produce blank lines - * @param lineEnding the line separator to use, {@code null} is system default - * @throws IOException in case of an I/O error - * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM + * @param file the file to write to. + * @param charsetName the name of the requested charset, {@code null} means platform default. + * @param lines the lines to write, {@code null} entries produce blank lines. + * @param lineEnding the line separator to use, {@code null} is system default. + * @throws IOException in case of an I/O error. + * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM. * @since 1.1 */ public static void writeLines(final File file, final String charsetName, final Collection> lines, final String lineEnding) throws IOException { @@ -3483,14 +3482,14 @@ public static void writeLines(final File file, final String charsetName, final C * the specified {@link File} line by line. * The specified character encoding and the line ending will be used. * - * @param file the file to write to - * @param charsetName the name of the requested charset, {@code null} means platform default - * @param lines the lines to write, {@code null} entries produce blank lines - * @param lineEnding the line separator to use, {@code null} is system default + * @param file the file to write to. + * @param charsetName the name of the requested charset, {@code null} means platform default. + * @param lines the lines to write, {@code null} entries produce blank lines. + * @param lineEnding the line separator to use, {@code null} is system default. * @param append if {@code true}, then the lines will be added to the - * end of the file rather than overwriting - * @throws IOException in case of an I/O error - * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM + * end of the file rather than overwriting. + * @throws IOException in case of an I/O error. + * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM. * @since 2.1 */ public static void writeLines(final File file, final String charsetName, final Collection> lines, final String lineEnding, final boolean append) @@ -3501,12 +3500,12 @@ public static void writeLines(final File file, final String charsetName, final C } /** - * Writes a String to a file creating the file if it does not exist using the virtual machine's {@link Charset#defaultCharset() default charset}. + * Writes a String to a file creating the file if it does not exist using the virtual machine's {@linkplain Charset#defaultCharset() default charset}. * - * @param file the file to write - * @param data the content to write to the file - * @throws IOException in case of an I/O error - * @deprecated Use {@link #writeStringToFile(File, String, Charset)} instead (and specify the appropriate encoding) + * @param file the file to write. + * @param data the content to write to the file. + * @throws IOException in case of an I/O error. + * @deprecated Use {@link #writeStringToFile(File, String, Charset)} instead (and specify the appropriate encoding). */ @Deprecated public static void writeStringToFile(final File file, final String data) throws IOException { @@ -3514,14 +3513,14 @@ public static void writeStringToFile(final File file, final String data) throws } /** - * Writes a String to a file creating the file if it does not exist using the virtual machine's {@link Charset#defaultCharset() default charset}. + * Writes a String to a file creating the file if it does not exist using the virtual machine's {@linkplain Charset#defaultCharset() default charset}. * - * @param file the file to write - * @param data the content to write to the file - * @param append if {@code true}, then the String will be added to the end of the file rather than overwriting - * @throws IOException in case of an I/O error + * @param file the file to write. + * @param data the content to write to the file. + * @param append if {@code true}, then the String will be added to the end of the file rather than overwriting. + * @throws IOException in case of an I/O error. * @since 2.1 - * @deprecated Use {@link #writeStringToFile(File, String, Charset, boolean)} instead (and specify the appropriate encoding) + * @deprecated Use {@link #writeStringToFile(File, String, Charset, boolean)} instead (and specify the appropriate encoding). */ @Deprecated public static void writeStringToFile(final File file, final String data, final boolean append) throws IOException { @@ -3532,11 +3531,11 @@ public static void writeStringToFile(final File file, final String data, final b * Writes a String to a file creating the file if it does not exist. * The parent directories of the file will be created if they do not exist. * - * @param file the file to write - * @param data the content to write to the file - * @param charset the charset to use, {@code null} means platform default - * @throws IOException in case of an I/O error - * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM + * @param file the file to write. + * @param data the content to write to the file. + * @param charset the charset to use, {@code null} means platform default. + * @throws IOException in case of an I/O error. + * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM. * @since 2.4 */ public static void writeStringToFile(final File file, final String data, final Charset charset) throws IOException { @@ -3547,12 +3546,12 @@ public static void writeStringToFile(final File file, final String data, final C * Writes a String to a file, creating the file if it does not exist. * The parent directories of the file are created if they do not exist. * - * @param file the file to write - * @param data the content to write to the file - * @param charset the charset to use, {@code null} means platform default + * @param file the file to write. + * @param data the content to write to the file. + * @param charset the charset to use, {@code null} means platform default. * @param append if {@code true}, then the String will be added to the - * end of the file rather than overwriting - * @throws IOException in case of an I/O error + * end of the file rather than overwriting. + * @throws IOException in case of an I/O error. * @since 2.3 */ public static void writeStringToFile(final File file, final String data, final Charset charset, final boolean append) throws IOException { @@ -3565,11 +3564,11 @@ public static void writeStringToFile(final File file, final String data, final C * Writes a String to a file, creating the file if it does not exist. * The parent directories of the file are created if they do not exist. * - * @param file the file to write - * @param data the content to write to the file - * @param charsetName the name of the requested charset, {@code null} means platform default - * @throws IOException in case of an I/O error - * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM + * @param file the file to write. + * @param data the content to write to the file. + * @param charsetName the name of the requested charset, {@code null} means platform default. + * @throws IOException in case of an I/O error. + * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM. */ public static void writeStringToFile(final File file, final String data, final String charsetName) throws IOException { writeStringToFile(file, data, charsetName, false); @@ -3579,13 +3578,13 @@ public static void writeStringToFile(final File file, final String data, final S * Writes a String to a file, creating the file if it does not exist. * The parent directories of the file are created if they do not exist. * - * @param file the file to write - * @param data the content to write to the file - * @param charsetName the name of the requested charset, {@code null} means platform default + * @param file the file to write. + * @param data the content to write to the file. + * @param charsetName the name of the requested charset, {@code null} means platform default. * @param append if {@code true}, then the String will be added to the - * end of the file rather than overwriting - * @throws IOException in case of an I/O error - * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported by the VM + * end of the file rather than overwriting. + * @throws IOException in case of an I/O error. + * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported by the VM. * @since 2.1 */ public static void writeStringToFile(final File file, final String data, final String charsetName, final boolean append) throws IOException { diff --git a/src/main/java/org/apache/commons/io/FilenameUtils.java b/src/main/java/org/apache/commons/io/FilenameUtils.java index ec836e29421..3c8ca2f8373 100644 --- a/src/main/java/org/apache/commons/io/FilenameUtils.java +++ b/src/main/java/org/apache/commons/io/FilenameUtils.java @@ -143,12 +143,14 @@ public class FilenameUtils { /** * The extension separator character. + * * @since 1.4 */ public static final char EXTENSION_SEPARATOR = '.'; /** * The extension separator String. + * * @since 1.4 */ public static final String EXTENSION_SEPARATOR_STR = Character.toString(EXTENSION_SEPARATOR); @@ -231,10 +233,10 @@ public class FilenameUtils { * use {@link #getFullPath(String)} on the base path argument. * * - * @param basePath the base path to attach to, always treated as a path - * @param fullFileNameToAdd the file name (or path) to attach to the base - * @return the concatenated path, or null if invalid - * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) + * @param basePath the base path to attach to, always treated as a path. + * @param fullFileNameToAdd the file name (or path) to attach to the base. + * @return the concatenated path, or null if invalid. + * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}). */ public static String concat(final String basePath, final String fullFileNameToAdd) { final int prefix = getPrefixLength(fullFileNameToAdd); @@ -280,29 +282,23 @@ public static String concat(final String basePath, final String fullFileNameToAd * @see FileUtils#directoryContains(File, File) */ public static boolean directoryContains(final String canonicalParent, final String canonicalChild) { - if (isEmpty(canonicalParent) || isEmpty(canonicalChild)) { - return false; - } - - if (IOCase.SYSTEM.checkEquals(canonicalParent, canonicalChild)) { + if (isEmpty(canonicalParent) || isEmpty(canonicalChild) || IOCase.SYSTEM.checkEquals(canonicalParent, canonicalChild)) { return false; } - final char separator = toSeparator(canonicalParent.charAt(0) == UNIX_NAME_SEPARATOR); final String parentWithEndSeparator = canonicalParent.charAt(canonicalParent.length() - 1) == separator ? canonicalParent : canonicalParent + separator; - return IOCase.SYSTEM.checkStartsWith(canonicalChild, parentWithEndSeparator); } /** * Does the work of getting the path. * - * @param fileName the file name - * @param includeSeparator true to include the end separator - * @return the path - * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) + * @param fileName the file name. + * @param includeEndSeparator true to include the end separator. + * @return the path. + * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}). */ - private static String doGetFullPath(final String fileName, final boolean includeSeparator) { + private static String doGetFullPath(final String fileName, final boolean includeEndSeparator) { if (fileName == null) { return null; } @@ -311,7 +307,7 @@ private static String doGetFullPath(final String fileName, final boolean include return null; } if (prefix >= fileName.length()) { - if (includeSeparator) { + if (includeEndSeparator) { return getPrefix(fileName); // add end slash if necessary } return fileName; @@ -320,7 +316,7 @@ private static String doGetFullPath(final String fileName, final boolean include if (index < 0) { return fileName.substring(0, prefix); } - int end = index + (includeSeparator ? 1 : 0); + int end = index + (includeEndSeparator ? 1 : 0); if (end == 0) { end++; } @@ -330,10 +326,10 @@ private static String doGetFullPath(final String fileName, final boolean include /** * Does the work of getting the path. * - * @param fileName the file name - * @param separatorAdd 0 to omit the end separator, 1 to return it - * @return the path - * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) + * @param fileName the file name. + * @param separatorAdd 0 to omit the end separator, 1 to return it. + * @return the path. + * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}). */ private static String doGetPath(final String fileName, final int separatorAdd) { if (fileName == null) { @@ -354,19 +350,17 @@ private static String doGetPath(final String fileName, final int separatorAdd) { /** * Internal method to perform the normalization. * - * @param fileName the file name - * @param separator The separator character to use - * @param keepSeparator true to keep the final separator - * @return the normalized fileName - * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) + * @param fileName the file name. + * @param separator The separator character to use. + * @param keepSeparator true to keep the final separator. + * @return the normalized fileName. + * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}). */ private static String doNormalize(final String fileName, final char separator, final boolean keepSeparator) { if (fileName == null) { return null; } - requireNonNullChars(fileName); - int size = fileName.length(); if (size == 0) { return fileName; @@ -375,10 +369,8 @@ private static String doNormalize(final String fileName, final char separator, f if (prefix < 0) { return null; } - - final char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy + final char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy fileName.getChars(0, fileName.length(), array, 0); - // fix separators throughout final char otherSeparator = flipSeparator(separator); for (int i = 0; i < array.length; i++) { @@ -386,14 +378,12 @@ private static String doNormalize(final String fileName, final char separator, f array[i] = separator; } } - // add extra separator on the end to simplify code below boolean lastIsDirectory = true; if (array[size - 1] != separator) { array[size++] = separator; lastIsDirectory = false; } - // adjoining slashes // If we get here, prefix can only be 0 or greater, size 1 or greater // If prefix is 0, set loop start to 1 to prevent index errors @@ -404,11 +394,9 @@ private static String doNormalize(final String fileName, final char separator, f i--; } } - // period slash for (int i = prefix + 1; i < size; i++) { - if (array[i] == separator && array[i - 1] == '.' && - (i == prefix + 1 || array[i - 2] == separator)) { + if (array[i] == separator && array[i - 1] == '.' && (i == prefix + 1 || array[i - 2] == separator)) { if (i == size - 1) { lastIsDirectory = true; } @@ -417,12 +405,9 @@ private static String doNormalize(final String fileName, final char separator, f i--; } } - // double period slash - outer: - for (int i = prefix + 2; i < size; i++) { - if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' && - (i == prefix + 2 || array[i - 3] == separator)) { + outer: for (int i = prefix + 2; i < size; i++) { + if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' && (i == prefix + 2 || array[i - 3] == separator)) { if (i == prefix + 2) { return null; } @@ -430,7 +415,7 @@ private static String doNormalize(final String fileName, final char separator, f lastIsDirectory = true; } int j; - for (j = i - 4 ; j >= prefix; j--) { + for (j = i - 4; j >= prefix; j--) { if (array[j] == separator) { // remove b/../ from a/b/../c System.arraycopy(array, i + 1, array, j + 1, size - i); @@ -445,17 +430,13 @@ private static String doNormalize(final String fileName, final char separator, f i = prefix + 1; } } - - if (size <= 0) { // should never be less than 0 + if (size <= 0) { // should never be less than 0 return EMPTY_STRING; } - if (size <= prefix) { // should never be less than prefix - return new String(array, 0, size); - } - if (lastIsDirectory && keepSeparator) { - return new String(array, 0, size); // keep trailing separator + if (size <= prefix || lastIsDirectory && keepSeparator) { + return new String(array, 0, size); // keep trailing separator } - return new String(array, 0, size - 1); // lose trailing separator + return new String(array, 0, size - 1); // lose trailing separator } /** @@ -465,9 +446,9 @@ private static String doNormalize(final String fileName, final char separator, f * This is merely a null-safe case-sensitive string equality. * * - * @param fileName1 the first file name, may be null - * @param fileName2 the second file name, may be null - * @return true if the file names are equal, null equals null + * @param fileName1 the first file name, may be null. + * @param fileName2 the second file name, may be null. + * @return true if the file names are equal, null equals null. * @see IOCase#SENSITIVE */ public static boolean equals(final String fileName1, final String fileName2) { @@ -478,15 +459,14 @@ public static boolean equals(final String fileName1, final String fileName2) { * Checks whether two file names are equal, optionally normalizing and providing * control over the case-sensitivity. * - * @param fileName1 the first file name, may be null - * @param fileName2 the second file name, may be null - * @param normalize whether to normalize the file names - * @param ioCase what case sensitivity rule to use, null means case-sensitive - * @return true if the file names are equal, null equals null + * @param fileName1 the first file name, may be null. + * @param fileName2 the second file name, may be null. + * @param normalize whether to normalize the file names. + * @param ioCase what case sensitivity rule to use, null means case-sensitive. + * @return true if the file names are equal, null equals null. * @since 1.3 */ public static boolean equals(String fileName1, String fileName2, final boolean normalize, final IOCase ioCase) { - if (fileName1 == null || fileName2 == null) { return fileName1 == null && fileName2 == null; } @@ -510,9 +490,9 @@ public static boolean equals(String fileName1, String fileName2, final boolean n * The check is then performed in a case-sensitive manner. * * - * @param fileName1 the first file name, may be null - * @param fileName2 the second file name, may be null - * @return true if the file names are equal, null equals null + * @param fileName1 the first file name, may be null. + * @param fileName2 the second file name, may be null. + * @return true if the file names are equal, null equals null. * @see IOCase#SENSITIVE */ public static boolean equalsNormalized(final String fileName1, final String fileName2) { @@ -528,9 +508,9 @@ public static boolean equalsNormalized(final String fileName1, final String file * case-insensitively on Windows. * * - * @param fileName1 the first file name, may be null - * @param fileName2 the second file name, may be null - * @return true if the file names are equal, null equals null + * @param fileName1 the first file name, may be null. + * @param fileName2 the second file name, may be null. + * @return true if the file names are equal, null equals null. * @see IOCase#SYSTEM */ public static boolean equalsNormalizedOnSystem(final String fileName1, final String fileName2) { @@ -544,9 +524,9 @@ public static boolean equalsNormalizedOnSystem(final String fileName1, final Str * The check is case-sensitive on Unix and case-insensitive on Windows. * * - * @param fileName1 the first file name, may be null - * @param fileName2 the second file name, may be null - * @return true if the file names are equal, null equals null + * @param fileName1 the first file name, may be null. + * @param fileName2 the second file name, may be null. + * @return true if the file names are equal, null equals null. * @see IOCase#SYSTEM */ public static boolean equalsOnSystem(final String fileName1, final String fileName2) { @@ -572,7 +552,7 @@ static char flipSeparator(final char ch) { /** * Special handling for NTFS ADS: Don't accept colon in the file name. * - * @param fileName a file name + * @param fileName a file name. * @return ADS offsets. */ private static int getAdsCriticalOffset(final String fileName) { @@ -609,9 +589,9 @@ private static int getAdsCriticalOffset(final String fileName) { * The output will be the same irrespective of the machine that the code is running on. * * - * @param fileName the file name, null returns null - * @return the name of the file without the path, or an empty string if none exists - * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) + * @param fileName the file name, null returns null. + * @return the name of the file without the path, or an empty string if none exists. + * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}). */ public static String getBaseName(final String fileName) { return removeExtension(getName(fileName)); @@ -682,9 +662,9 @@ public static String getExtension(final String fileName) throws IllegalArgumentE * The output will be the same irrespective of the machine that the code is running on. * * - * @param fileName the file name, null returns null - * @return the path of the file, an empty string if none exists, null if invalid - * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) + * @param fileName the file name, null returns null. + * @return the path of the file, an empty string if none exists, null if invalid. + * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}). */ public static String getFullPath(final String fileName) { return doGetFullPath(fileName, true); @@ -715,9 +695,9 @@ public static String getFullPath(final String fileName) { * The output will be the same irrespective of the machine that the code is running on. * * - * @param fileName the file name, null returns null - * @return the path of the file, an empty string if none exists, null if invalid - * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) + * @param fileName the file name, null returns null. + * @return the path of the file, an empty string if none exists, null if invalid. + * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}). */ public static String getFullPathNoEndSeparator(final String fileName) { return doGetFullPath(fileName, false); @@ -740,9 +720,9 @@ public static String getFullPathNoEndSeparator(final String fileName) { * The output will be the same irrespective of the machine that the code is running on. * * - * @param fileName the file name, null returns null - * @return the name of the file without the path, or an empty string if none exists - * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}) + * @param fileName the file name, null returns null. + * @return the name of the file without the path, or an empty string if none exists. + * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}). */ public static String getName(final String fileName) { if (fileName == null) { @@ -773,9 +753,9 @@ public static String getName(final String fileName) { * See {@link #getFullPath(String)} for the method that retains the prefix. * * - * @param fileName the file name, null returns null - * @return the path of the file, an empty string if none exists, null if invalid - * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) + * @param fileName the file name, null returns null. + * @return the path of the file, an empty string if none exists, null if invalid. + * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}). */ public static String getPath(final String fileName) { return doGetPath(fileName, 1); @@ -804,9 +784,9 @@ public static String getPath(final String fileName) { * See {@link #getFullPathNoEndSeparator(String)} for the method that retains the prefix. * * - * @param fileName the file name, null returns null - * @return the path of the file, an empty string if none exists, null if invalid - * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}) + * @param fileName the file name, null returns null. + * @return the path of the file, an empty string if none exists, null if invalid. + * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}). */ public static String getPathNoEndSeparator(final String fileName) { return doGetPath(fileName, 0); @@ -839,9 +819,9 @@ public static String getPathNoEndSeparator(final String fileName) { * ie. both Unix and Windows prefixes are matched regardless. * * - * @param fileName the file name, null returns null - * @return the prefix of the file, null if invalid - * @throws IllegalArgumentException if the result contains the null character ({@code U+0000}) + * @param fileName the file name, null returns null. + * @return the prefix of the file, null if invalid. + * @throws IllegalArgumentException if the result contains the null character ({@code U+0000}). */ public static String getPrefix(final String fileName) { if (fileName == null) { @@ -898,8 +878,8 @@ public static String getPrefix(final String fileName) { * to a single slash at the start of the file name. * * - * @param fileName the file name to find the prefix in, null returns -1 - * @return the length of the prefix, -1 if invalid or null + * @param fileName the file name to find the prefix in, null returns -1. + * @return the length of the prefix, -1 if invalid or null. */ public static int getPrefixLength(final String fileName) { if (fileName == null) { @@ -979,8 +959,8 @@ public static int getPrefixLength(final String fileName) { * an {@link IllegalArgumentException} for names like this. * * @param fileName - * the file name to find the last extension separator in, null returns -1 - * @return the index of the last extension separator character, or -1 if there is no such character + * the file name to find the last extension separator in, null returns -1. + * @return the index of the last extension separator character, or -1 if there is no such character. * @throws IllegalArgumentException Windows only: the file name parameter is, in fact, * the identifier of an Alternate Data Stream, for example "foo.exe:bar.txt". */ @@ -1008,9 +988,9 @@ public static int indexOfExtension(final String fileName) throws IllegalArgument *
* The output will be the same irrespective of the machine that the code is running on.
*
- * @param fileName the file name to find the last path separator in, null returns -1
+ * @param fileName the file name to find the last path separator in, null returns -1.
* @return the index of the last separator character, or -1 if there
- * is no such character
+ * is no such character.
*/
public static int indexOfLastSeparator(final String fileName) {
if (fileName == null) {
@@ -1032,17 +1012,16 @@ private static boolean isEmpty(final String string) {
* after the last period. There must be no directory separator after the period.
* The extension check is case-sensitive on all platforms.
*
- * @param fileName the file name, null returns false
- * @param extensions the extensions to check for, null checks for no extension
- * @return true if the file name is one of the extensions
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * @param fileName the file name, null returns false.
+ * @param extensions the extensions to check for, null checks for no extension.
+ * @return true if the file name is one of the extensions.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
public static boolean isExtension(final String fileName, final Collection
* The output will be the same irrespective of the machine that the code is running on.
*
- * @param fileName the file name, null returns null
- * @return the file name minus the extension
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * @param fileName the file name, null returns null.
+ * @return the file name minus the extension.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
public static String removeExtension(final String fileName) {
if (fileName == null) {
return null;
}
requireNonNullChars(fileName);
-
final int index = indexOfExtension(fileName);
if (index == NOT_FOUND) {
return fileName;
@@ -1477,9 +1447,9 @@ public static String removeExtension(final String fileName) {
*
* This may be used to defend against poison byte attacks.
*
- * @param path the path to check
- * @return The input
- * @throws IllegalArgumentException if path contains the null character ({@code U+0000})
+ * @param path the path to check.
+ * @return The input.
+ * @throws IllegalArgumentException if path contains the null character ({@code U+0000}).
*/
private static String requireNonNullChars(final String path) {
if (path.indexOf(0) >= 0) {
@@ -1524,17 +1494,15 @@ public static String separatorsToWindows(final String path) {
* The text is split by '?' and '*'.
* Where multiple '*' occur consecutively they are collapsed into a single '*'.
*
- * @param text the text to split
- * @return the array of tokens, never null
+ * @param text the text to split.
+ * @return the array of tokens, never null.
*/
static String[] splitOnTokens(final String text) {
// used by wildcardMatch
// package level so a unit test may run on this
-
if (text.indexOf('?') == NOT_FOUND && text.indexOf('*') == NOT_FOUND) {
return new String[] { text };
}
-
final char[] array = text.toCharArray();
final ArrayList
- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset}. + * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset}. *
* - * @param data the byte array to be dumped - * @param offset offset of the byte array within a larger entity + * @param data the byte array to be dumped. + * @param offset offset of the byte array within a larger entity. * @param stream the OutputStream to which the data is to be - * written - * @param index initial index into the byte array + * written. + * @param index initial index into the byte array. * @throws IOException is thrown if anything goes wrong writing - * the data to stream + * the data to stream. * @throws ArrayIndexOutOfBoundsException if the index is - * outside the data array's bounds - * @throws NullPointerException if the output stream is null + * outside the data array's bounds. + * @throws NullPointerException if the output stream is null. */ @SuppressWarnings("resource") // Caller closes stream public static void dump(final byte[] data, final long offset, @@ -197,8 +197,8 @@ public static void dump(final byte[] data, final long offset, /** * Dumps a byte value into a StringBuilder. * - * @param builder the StringBuilder to dump the value in - * @param value the byte value to be dumped + * @param builder the StringBuilder to dump the value in. + * @param value the byte value to be dumped. * @return StringBuilder containing the dumped value. */ private static StringBuilder dump(final StringBuilder builder, final byte value) { @@ -211,8 +211,8 @@ private static StringBuilder dump(final StringBuilder builder, final byte value) /** * Dumps a long value into a StringBuilder. * - * @param builder the StringBuilder to dump the value in - * @param value the long value to be dumped + * @param builder the StringBuilder to dump the value in. + * @param value the long value to be dumped. * @return StringBuilder containing the dumped value. */ private static StringBuilder dump(final StringBuilder builder, final long value) { diff --git a/src/main/java/org/apache/commons/io/IOCase.java b/src/main/java/org/apache/commons/io/IOCase.java index 7fee424f489..9a4d168fc3a 100644 --- a/src/main/java/org/apache/commons/io/IOCase.java +++ b/src/main/java/org/apache/commons/io/IOCase.java @@ -21,7 +21,7 @@ import java.util.stream.Stream; /** - * Enumeration of IO case sensitivity. + * Enumerates IO case sensitivity types. *
* Different filing systems have different rules for case-sensitivity.
* Windows is case-insensitive, Unix is case-sensitive.
@@ -72,9 +72,9 @@ public enum IOCase {
/**
* Looks up an IOCase by name.
*
- * @param name the name to find
- * @return the IOCase object
- * @throws IllegalArgumentException if the name is invalid
+ * @param name the name to find.
+ * @return the IOCase object.
+ * @throws IllegalArgumentException if the name is invalid.
*/
public static IOCase forName(final String name) {
return Stream.of(values()).filter(ioCase -> ioCase.getName().equals(name)).findFirst()
@@ -95,7 +95,7 @@ public static boolean isCaseSensitive(final IOCase ioCase) {
/**
* Returns the given value if not-null, the defaultValue if null.
*
- * @param value the value to test.
+ * @param value the value to test, may be null.
* @param defaultValue the default value.
* @return the given value if not-null, the defaultValue if null.
* @since 2.12.0
@@ -236,7 +236,7 @@ public boolean checkStartsWith(final String str, final String start) {
/**
* Gets the name of the constant.
*
- * @return the name of the constant
+ * @return the name of the constant.
*/
public String getName() {
return name;
diff --git a/src/main/java/org/apache/commons/io/IOExceptionList.java b/src/main/java/org/apache/commons/io/IOExceptionList.java
index 740bedb6789..256cebd1360 100644
--- a/src/main/java/org/apache/commons/io/IOExceptionList.java
+++ b/src/main/java/org/apache/commons/io/IOExceptionList.java
@@ -126,7 +126,7 @@ public
- * The byte-to-char methods and char-to-byte methods involve a conversion step. - * Two methods are provided in each case, one that uses the platform default - * encoding and the other which allows you to specify an encoding. You are - * encouraged to always specify an encoding because relying on the platform - * default can lead to unexpected results, for example when moving from - * development to production. + * The byte-to-char methods and char-to-byte methods involve a conversion step. Two methods are provided in each case, one that uses the platform default + * encoding and the other which allows you to specify an encoding. You are encouraged to always specify an encoding because relying on the platform default can + * lead to unexpected results, for example when moving from development to production. *
*- * All the methods in this class that read a stream are buffered internally. - * This means that there is no cause to use a {@link BufferedInputStream} - * or {@link BufferedReader}. The default buffer size of 4K has been shown - * to be efficient in tests. + * All the methods in this class that read a stream are buffered internally. This means that there is no cause to use a {@link BufferedInputStream} or + * {@link BufferedReader}. The default buffer size of 4K has been shown to be efficient in tests. *
** The various copy methods all delegate the actual copying to one of the following methods: @@ -110,18 +105,14 @@ *
- * Applications can re-use buffers by using the underlying methods directly. - * This may improve performance for applications that need to do a lot of copying. + * Applications can re-use buffers by using the underlying methods directly. This may improve performance for applications that need to do a lot of copying. *
*- * Wherever possible, the methods in this class do not flush or close - * the stream. This is to avoid making non-portable assumptions about the - * streams' origin and further use. Thus the caller is still responsible for - * closing streams after use. + * Wherever possible, the methods in this class do not flush or close the stream. This is to avoid making non-portable assumptions about the streams' + * origin and further use. Thus the caller is still responsible for closing streams after use. *
** Provenance: Excalibur. @@ -132,6 +123,142 @@ public class IOUtils { // Writer. Each method should take at least one of these as a parameter, // or return one of them. + /** + * Holder for per-thread internal scratch buffer. + *
+ * Buffers are created lazily and reused within the same thread to reduce allocation overhead. In the rare case of reentrant access, a temporary buffer is + * allocated to avoid data corruption. + *
+ *+ * Typical usage: + *
+ * + *{@code
+ * try (ScratchBytes scratch = ScratchBytes.get()) {
+ * // use the buffer
+ * byte[] bytes = scratch.array();
+ * // ...
+ * }
+ * }
+ */
+ static final class ScratchBytes implements AutoCloseable {
+
+ /**
+ * Wraps an internal byte array. [0] boolean in use. [1] byte[] buffer.
+ */
+ private static final ThreadLocal+ * Buffers are created lazily and reused within the same thread to reduce allocation overhead. In the rare case of reentrant access, a temporary buffer is + * allocated to avoid data corruption. + *
+ *+ * Typical usage: + *
+ * + *{@code
+ * try (ScratchChars scratch = ScratchChars.get()) {
+ * // use the buffer
+ * char[] bytes = scratch.array();
+ * // ...
+ * }
+ * }
+ */
+ static final class ScratchChars implements AutoCloseable {
+
+ /**
+ * Wraps an internal char array. [0] boolean in use. [1] char[] buffer.
+ */
+ private static final ThreadLocal@@ -232,8 +340,7 @@ public class IOUtils { public static final int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8; /** - * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a - * BufferedInputStream from the given InputStream. + * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a BufferedInputStream from the given InputStream. * * @param inputStream the InputStream to wrap or return (not null). * @return the given InputStream or a new {@link BufferedInputStream} for the given InputStream. @@ -245,16 +352,14 @@ public static BufferedInputStream buffer(final InputStream inputStream) { // reject null early on rather than waiting for IO operation to fail // not checked by BufferedInputStream Objects.requireNonNull(inputStream, "inputStream"); - return inputStream instanceof BufferedInputStream ? - (BufferedInputStream) inputStream : new BufferedInputStream(inputStream); + return inputStream instanceof BufferedInputStream ? (BufferedInputStream) inputStream : new BufferedInputStream(inputStream); } /** - * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a - * BufferedInputStream from the given InputStream. + * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a BufferedInputStream from the given InputStream. * * @param inputStream the InputStream to wrap or return (not null). - * @param size the buffer size, if a new BufferedInputStream is created. + * @param size the buffer size, if a new BufferedInputStream is created. * @return the given InputStream or a new {@link BufferedInputStream} for the given InputStream. * @throws NullPointerException if the input parameter is null. * @since 2.5 @@ -264,16 +369,14 @@ public static BufferedInputStream buffer(final InputStream inputStream, final in // reject null early on rather than waiting for IO operation to fail // not checked by BufferedInputStream Objects.requireNonNull(inputStream, "inputStream"); - return inputStream instanceof BufferedInputStream ? - (BufferedInputStream) inputStream : new BufferedInputStream(inputStream, size); + return inputStream instanceof BufferedInputStream ? (BufferedInputStream) inputStream : new BufferedInputStream(inputStream, size); } /** - * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a - * BufferedOutputStream from the given OutputStream. + * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a BufferedOutputStream from the given OutputStream. * * @param outputStream the OutputStream to wrap or return (not null). - * @return the given OutputStream or a new {@link BufferedOutputStream} for the given OutputStream + * @return the given OutputStream or a new {@link BufferedOutputStream} for the given OutputStream. * @throws NullPointerException if the input parameter is null. * @since 2.5 */ @@ -282,16 +385,14 @@ public static BufferedOutputStream buffer(final OutputStream outputStream) { // reject null early on rather than waiting for IO operation to fail // not checked by BufferedInputStream Objects.requireNonNull(outputStream, "outputStream"); - return outputStream instanceof BufferedOutputStream ? - (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream); + return outputStream instanceof BufferedOutputStream ? (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream); } /** - * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a - * BufferedOutputStream from the given OutputStream. + * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a BufferedOutputStream from the given OutputStream. * * @param outputStream the OutputStream to wrap or return (not null). - * @param size the buffer size, if a new BufferedOutputStream is created. + * @param size the buffer size, if a new BufferedOutputStream is created. * @return the given OutputStream or a new {@link BufferedOutputStream} for the given OutputStream. * @throws NullPointerException if the input parameter is null. * @since 2.5 @@ -301,13 +402,11 @@ public static BufferedOutputStream buffer(final OutputStream outputStream, final // reject null early on rather than waiting for IO operation to fail // not checked by BufferedInputStream Objects.requireNonNull(outputStream, "outputStream"); - return outputStream instanceof BufferedOutputStream ? - (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream, size); + return outputStream instanceof BufferedOutputStream ? (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream, size); } /** - * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from - * the given reader. + * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from the given reader. * * @param reader the reader to wrap or return (not null). * @return the given reader or a new {@link BufferedReader} for the given reader. @@ -319,11 +418,10 @@ public static BufferedReader buffer(final Reader reader) { } /** - * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from the - * given reader. + * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from the given reader. * * @param reader the reader to wrap or return (not null). - * @param size the buffer size, if a new BufferedReader is created. + * @param size the buffer size, if a new BufferedReader is created. * @return the given reader or a new {@link BufferedReader} for the given reader. * @throws NullPointerException if the input parameter is null. * @since 2.5 @@ -333,8 +431,7 @@ public static BufferedReader buffer(final Reader reader, final int size) { } /** - * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the - * given Writer. + * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the given Writer. * * @param writer the Writer to wrap or return (not null). * @return the given Writer or a new {@link BufferedWriter} for the given Writer. @@ -346,11 +443,10 @@ public static BufferedWriter buffer(final Writer writer) { } /** - * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the - * given Writer. + * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the given Writer. * * @param writer the Writer to wrap or return (not null). - * @param size the buffer size, if a new BufferedWriter is created. + * @param size the buffer size, if a new BufferedWriter is created. * @return the given Writer or a new {@link BufferedWriter} for the given Writer. * @throws NullPointerException if the input parameter is null. * @since 2.5 @@ -370,9 +466,7 @@ public static byte[] byteArray() { } /** - * Returns a new byte array of the given size. - * - * TODO Consider guarding or warning against large allocations. + * Returns a new byte array of the given size. TODO Consider guarding or warning against large allocations. * * @param size array size. * @return a new byte array of the given size. @@ -394,9 +488,7 @@ private static char[] charArray() { } /** - * Returns a new char array of the given size. - * - * TODO Consider guarding or warning against large allocations. + * Returns a new char array of the given size. TODO Consider guarding or warning against large allocations. * * @param size array size. * @return a new char array of the given size. @@ -408,19 +500,23 @@ private static char[] charArray(final int size) { /** * Validates that the sub-range {@code [off, off + len)} is within the bounds of the given array. - * - *
The range is valid if all of the following hold:
+ *+ * The range is valid if all of the following hold: + *
*+ * If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message. + *
+ *+ * Typical usage in {@link InputStream#read(byte[], int, int)} and {@link OutputStream#write(byte[], int, int)} implementations: + *
* - *If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
- * - *Typical usage in {@link InputStream#read(byte[], int, int)} and {@link OutputStream#write(byte[], int, int)} implementations:
- * - *
+ *
+ *
* public int read(byte[] b, int off, int len) throws IOException {
* IOUtils.checkFromIndexSize(b, off, len);
* if (len == 0) {
@@ -438,13 +534,14 @@ private static char[] charArray(final int size) {
* ensureOpen();
* // perform write...
* }
- *
+ *
+ *
*
- * @param array the array against which the range is validated
- * @param off the starting offset into the array (inclusive)
- * @param len the number of elements to access
- * @throws NullPointerException if {@code array} is {@code null}
- * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code array}
+ * @param array the array against which the range is validated.
+ * @param off the starting offset into the array (inclusive).
+ * @param len the number of elements to access.
+ * @throws NullPointerException if {@code array} is {@code null}.
+ * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code array}.
* @see InputStream#read(byte[], int, int)
* @see OutputStream#write(byte[], int, int)
* @since 2.21.0
@@ -455,19 +552,23 @@ public static void checkFromIndexSize(final byte[] array, final int off, final i
/**
* Validates that the sub-range {@code [off, off + len)} is within the bounds of the given array.
- *
- * The range is valid if all of the following hold:
+ *+ * The range is valid if all of the following hold: + *
*+ * If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message. + *
+ *+ * Typical usage in {@link Reader#read(char[], int, int)} and {@link Writer#write(char[], int, int)} implementations: + *
* - *If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
- * - *Typical usage in {@link Reader#read(char[], int, int)} and {@link Writer#write(char[], int, int)} implementations:
- * - *
+ *
+ *
* public int read(char[] cbuf, int off, int len) throws IOException {
* ensureOpen();
* IOUtils.checkFromIndexSize(cbuf, off, len);
@@ -485,13 +586,14 @@ public static void checkFromIndexSize(final byte[] array, final int off, final i
* }
* // perform write...
* }
- *
+ *
+ *
*
- * @param array the array against which the range is validated
- * @param off the starting offset into the array (inclusive)
- * @param len the number of characters to access
- * @throws NullPointerException if {@code array} is {@code null}
- * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code array}
+ * @param array the array against which the range is validated.
+ * @param off the starting offset into the array (inclusive).
+ * @param len the number of characters to access.
+ * @throws NullPointerException if {@code array} is {@code null}.
+ * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code array}.
* @see Reader#read(char[], int, int)
* @see Writer#write(char[], int, int)
* @since 2.21.0
@@ -500,21 +602,31 @@ public static void checkFromIndexSize(final char[] array, final int off, final i
checkFromIndexSize(off, len, Objects.requireNonNull(array, "char array").length);
}
+ static void checkFromIndexSize(final int off, final int len, final int arrayLength) {
+ if ((off | len | arrayLength) < 0 || arrayLength - len < off) {
+ throw new IndexOutOfBoundsException(String.format("Range [%s, %+ * The range is valid if all of the following hold: + *
*+ * If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message. + *
+ *+ * Typical usage in {@link Writer#write(String, int, int)} implementations: + *
* - *If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
- * - *Typical usage in {@link Writer#write(String, int, int)} implementations:
- * - *
+ *
+ *
* public void write(String str, int off, int len) throws IOException {
* IOUtils.checkFromIndexSize(str, off, len);
* if (len == 0) {
@@ -522,13 +634,14 @@ public static void checkFromIndexSize(final char[] array, final int off, final i
* }
* // perform write...
* }
- *
+ *
+ *
*
- * @param str the string against which the range is validated
- * @param off the starting offset into the string (inclusive)
- * @param len the number of characters to write
- * @throws NullPointerException if {@code str} is {@code null}
- * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code str}
+ * @param str the string against which the range is validated.
+ * @param off the starting offset into the string (inclusive).
+ * @param len the number of characters to write.
+ * @throws NullPointerException if {@code str} is {@code null}.
+ * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code str}.
* @see Writer#write(String, int, int)
* @since 2.21.0
*/
@@ -536,40 +649,40 @@ public static void checkFromIndexSize(final String str, final int off, final int
checkFromIndexSize(off, len, Objects.requireNonNull(str, "str").length());
}
- static void checkFromIndexSize(final int off, final int len, final int arrayLength) {
- if ((off | len | arrayLength) < 0 || arrayLength - len < off) {
- throw new IndexOutOfBoundsException(String.format("Range [%s, %+ * The sub-sequence is valid if all of the following hold: + *
*+ * If {@code seq} is {@code null}, it is treated as the literal string {@code "null"} (length {@code 4}). + *
+ *+ * If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message. + *
+ *+ * Typical usage in {@link Appendable#append(CharSequence, int, int)} implementations: + *
* - *If {@code seq} is {@code null}, it is treated as the literal string {@code "null"} (length {@code 4}).
- * - *If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
- * - *Typical usage in {@link Appendable#append(CharSequence, int, int)} implementations:
- * - *
+ *
+ *
* public Appendable append(CharSequence csq, int start, int end) throws IOException {
* IOUtils.checkFromToIndex(csq, start, end);
* // perform append...
* return this;
* }
- *
+ *
+ *
*
- * @param seq the character sequence to validate (may be {@code null}, treated as {@code "null"})
- * @param fromIndex the starting index (inclusive)
- * @param toIndex the ending index (exclusive)
- * @throws IndexOutOfBoundsException if the range {@code [fromIndex, toIndex)} is out of bounds for {@code seq}
+ * @param seq the character sequence to validate (may be {@code null}, treated as {@code "null"}).
+ * @param fromIndex the starting index (inclusive).
+ * @param toIndex the ending index (exclusive).
+ * @throws IndexOutOfBoundsException if the range {@code [fromIndex, toIndex)} is out of bounds for {@code seq}.
* @see Appendable#append(CharSequence, int, int)
* @since 2.21.0
*/
@@ -589,13 +702,12 @@ static void checkFromToIndex(final int fromIndex, final int toIndex, final int l
* - * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in - * finally blocks. + * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in finally blocks. *
* Example code: *
+ * *
* Closeable closeable = null;
* try {
@@ -691,6 +798,7 @@ private static void closeQ(final Closeable closeable) {
*
* Closing all streams:
*
+ *
*
* try {
* return IOUtils.copy(inputStream, outputStream);
@@ -708,7 +816,7 @@ private static void closeQ(final Closeable closeable) {
* @see Throwable#addSuppressed(Throwable)
*/
public static void closeQuietly(final Closeable closeable) {
- closeQuietly(closeable, null);
+ closeQuietly(closeable, (Consumer) null);
}
/**
@@ -716,17 +824,17 @@ public static void closeQuietly(final Closeable closeable) {
*
* Equivalent to {@link Closeable#close()}, except any exceptions will be ignored.
*
- * This is typically used in finally blocks to ensure that the closeable is closed
- * even if an Exception was thrown before the normal close statement was reached.
- *
- * It should not be used to replace the close statement(s)
- * which should be present for the non-exceptional case.
- *
- * It is only intended to simplify tidying up where normal processing has already failed
- * and reporting close failure as well is not necessary or useful.
+ * This is typically used in finally blocks to ensure that the closeable is closed even if an Exception was thrown before the normal close statement was
+ * reached.
+ *
+ *
+ * It should not be used to replace the close statement(s) which should be present for the non-exceptional case.
+ *
+ * It is only intended to simplify tidying up where normal processing has already failed and reporting close failure as well is not necessary or useful.
*
* Example code:
*
+ *
*
* Closeable closeable = null;
* try {
@@ -741,7 +849,8 @@ public static void closeQuietly(final Closeable closeable) {
*
*
* Closing all streams:
- *
+ *
+ *
*
* try {
* return IOUtils.copy(inputStream, outputStream);
@@ -752,6 +861,7 @@ public static void closeQuietly(final Closeable closeable) {
*
* Also consider using a try-with-resources statement where appropriate.
*
+ *
* @param closeables the objects to close, may be null or already closed.
* @see #closeQuietly(Closeable)
* @since 2.5
@@ -767,7 +877,7 @@ public static void closeQuietly(final Closeable... closeables) {
* Closes the given {@link Closeable} as a null-safe operation while consuming IOException by the given {@code consumer}.
*
* @param closeable The resource to close, may be null.
- * @param consumer Consumes the Exception thrown by {@link Closeable#close()}.
+ * @param consumer Consumes the Exception thrown by {@link Closeable#close()}.
* @since 2.7
*/
public static void closeQuietly(final Closeable closeable, final Consumer consumer) {
@@ -785,24 +895,24 @@ public static void closeQuietly(final Closeable closeable, final Consumer
- * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
*
* Example code:
*
+ *
*
- * byte[] data = new byte[1024];
- * InputStream in = null;
- * try {
- * in = new FileInputStream("foo.txt");
- * in.read(data);
- * in.close(); //close errors are handled
- * } catch (Exception e) {
- * // error handling
- * } finally {
- * IOUtils.closeQuietly(in);
- * }
+ * byte[] data = new byte[1024];
+ * InputStream in = null;
+ * try {
+ * in = new FileInputStream("foo.txt");
+ * in.read(data);
+ * in.close(); // close errors are handled
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * IOUtils.closeQuietly(in);
+ * }
*
*
* Also consider using a try-with-resources statement where appropriate.
@@ -834,20 +944,19 @@ public static void closeQuietly(final Iterable closeables) {
/**
* Closes an {@link OutputStream} unconditionally.
*
- * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
*
* Example code:
*
+ *
*
* byte[] data = "Hello, World".getBytes();
- *
* OutputStream out = null;
* try {
* out = new FileOutputStream("foo.txt");
* out.write(data);
- * out.close(); //close errors are handled
+ * out.close(); // close errors are handled
* } catch (IOException e) {
* // error handling
* } finally {
@@ -868,24 +977,24 @@ public static void closeQuietly(final OutputStream output) {
/**
* Closes an {@link Reader} unconditionally.
*
- * Equivalent to {@link Reader#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link Reader#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
*
* Example code:
*
+ *
*
- * char[] data = new char[1024];
- * Reader in = null;
- * try {
- * in = new FileReader("foo.txt");
- * in.read(data);
- * in.close(); //close errors are handled
- * } catch (Exception e) {
- * // error handling
- * } finally {
- * IOUtils.closeQuietly(in);
- * }
+ * char[] data = new char[1024];
+ * Reader in = null;
+ * try {
+ * in = new FileReader("foo.txt");
+ * in.read(data);
+ * in.close(); // close errors are handled
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * IOUtils.closeQuietly(in);
+ * }
*
*
* Also consider using a try-with-resources statement where appropriate.
@@ -901,23 +1010,22 @@ public static void closeQuietly(final Reader reader) {
/**
* Closes a {@link Selector} unconditionally.
*
- * Equivalent to {@link Selector#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link Selector#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
*
* Example code:
*
+ *
*
- * Selector selector = null;
- * try {
- * selector = Selector.open();
- * // process socket
- *
- * } catch (Exception e) {
- * // error handling
- * } finally {
- * IOUtils.closeQuietly(selector);
- * }
+ * Selector selector = null;
+ * try {
+ * selector = Selector.open();
+ * // process socket
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * IOUtils.closeQuietly(selector);
+ * }
*
*
* Also consider using a try-with-resources statement where appropriate.
@@ -934,23 +1042,23 @@ public static void closeQuietly(final Selector selector) {
/**
* Closes a {@link ServerSocket} unconditionally.
*
- * Equivalent to {@link ServerSocket#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link ServerSocket#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
*
* Example code:
*
+ *
*
- * ServerSocket socket = null;
- * try {
- * socket = new ServerSocket();
- * // process socket
- * socket.close();
- * } catch (Exception e) {
- * // error handling
- * } finally {
- * IOUtils.closeQuietly(socket);
- * }
+ * ServerSocket socket = null;
+ * try {
+ * socket = new ServerSocket();
+ * // process socket
+ * socket.close();
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * IOUtils.closeQuietly(socket);
+ * }
*
*
* Also consider using a try-with-resources statement where appropriate.
@@ -967,23 +1075,23 @@ public static void closeQuietly(final ServerSocket serverSocket) {
/**
* Closes a {@link Socket} unconditionally.
*
- * Equivalent to {@link Socket#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link Socket#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
*
* Example code:
*
+ *
*
- * Socket socket = null;
- * try {
- * socket = new Socket("http://www.foo.com/", 80);
- * // process socket
- * socket.close();
- * } catch (Exception e) {
- * // error handling
- * } finally {
- * IOUtils.closeQuietly(socket);
- * }
+ * Socket socket = null;
+ * try {
+ * socket = new Socket("http://www.foo.com/", 80);
+ * // process socket
+ * socket.close();
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * IOUtils.closeQuietly(socket);
+ * }
*
*
* Also consider using a try-with-resources statement where appropriate.
@@ -1016,23 +1124,23 @@ public static void closeQuietly(final Stream closeables) {
/**
* Closes an {@link Writer} unconditionally.
*
- * Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link Writer#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
*
* Example code:
*
+ *
*
- * Writer out = null;
- * try {
- * out = new StringWriter();
- * out.write("Hello World");
- * out.close(); //close errors are handled
- * } catch (Exception e) {
- * // error handling
- * } finally {
- * IOUtils.closeQuietly(out);
- * }
+ * Writer out = null;
+ * try {
+ * out = new StringWriter();
+ * out.write("Hello World");
+ * out.close(); // close errors are handled
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * IOUtils.closeQuietly(out);
+ * }
*
*
* Also consider using a try-with-resources statement where appropriate.
@@ -1045,6 +1153,37 @@ public static void closeQuietly(final Writer writer) {
closeQ(writer);
}
+ /**
+ * Closes a {@link Closeable} unconditionally and adds any exception thrown by the {@code close()} to the given Throwable.
+ *
+ * For example:
+ *
+ *
+ *
+ * Closeable closeable = ...;
+ * try {
+ * // process closeable.
+ * } catch (Exception e) {
+ * // Handle exception.
+ * throw IOUtils.closeQuietlySuppress(closeable, e);
+ * }
+ *
+ *
+ * Also consider using a try-with-resources statement where appropriate.
+ *
+ *
+ * @param The Throwable type.
+ * @param closeable The object to close, may be null or already closed.
+ * @param throwable Add the exception throw by the closeable to the given Throwable.
+ * @return The given Throwable.
+ * @since 2.22.0
+ * @see Throwable#addSuppressed(Throwable)
+ */
+ public static T closeQuietlySuppress(final Closeable closeable, final T throwable) {
+ closeQuietly(closeable, throwable::addSuppressed);
+ return throwable;
+ }
+
/**
* Consumes bytes from a {@link InputStream} and ignores them.
*
@@ -1054,7 +1193,7 @@ public static void closeQuietly(final Writer writer) {
* @param input the {@link InputStream} to read.
* @return the number of bytes copied. or {@code 0} if {@code input is null}.
* @throws NullPointerException if the InputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.8.0
*/
public static long consume(final InputStream input) throws IOException {
@@ -1070,7 +1209,7 @@ public static long consume(final InputStream input) throws IOException {
* @param input the {@link Reader} to read.
* @return the number of bytes copied. or {@code 0} if {@code input is null}.
* @throws NullPointerException if the Reader is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.12.0
*/
public static long consume(final Reader input) throws IOException {
@@ -1078,18 +1217,15 @@ public static long consume(final Reader input) throws IOException {
}
/**
- * Compares the contents of two Streams to determine if they are equal or
- * not.
+ * Compares the contents of two Streams to determine if they are equal or not.
*
- * This method buffers the input internally using
- * {@link BufferedInputStream} if they are not already buffered.
+ * This method buffers the input internally using {@link BufferedInputStream} if they are not already buffered.
*
*
* @param input1 the first stream.
* @param input2 the second stream.
- * @return true if the content of the streams are equal or they both don't.
- * exist, false otherwise.
- * @throws IOException if an I/O error occurs.
+ * @return true if the content of the streams are equal or they both don't. exist, false otherwise.
+ * @throws IOException if an I/O error occurs.
*/
@SuppressWarnings("resource") // Caller closes input streams
public static boolean contentEquals(final InputStream input1, final InputStream input2) throws IOException {
@@ -1107,10 +1243,7 @@ public static boolean contentEquals(final InputStream input1, final InputStream
// TODO Consider making public
private static boolean contentEquals(final Iterator> iterator1, final Iterator> iterator2) {
while (iterator1.hasNext()) {
- if (!iterator2.hasNext()) {
- return false;
- }
- if (!Objects.equals(iterator1.next(), iterator2.next())) {
+ if (!iterator2.hasNext() || !Objects.equals(iterator1.next(), iterator2.next())) {
return false;
}
}
@@ -1127,7 +1260,7 @@ private static boolean contentEquals(final Iterator> iterator1, final Iterator
* @param input2 the second reader.
* @return true if the content of the readers 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.
+ * @throws IOException if an I/O error occurs.
* @since 1.1
*/
public static boolean contentEquals(final Reader input1, final Reader input2) throws IOException {
@@ -1137,39 +1270,38 @@ public static boolean contentEquals(final Reader input1, final Reader input2) th
if (input1 == null || input2 == null) {
return false;
}
-
- // reuse one
- final char[] array1 = getScratchCharArray();
- // but allocate another
- final char[] array2 = charArray();
- int pos1;
- int pos2;
- int count1;
- int count2;
- while (true) {
- pos1 = 0;
- pos2 = 0;
- for (int index = 0; index < DEFAULT_BUFFER_SIZE; index++) {
- if (pos1 == index) {
- do {
- count1 = input1.read(array1, pos1, DEFAULT_BUFFER_SIZE - pos1);
- } while (count1 == 0);
- if (count1 == EOF) {
- return pos2 == index && input2.read() == EOF;
+ try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
+ final char[] array1 = scratch.array();
+ final char[] array2 = charArray();
+ int pos1;
+ int pos2;
+ int count1;
+ int count2;
+ while (true) {
+ pos1 = 0;
+ pos2 = 0;
+ for (int index = 0; index < DEFAULT_BUFFER_SIZE; index++) {
+ if (pos1 == index) {
+ do {
+ count1 = input1.read(array1, pos1, DEFAULT_BUFFER_SIZE - pos1);
+ } while (count1 == 0);
+ if (count1 == EOF) {
+ return pos2 == index && input2.read() == EOF;
+ }
+ pos1 += count1;
}
- pos1 += count1;
- }
- if (pos2 == index) {
- do {
- count2 = input2.read(array2, pos2, DEFAULT_BUFFER_SIZE - pos2);
- } while (count2 == 0);
- if (count2 == EOF) {
- return pos1 == index && input1.read() == EOF;
+ if (pos2 == index) {
+ do {
+ count2 = input2.read(array2, pos2, DEFAULT_BUFFER_SIZE - pos2);
+ } while (count2 == 0);
+ if (count2 == EOF) {
+ return pos1 == index && input1.read() == EOF;
+ }
+ pos2 += count2;
+ }
+ if (array1[index] != array2[index]) {
+ return false;
}
- pos2 += count2;
- }
- if (array1[index] != array2[index]) {
- return false;
}
}
}
@@ -1198,16 +1330,14 @@ private static boolean contentEqualsIgnoreEOL(final BufferedReader reader1, fina
}
/**
- * Compares the contents of two Readers to determine if they are equal or
- * not, ignoring EOL characters.
+ * Compares the contents of two Readers to determine if they are equal or not, ignoring EOL characters.
*
- * This method buffers the input internally using
- * {@link BufferedReader} if they are not already buffered.
+ * This method buffers the input internally using {@link BufferedReader} if they are not already buffered.
*
*
* @param reader1 the first reader.
* @param reader2 the second reader.
- * @return true if the content of the readers are equal (ignoring EOL differences), false otherwise.
+ * @return true if the content of the readers are equal (ignoring EOL differences), false otherwise.
* @throws NullPointerException if either input is null.
* @throws UncheckedIOException if an I/O error occurs.
* @since 2.2
@@ -1229,17 +1359,16 @@ public static boolean contentEqualsIgnoreEOL(final Reader reader1, final Reader
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * Large streams (over 2GB) will return a bytes copied value of {@code -1} after the copy has completed since
- * the correct number of bytes cannot be returned as an int. For large streams use the
- * {@link #copyLarge(InputStream, OutputStream)} method.
+ * Large streams (over 2GB) will return a bytes copied value of {@code -1} after the copy has completed since the correct number of bytes cannot be returned
+ * as an int. For large streams use the {@link #copyLarge(InputStream, OutputStream)} method.
*
*
- * @param inputStream the {@link InputStream} to read.
+ * @param inputStream the {@link InputStream} to read.
* @param outputStream the {@link OutputStream} to write.
* @return the number of bytes copied, or -1 if greater than {@link Integer#MAX_VALUE}.
* @throws NullPointerException if the InputStream is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 1.1
*/
public static int copy(final InputStream inputStream, final OutputStream outputStream) throws IOException {
@@ -1248,19 +1377,18 @@ public static int copy(final InputStream inputStream, final OutputStream outputS
}
/**
- * Copies bytes from an {@link InputStream} to an {@link OutputStream} using an internal buffer of the
- * given size.
+ * Copies bytes from an {@link InputStream} to an {@link OutputStream} using an internal buffer of the given size.
*
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param inputStream the {@link InputStream} to read.
+ * @param inputStream the {@link InputStream} to read.
* @param outputStream the {@link OutputStream} to write to.
- * @param bufferSize the bufferSize used to copy from the input to the output.
+ * @param bufferSize the bufferSize used to copy from the input to the output.
* @return the number of bytes copied.
* @throws NullPointerException if the InputStream is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.5
*/
public static long copy(final InputStream inputStream, final OutputStream outputStream, final int bufferSize) throws IOException {
@@ -1268,17 +1396,15 @@ public static long copy(final InputStream inputStream, final OutputStream output
}
/**
- * Copies bytes from an {@link InputStream} to chars on a
- * {@link Writer} using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Copies bytes from an {@link InputStream} to chars on a {@link Writer} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* This method uses {@link InputStreamReader}.
*
*
- * @param input the {@link InputStream} to read.
+ * @param input the {@link InputStream} to read.
* @param writer the {@link Writer} to write to.
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
@@ -1291,18 +1417,16 @@ public static void copy(final InputStream input, final Writer writer) throws IOE
}
/**
- * Copies bytes from an {@link InputStream} to chars on a
- * {@link Writer} using the specified character encoding.
+ * Copies bytes from an {@link InputStream} to chars on a {@link Writer} using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* This method uses {@link InputStreamReader}.
*
*
- * @param input the {@link InputStream} to read.
- * @param writer the {@link Writer} to write to.
+ * @param input the {@link InputStream} to read.
+ * @param writer the {@link Writer} to write to.
* @param inputCharset the charset to use for the input stream, null means platform default.
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
@@ -1313,22 +1437,19 @@ public static void copy(final InputStream input, final Writer writer, final Char
}
/**
- * Copies bytes from an {@link InputStream} to chars on a
- * {@link Writer} using the specified character encoding.
+ * Copies bytes from an {@link InputStream} to chars on a {@link Writer} using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link InputStreamReader}.
*
*
- * @param input the {@link InputStream} to read
- * @param writer the {@link Writer} to write to
+ * @param input the {@link InputStream} to read.
+ * @param writer the {@link Writer} to write to.
* @param inputCharsetName the name of the requested charset for the InputStream, null means platform default.
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
@@ -1342,8 +1463,7 @@ public static void copy(final InputStream input, final Writer writer, final Stri
/**
* Copies bytes from a {@link ByteArrayOutputStream} to a {@link QueueInputStream}.
*
- * Unlike using JDK {@link PipedInputStream} and {@link PipedOutputStream} for this, this
- * solution works safely in a single thread environment.
+ * Unlike using JDK {@link PipedInputStream} and {@link PipedOutputStream} for this, this solution works safely in a single thread environment.
*
*
* Example usage:
@@ -1352,14 +1472,13 @@ public static void copy(final InputStream input, final Writer writer, final Stri
*
* ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
* outputStream.writeBytes("hello world".getBytes(StandardCharsets.UTF_8));
- *
* InputStream inputStream = IOUtils.copy(outputStream);
*
*
* @param outputStream the {@link ByteArrayOutputStream} to read.
* @return the {@link QueueInputStream} filled with the content of the outputStream.
* @throws NullPointerException if the {@link ByteArrayOutputStream} is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.12
*/
@SuppressWarnings("resource") // streams are closed by the caller.
@@ -1373,14 +1492,11 @@ public static QueueInputStream copy(final java.io.ByteArrayOutputStream outputSt
/**
* Copies chars from a {@link Reader} to a {@link Appendable}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
- * Large streams (over 2GB) will return a chars copied value of
- * {@code -1} after the copy has completed since the correct
- * number of chars cannot be returned as an int. For large streams
- * use the {@link #copyLarge(Reader, Writer)} method.
+ * Large streams (over 2GB) will return a chars copied value of {@code -1} after the copy has completed since the correct number of chars cannot be returned
+ * as an int. For large streams use the {@link #copyLarge(Reader, Writer)} method.
*
*
* @param reader the {@link Reader} to read.
@@ -1397,8 +1513,7 @@ public static long copy(final Reader reader, final Appendable output) throws IOE
/**
* Copies chars from a {@link Reader} to an {@link Appendable}.
*
- * This method uses the provided buffer, so there is no need to use a
- * {@link BufferedReader}.
+ * This method uses the provided buffer, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to read.
@@ -1421,7 +1536,7 @@ public static long copy(final Reader reader, final Appendable output, final Char
}
/**
- * Copies chars from a {@link Reader} to bytes on an {@link OutputStream} using the the virtual machine's {@link Charset#defaultCharset() default charset},
+ * Copies chars from a {@link Reader} to bytes on an {@link OutputStream} using the virtual machine's {@linkplain Charset#defaultCharset() default charset},
* and calling flush.
*
* This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
@@ -1438,7 +1553,7 @@ public static long copy(final Reader reader, final Appendable output, final Char
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
* @since 1.1
- * @deprecated Use {@link #copy(Reader, OutputStream, Charset)} instead
+ * @deprecated Use {@link #copy(Reader, OutputStream, Charset)} instead.
*/
@Deprecated
public static void copy(final Reader reader, final OutputStream output) throws IOException {
@@ -1478,7 +1593,7 @@ public static void copy(final Reader reader, final OutputStream output, final Ch
* This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
- * Character encoding names can be found at IANA.
+ * Character encoding names can be found at IANA.
*
*
* Due to the implementation of OutputStreamWriter, this method performs a flush.
@@ -1502,14 +1617,11 @@ public static void copy(final Reader reader, final OutputStream output, final St
/**
* Copies chars from a {@link Reader} to a {@link Writer}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
- * Large streams (over 2GB) will return a chars copied value of
- * {@code -1} after the copy has completed since the correct
- * number of chars cannot be returned as an int. For large streams
- * use the {@link #copyLarge(Reader, Writer)} method.
+ * Large streams (over 2GB) will return a chars copied value of {@code -1} after the copy has completed since the correct number of chars cannot be returned
+ * as an int. For large streams use the {@link #copyLarge(Reader, Writer)} method.
*
*
* @param reader the {@link Reader} to read.
@@ -1536,12 +1648,12 @@ public static int copy(final Reader reader, final Writer writer) throws IOExcept
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
*
- * @param url the {@link URL} to read.
+ * @param url the {@link URL} to read.
* @param file the {@link OutputStream} to write.
* @return the number of bytes copied.
* @throws NullPointerException if the URL is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.9.0
*/
public static long copy(final URL url, final File file) throws IOException {
@@ -1559,12 +1671,12 @@ public static long copy(final URL url, final File file) throws IOException {
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
*
- * @param url the {@link URL} to read.
+ * @param url the {@link URL} to read.
* @param outputStream the {@link OutputStream} to write.
* @return the number of bytes copied.
* @throws NullPointerException if the URL is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.9.0
*/
public static long copy(final URL url, final OutputStream outputStream) throws IOException {
@@ -1574,49 +1686,43 @@ public static long copy(final URL url, final OutputStream outputStream) throws I
}
/**
- * Copies bytes from a large (over 2GB) {@link InputStream} to an
- * {@link OutputStream}.
+ * Copies bytes from a large (over 2GB) {@link InputStream} to an {@link OutputStream}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
*
- * @param inputStream the {@link InputStream} to read.
+ * @param inputStream the {@link InputStream} to read.
* @param outputStream the {@link OutputStream} to write.
* @return the number of bytes copied.
* @throws NullPointerException if the InputStream is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 1.3
*/
- public static long copyLarge(final InputStream inputStream, final OutputStream outputStream)
- throws IOException {
+ public static long copyLarge(final InputStream inputStream, final OutputStream outputStream) throws IOException {
return copy(inputStream, outputStream, DEFAULT_BUFFER_SIZE);
}
/**
- * Copies bytes from a large (over 2GB) {@link InputStream} to an
- * {@link OutputStream}.
+ * Copies bytes from a large (over 2GB) {@link InputStream} to an {@link OutputStream}.
*
- * This method uses the provided buffer, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method uses the provided buffer, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param inputStream the {@link InputStream} to read.
+ * @param inputStream the {@link InputStream} to read.
* @param outputStream the {@link OutputStream} to write.
- * @param buffer the buffer to use for the copy
+ * @param buffer the buffer to use for the copy.
* @return the number of bytes copied.
* @throws NullPointerException if the InputStream is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.2
*/
@SuppressWarnings("resource") // streams are closed by the caller.
- public static long copyLarge(final InputStream inputStream, final OutputStream outputStream, final byte[] buffer)
- throws IOException {
+ public static long copyLarge(final InputStream inputStream, final OutputStream outputStream, final byte[] buffer) throws IOException {
Objects.requireNonNull(inputStream, "inputStream");
Objects.requireNonNull(outputStream, "outputStream");
long count = 0;
@@ -1629,58 +1735,53 @@ public static long copyLarge(final InputStream inputStream, final OutputStream o
}
/**
- * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an
- * {@link OutputStream}, optionally skipping input bytes.
+ * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an {@link OutputStream}, optionally skipping input bytes.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * Note that the implementation uses {@link #skip(InputStream, long)}.
- * This means that the method may be considerably less efficient than using the actual skip implementation,
- * this is done to guarantee that the correct number of characters are skipped.
+ * Note that the implementation uses {@link #skip(InputStream, long)}. This means that the method may be considerably less efficient than using the actual
+ * skip implementation, this is done to guarantee that the correct number of characters are skipped.
*
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
- * @param input the {@link InputStream} to read.
- * @param output the {@link OutputStream} to write.
+ * @param input the {@link InputStream} to read.
+ * @param output the {@link OutputStream} to write.
* @param inputOffset number of bytes to skip from input before copying, these bytes are ignored.
- * @param length number of bytes to copy.
+ * @param length number of bytes to copy.
* @return the number of bytes copied.
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
* @since 2.2
*/
- public static long copyLarge(final InputStream input, final OutputStream output, final long inputOffset,
- final long length) throws IOException {
- return copyLarge(input, output, inputOffset, length, getScratchByteArray());
+ public static long copyLarge(final InputStream input, final OutputStream output, final long inputOffset, final long length) throws IOException {
+ try (ScratchBytes scratch = ScratchBytes.get()) {
+ return copyLarge(input, output, inputOffset, length, scratch.array());
+ }
}
/**
- * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an
- * {@link OutputStream}, optionally skipping input bytes.
+ * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an {@link OutputStream}, optionally skipping input bytes.
*
- * This method uses the provided buffer, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method uses the provided buffer, so there is no need to use a {@link BufferedInputStream}.
*
*
- * Note that the implementation uses {@link #skip(InputStream, long)}.
- * This means that the method may be considerably less efficient than using the actual skip implementation,
- * this is done to guarantee that the correct number of characters are skipped.
+ * Note that the implementation uses {@link #skip(InputStream, long)}. This means that the method may be considerably less efficient than using the actual
+ * skip implementation, this is done to guarantee that the correct number of characters are skipped.
*
*
- * @param input the {@link InputStream} to read.
- * @param output the {@link OutputStream} to write.
+ * @param input the {@link InputStream} to read.
+ * @param output the {@link OutputStream} to write.
* @param inputOffset number of bytes to skip from input before copying, these bytes are ignored.
- * @param length number of bytes to copy.
- * @param buffer the buffer to use for the copy.
+ * @param length number of bytes to copy.
+ * @param buffer the buffer to use for the copy.
* @return the number of bytes copied.
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
* @since 2.2
*/
- public static long copyLarge(final InputStream input, final OutputStream output,
- final long inputOffset, final long length, final byte[] buffer) throws IOException {
+ public static long copyLarge(final InputStream input, final OutputStream output, final long inputOffset, final long length, final byte[] buffer)
+ throws IOException {
if (inputOffset > 0) {
skipFully(input, inputOffset);
}
@@ -1698,7 +1799,7 @@ public static long copyLarge(final InputStream input, final OutputStream output,
output.write(buffer, 0, read);
totalRead += read;
if (length > 0) { // only adjust length if not reading to the end
- // Note the cast must work because buffer.length is an integer
+ // Note the cast must work because bufferLength = buffer.length is an integer
bytesToRead = (int) Math.min(length - totalRead, bufferLength);
}
}
@@ -1708,8 +1809,7 @@ public static long copyLarge(final InputStream input, final OutputStream output,
/**
* Copies chars from a large (over 2GB) {@link Reader} to a {@link Writer}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
@@ -1723,22 +1823,23 @@ public static long copyLarge(final InputStream input, final OutputStream output,
* @since 1.3
*/
public static long copyLarge(final Reader reader, final Writer writer) throws IOException {
- return copyLarge(reader, writer, getScratchCharArray());
+ try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
+ return copyLarge(reader, writer, scratch.array());
+ }
}
/**
* Copies chars from a large (over 2GB) {@link Reader} to a {@link Writer}.
*
- * This method uses the provided buffer, so there is no need to use a
- * {@link BufferedReader}.
+ * This method uses the provided buffer, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to source.
* @param writer the {@link Writer} to target.
- * @param buffer the buffer to be used for the copy
- * @return the number of characters copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
+ * @param buffer the buffer to be used for the copy.
+ * @return the number of characters copied.
+ * @throws NullPointerException if the input or output is null.
+ * @throws IOException if an I/O error occurs.
* @since 2.2
*/
public static long copyLarge(final Reader reader, final Writer writer, final char[] buffer) throws IOException {
@@ -1770,7 +1871,9 @@ public static long copyLarge(final Reader reader, final Writer writer, final cha
* @since 2.2
*/
public static long copyLarge(final Reader reader, final Writer writer, final long inputOffset, final long length) throws IOException {
- return copyLarge(reader, writer, inputOffset, length, getScratchCharArray());
+ try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
+ return copyLarge(reader, writer, inputOffset, length, scratch.array());
+ }
}
/**
@@ -1817,84 +1920,18 @@ public static long copyLarge(final Reader reader, final Writer writer, final lon
* Copies up to {@code size} bytes from the given {@link InputStream} into a new {@link UnsynchronizedByteArrayOutputStream}.
*
* @param input The {@link InputStream} to read; must not be {@code null}.
- * @param limit The maximum number of bytes to read; must be {@code >= 0}.
- * The actual bytes read are validated to equal {@code size}.
+ * @param limit The maximum number of bytes to read; must be {@code >= 0}. The actual bytes read are validated to equal {@code size}.
* @param bufferSize The buffer size of the output stream; must be {@code > 0}.
* @return a ByteArrayOutputStream containing the read bytes.
*/
- static UnsynchronizedByteArrayOutputStream copyToOutputStream(
- final InputStream input, final long limit, final int bufferSize) throws IOException {
- try (UnsynchronizedByteArrayOutputStream output = UnsynchronizedByteArrayOutputStream.builder()
- .setBufferSize(bufferSize)
- .get();
- InputStream boundedInput = BoundedInputStream.builder()
- .setMaxCount(limit)
- .setPropagateClose(false)
- .setInputStream(input)
- .get()) {
+ static UnsynchronizedByteArrayOutputStream copyToOutputStream(final InputStream input, final long limit, final int bufferSize) throws IOException {
+ try (UnsynchronizedByteArrayOutputStream output = UnsynchronizedByteArrayOutputStream.builder().setBufferSize(bufferSize).get();
+ InputStream boundedInput = BoundedInputStream.builder().setMaxCount(limit).setPropagateClose(false).setInputStream(input).get()) {
output.write(boundedInput);
return output;
}
}
- /**
- * Fills the given array with 0s.
- *
- * @param arr The non-null array to fill.
- * @return The given array.
- */
- private static byte[] fill0(final byte[] arr) {
- Arrays.fill(arr, (byte) 0);
- return arr;
- }
-
- /**
- * Fills the given array with 0s.
- *
- * @param arr The non-null array to fill.
- * @return The given array.
- */
- private static char[] fill0(final char[] arr) {
- Arrays.fill(arr, (char) 0);
- return arr;
- }
-
- /**
- * Gets the internal byte array buffer, intended for both reading and writing.
- *
- * @return the internal byte array buffer, intended for both reading and writing.
- */
- static byte[] getScratchByteArray() {
- return fill0(SCRATCH_BYTE_BUFFER_RW.get());
- }
-
- /**
- * Gets the internal byte array intended for write only operations.
- *
- * @return the internal byte array intended for write only operations.
- */
- static byte[] getScratchByteArrayWriteOnly() {
- return fill0(SCRATCH_BYTE_BUFFER_WO);
- }
-
- /**
- * Gets the char byte array buffer, intended for both reading and writing.
- *
- * @return the char byte array buffer, intended for both reading and writing.
- */
- static char[] getScratchCharArray() {
- return fill0(SCRATCH_CHAR_BUFFER_RW.get());
- }
-
- /**
- * Gets the internal char array intended for write only operations.
- *
- * @return the internal char array intended for write only operations.
- */
- static char[] getScratchCharArrayWriteOnly() {
- return fill0(SCRATCH_CHAR_BUFFER_WO);
- }
-
/**
* Returns the length of the given array in a null-safe manner.
*
@@ -1940,31 +1977,29 @@ public static int length(final Object[] array) {
}
/**
- * Returns an Iterator for the lines in an {@link InputStream}, using
- * the character encoding specified (or default encoding if null).
+ * Returns an Iterator for the lines in an {@link InputStream}, using the character encoding specified (or default encoding if null).
*
- * {@link LineIterator} holds a reference to the open
- * {@link InputStream} specified here. When you have finished with
- * the iterator you should close the stream to free internal resources.
- * This can be done by using a try-with-resources block, closing the stream directly, or by calling
+ * {@link LineIterator} holds a reference to the open {@link InputStream} specified here. When you have finished with the iterator you should close the
+ * stream to free internal resources. This can be done by using a try-with-resources block, closing the stream directly, or by calling
* {@link LineIterator#close()}.
*
*
* The recommended usage pattern is:
*
+ *
*
* try {
- * LineIterator it = IOUtils.lineIterator(stream, charset);
- * while (it.hasNext()) {
- * String line = it.nextLine();
- * /// do something with line
- * }
+ * LineIterator it = IOUtils.lineIterator(stream, charset);
+ * while (it.hasNext()) {
+ * String line = it.nextLine();
+ * /// do something with line
+ * }
* } finally {
- * IOUtils.closeQuietly(stream);
+ * IOUtils.closeQuietly(stream);
* }
*
*
- * @param input the {@link InputStream} to read, not null.
+ * @param input the {@link InputStream} to read, not null.
* @param charset the charset to use, null means platform default.
* @return an Iterator of the lines in the reader, never null.
* @throws IllegalArgumentException if the input is null.
@@ -1975,31 +2010,29 @@ public static LineIterator lineIterator(final InputStream input, final Charset c
}
/**
- * Returns an Iterator for the lines in an {@link InputStream}, using
- * the character encoding specified (or default encoding if null).
+ * Returns an Iterator for the lines in an {@link InputStream}, using the character encoding specified (or default encoding if null).
*
- * {@link LineIterator} holds a reference to the open
- * {@link InputStream} specified here. When you have finished with
- * the iterator you should close the stream to free internal resources.
- * This can be done by using a try-with-resources block, closing the stream directly, or by calling
+ * {@link LineIterator} holds a reference to the open {@link InputStream} specified here. When you have finished with the iterator you should close the
+ * stream to free internal resources. This can be done by using a try-with-resources block, closing the stream directly, or by calling
* {@link LineIterator#close()}.
*
*
* The recommended usage pattern is:
*
+ *
*
* try {
- * LineIterator it = IOUtils.lineIterator(stream, StandardCharsets.UTF_8.name());
- * while (it.hasNext()) {
- * String line = it.nextLine();
- * /// do something with line
- * }
+ * LineIterator it = IOUtils.lineIterator(stream, StandardCharsets.UTF_8.name());
+ * while (it.hasNext()) {
+ * String line = it.nextLine();
+ * /// do something with line
+ * }
* } finally {
- * IOUtils.closeQuietly(stream);
+ * IOUtils.closeQuietly(stream);
* }
*
*
- * @param input the {@link InputStream} to read, not null.
+ * @param input the {@link InputStream} to read, not null.
* @param charsetName the encoding to use, null means platform default.
* @return an Iterator of the lines in the reader, never null.
* @throws IllegalArgumentException if the input is null.
@@ -2013,24 +2046,22 @@ public static LineIterator lineIterator(final InputStream input, final String ch
/**
* Returns an Iterator for the lines in a {@link Reader}.
*
- * {@link LineIterator} holds a reference to the open
- * {@link Reader} specified here. When you have finished with the
- * iterator you should close the reader to free internal resources.
- * This can be done by using a try-with-resources block, closing the reader directly, or by calling
- * {@link LineIterator#close()}.
+ * {@link LineIterator} holds a reference to the open {@link Reader} specified here. When you have finished with the iterator you should close the reader to
+ * free internal resources. This can be done by using a try-with-resources block, closing the reader directly, or by calling {@link LineIterator#close()}.
*
*
* The recommended usage pattern is:
*
+ *
*
* try {
- * LineIterator it = IOUtils.lineIterator(reader);
- * while (it.hasNext()) {
- * String line = it.nextLine();
- * /// do something with line
- * }
+ * LineIterator it = IOUtils.lineIterator(reader);
+ * while (it.hasNext()) {
+ * String line = it.nextLine();
+ * /// do something with line
+ * }
* } finally {
- * IOUtils.closeQuietly(reader);
+ * IOUtils.closeQuietly(reader);
* }
*
*
@@ -2046,15 +2077,15 @@ public static LineIterator lineIterator(final Reader reader) {
/**
* Reads bytes from an input stream.
*
- * This implementation guarantees that it will read as many bytes
- * as possible before giving up; this may not always be the case for
- * subclasses of {@link InputStream}.
+ * This implementation guarantees that it will read as many bytes as possible before giving up; this may not always be the case for subclasses of
+ * {@link InputStream}.
*
*
- * @param input where to read input from.
+ * @param input where to read input from.
* @param buffer destination.
* @return actual length read; may be less than requested if EOF was reached.
- * @throws IOException if a read error occurs.
+ * @throws NullPointerException if {@code input} or {@code buffer} is null.
+ * @throws IOException if a read error occurs.
* @since 2.2
*/
public static int read(final InputStream input, final byte[] buffer) throws IOException {
@@ -2064,50 +2095,26 @@ public static int read(final InputStream input, final byte[] buffer) throws IOEx
/**
* Reads bytes from an input stream.
*
- * This implementation guarantees that it will read as many bytes
- * as possible before giving up; this may not always be the case for
- * subclasses of {@link InputStream}.
+ * This implementation guarantees that it will read as many bytes as possible before giving up; this may not always be the case for subclasses of
+ * {@link InputStream}.
*
*
- * @param input where to read input.
+ * @param input where to read input.
* @param buffer destination.
* @param offset initial offset into buffer.
* @param length length to read, must be >= 0.
* @return actual length read; may be less than requested if EOF was reached.
- * @throws IllegalArgumentException if length is negative.
- * @throws IOException if a read error occurs.
+ * @throws NullPointerException if {@code input} or {@code buffer} is null.
+ * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if {@code offset + length} is greater than {@code buffer.length}.
+ * @throws IOException if a read error occurs.
* @since 2.2
*/
- public static int read(final InputStream input, final byte[] buffer, final int offset, final int length)
- throws IOException {
- if (length == 0) {
- return 0;
- }
- return read(input::read, buffer, offset, length);
- }
-
- /**
- * Reads bytes from an input. This implementation guarantees that it will read as many bytes as possible before giving up; this may not always be the case
- * for subclasses of {@link InputStream}.
- *
- * @param input How to read input.
- * @param buffer destination.
- * @param offset initial offset into buffer.
- * @param length length to read, must be >= 0.
- * @return actual length read; may be less than requested if EOF was reached.
- * @throws IllegalArgumentException if length is negative.
- * @throws IOException if a read error occurs.
- * @since 2.2
- */
- static int read(final IOTriFunction input, final byte[] buffer, final int offset, final int length)
- throws IOException {
- if (length < 0) {
- throw new IllegalArgumentException("Length must not be negative: " + length);
- }
+ public static int read(final InputStream input, final byte[] buffer, final int offset, final int length) throws IOException {
+ checkFromIndexSize(buffer, offset, length);
int remaining = length;
while (remaining > 0) {
final int location = length - remaining;
- final int count = input.apply(buffer, offset + location, remaining);
+ final int count = input.read(buffer, offset + location, remaining);
if (EOF == count) {
break;
}
@@ -2119,12 +2126,11 @@ static int read(final IOTriFunction input, fi
/**
* Reads bytes from a ReadableByteChannel.
*
- * This implementation guarantees that it will read as many bytes
- * as possible before giving up; this may not always be the case for
- * subclasses of {@link ReadableByteChannel}.
+ * This implementation guarantees that it will read as many bytes as possible before giving up; this may not always be the case for subclasses of
+ * {@link ReadableByteChannel}.
*
*
- * @param input the byte channel to read.
+ * @param input the byte channel to read.
* @param buffer byte buffer destination.
* @return the actual length read; may be less than requested if EOF was reached.
* @throws IOException if a read error occurs.
@@ -2144,9 +2150,8 @@ public static int read(final ReadableByteChannel input, final ByteBuffer buffer)
/**
* Reads characters from an input character stream.
*
- * This implementation guarantees that it will read as many characters
- * as possible before giving up; this may not always be the case for
- * subclasses of {@link Reader}.
+ * This implementation guarantees that it will read as many characters as possible before giving up; this may not always be the case for subclasses of
+ * {@link Reader}.
*
*
* @param reader where to read input from.
@@ -2162,9 +2167,8 @@ public static int read(final Reader reader, final char[] buffer) throws IOExcept
/**
* Reads characters from an input character stream.
*
- * This implementation guarantees that it will read as many characters
- * as possible before giving up; this may not always be the case for
- * subclasses of {@link Reader}.
+ * This implementation guarantees that it will read as many characters as possible before giving up; this may not always be the case for subclasses of
+ * {@link Reader}.
*
*
* @param reader where to read input from.
@@ -2172,15 +2176,13 @@ public static int read(final Reader reader, final char[] buffer) throws IOExcept
* @param offset initial offset into buffer.
* @param length length to read, must be >= 0.
* @return actual length read; may be less than requested if EOF was reached.
- * @throws IllegalArgumentException if length is negative.
- * @throws IOException if a read error occurs.
+ * @throws NullPointerException if {@code reader} or {@code buffer} is null.
+ * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if {@code offset + length} is greater than {@code buffer.length}.
+ * @throws IOException if a read error occurs.
* @since 2.2
*/
- public static int read(final Reader reader, final char[] buffer, final int offset, final int length)
- throws IOException {
- if (length < 0) {
- throw new IllegalArgumentException("Length must not be negative: " + length);
- }
+ public static int read(final Reader reader, final char[] buffer, final int offset, final int length) throws IOException {
+ checkFromIndexSize(buffer, offset, length);
int remaining = length;
while (remaining > 0) {
final int location = length - remaining;
@@ -2196,15 +2198,15 @@ public static int read(final Reader reader, final char[] buffer, final int offse
/**
* Reads the requested number of bytes or fail if there are not enough left.
*
- * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
- * not read as many bytes as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may not read as many bytes as requested (most likely because of reaching
+ * EOF).
*
*
- * @param input where to read input from.
+ * @param input where to read input from.
* @param buffer destination.
- * @throws IOException if there is a problem reading the file.
- * @throws IllegalArgumentException if length is negative.
- * @throws EOFException if the number of bytes read was incorrect.
+ * @throws NullPointerException if {@code input} or {@code buffer} is null.
+ * @throws EOFException if the number of bytes read was incorrect.
+ * @throws IOException if there is a problem reading the file.
* @since 2.2
*/
public static void readFully(final InputStream input, final byte[] buffer) throws IOException {
@@ -2214,21 +2216,21 @@ public static void readFully(final InputStream input, final byte[] buffer) throw
/**
* Reads the requested number of bytes or fail if there are not enough left.
*
- * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
- * not read as many bytes as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may not read as many bytes as requested (most likely because of reaching
+ * EOF).
*
*
- * @param input where to read input from.
+ * @param input where to read input from.
* @param buffer destination.
* @param offset initial offset into buffer.
* @param length length to read, must be >= 0.
- * @throws IOException if there is a problem reading the file.
- * @throws IllegalArgumentException if length is negative.
- * @throws EOFException if the number of bytes read was incorrect.
+ * @throws NullPointerException if {@code input} or {@code buffer} is null.
+ * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if {@code offset + length} is greater than {@code buffer.length}.
+ * @throws EOFException if the number of bytes read was incorrect.
+ * @throws IOException if there is a problem reading the file.
* @since 2.2
*/
- public static void readFully(final InputStream input, final byte[] buffer, final int offset, final int length)
- throws IOException {
+ public static void readFully(final InputStream input, final byte[] buffer, final int offset, final int length) throws IOException {
final int actual = read(input, buffer, offset, length);
if (actual != length) {
throw new EOFException("Length to read: " + length + " actual: " + actual);
@@ -2238,11 +2240,11 @@ public static void readFully(final InputStream input, final byte[] buffer, final
/**
* Reads the requested number of bytes or fail if there are not enough left.
*
- * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
- * not read as many bytes as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may not read as many bytes as requested (most likely because of reaching
+ * EOF).
*
*
- * @param input where to read input from.
+ * @param input where to read input from.
* @param length length to read, must be >= 0.
* @return the bytes read from input.
* @throws IOException if there is a problem reading the file.
@@ -2259,11 +2261,11 @@ public static byte[] readFully(final InputStream input, final int length) throws
/**
* Reads the requested number of bytes or fail if there are not enough left.
*
- * This allows for the possibility that {@link ReadableByteChannel#read(ByteBuffer)} may
- * not read as many bytes as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link ReadableByteChannel#read(ByteBuffer)} may not read as many bytes as requested (most likely because of
+ * reaching EOF).
*
*
- * @param input the byte channel to read.
+ * @param input the byte channel to read.
* @param buffer byte buffer destination.
* @throws IOException if there is a problem reading the file.
* @throws EOFException if the number of bytes read was incorrect.
@@ -2280,15 +2282,15 @@ public static void readFully(final ReadableByteChannel input, final ByteBuffer b
/**
* Reads the requested number of characters or fail if there are not enough left.
*
- * This allows for the possibility that {@link Reader#read(char[], int, int)} may
- * not read as many characters as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link Reader#read(char[], int, int)} may not read as many characters as requested (most likely because of reaching
+ * EOF).
*
*
* @param reader where to read input from.
* @param buffer destination.
- * @throws IOException if there is a problem reading the file.
- * @throws IllegalArgumentException if length is negative.
- * @throws EOFException if the number of characters read was incorrect.
+ * @throws NullPointerException if {@code reader} or {@code buffer} is null.
+ * @throws EOFException if the number of characters read was incorrect.
+ * @throws IOException if there is a problem reading the file.
* @since 2.2
*/
public static void readFully(final Reader reader, final char[] buffer) throws IOException {
@@ -2298,21 +2300,21 @@ public static void readFully(final Reader reader, final char[] buffer) throws IO
/**
* Reads the requested number of characters or fail if there are not enough left.
*
- * This allows for the possibility that {@link Reader#read(char[], int, int)} may
- * not read as many characters as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link Reader#read(char[], int, int)} may not read as many characters as requested (most likely because of reaching
+ * EOF).
*
*
* @param reader where to read input from.
* @param buffer destination.
* @param offset initial offset into buffer.
* @param length length to read, must be >= 0.
- * @throws IOException if there is a problem reading the file.
- * @throws IllegalArgumentException if length is negative.
- * @throws EOFException if the number of characters read was incorrect.
+ * @throws NullPointerException if {@code reader} or {@code buffer} is null.
+ * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if {@code offset + length} is greater than {@code buffer.length}.
+ * @throws EOFException if the number of characters read was incorrect.
+ * @throws IOException if there is a problem reading the file.
* @since 2.2
*/
- public static void readFully(final Reader reader, final char[] buffer, final int offset, final int length)
- throws IOException {
+ public static void readFully(final Reader reader, final char[] buffer, final int offset, final int length) throws IOException {
final int actual = read(reader, buffer, offset, length);
if (actual != length) {
throw new EOFException("Length to read: " + length + " actual: " + actual);
@@ -2334,11 +2336,10 @@ public static List readLines(final CharSequence csq) throws UncheckedIOE
}
/**
- * Gets the contents of an {@link InputStream} as a list of Strings,
- * one entry per line, using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of an {@link InputStream} as a list of Strings, one entry per line, using the virtual machine's {@linkplain Charset#defaultCharset()
+ * default charset}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* @param input the {@link InputStream} to read, not null.
@@ -2346,7 +2347,7 @@ public static List readLines(final CharSequence csq) throws UncheckedIOE
* @throws NullPointerException if the input is null.
* @throws UncheckedIOException if an I/O error occurs.
* @since 1.1
- * @deprecated Use {@link #readLines(InputStream, Charset)} instead
+ * @deprecated Use {@link #readLines(InputStream, Charset)} instead.
*/
@Deprecated
public static List readLines(final InputStream input) throws UncheckedIOException {
@@ -2354,14 +2355,12 @@ public static List readLines(final InputStream input) throws UncheckedIO
}
/**
- * Gets the contents of an {@link InputStream} as a list of Strings,
- * one entry per line, using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a list of Strings, one entry per line, using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input the {@link InputStream} to read, not null.
+ * @param input the {@link InputStream} to read, not null.
* @param charset the charset to use, null means platform default.
* @return the list of Strings, never null.
* @throws NullPointerException if the input is null.
@@ -2373,18 +2372,15 @@ public static List readLines(final InputStream input, final Charset char
}
/**
- * Gets the contents of an {@link InputStream} as a list of Strings,
- * one entry per line, using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a list of Strings, one entry per line, using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input the {@link InputStream} to read, not null.
+ * @param input the {@link InputStream} to read, not null.
* @param charsetName the name of the requested charset, null means platform default.
* @return the list of Strings, never null.
* @throws NullPointerException if the input is null.
@@ -2397,11 +2393,9 @@ public static List readLines(final InputStream input, final String chars
}
/**
- * Gets the contents of a {@link Reader} as a list of Strings,
- * one entry per line.
+ * Gets the contents of a {@link Reader} as a list of Strings, one entry per line.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to read, not null.
@@ -2437,7 +2431,7 @@ public static byte[] resourceToByteArray(final String name) throws IOException {
* Delegates to {@link #resourceToURL(String, ClassLoader)}.
*
*
- * @param name The resource name.
+ * @param name The resource name.
* @param classLoader the class loader that the resolution of the resource is delegated to.
* @return the requested byte array.
* @throws IOException if an I/O error occurs or the resource is not found.
@@ -2454,7 +2448,7 @@ public static byte[] resourceToByteArray(final String name, final ClassLoader cl
* Delegates to {@link #resourceToString(String, Charset, ClassLoader) resourceToString(String, Charset, null)}.
*
*
- * @param name The resource name.
+ * @param name The resource name.
* @param charset the charset to use, null means platform default.
* @return the requested String.
* @throws IOException if an I/O error occurs or the resource is not found.
@@ -2471,8 +2465,8 @@ public static String resourceToString(final String name, final Charset charset)
* Delegates to {@link #resourceToURL(String, ClassLoader)}.
*
*
- * @param name The resource name.
- * @param charset the Charset to use, null means platform default.
+ * @param name The resource name.
+ * @param charset the Charset to use, null means platform default.
* @param classLoader the class loader that the resolution of the resource is delegated to.
* @return the requested String.
* @throws IOException if an I/O error occurs.
@@ -2501,11 +2495,11 @@ public static URL resourceToURL(final String name) throws IOException {
/**
* Gets a URL pointing to the given resource.
*
- * If the {@code classLoader} is not null, call {@link ClassLoader#getResource(String)}, otherwise call
- * {@link Class#getResource(String) IOUtils.class.getResource(name)}.
+ * If the {@code classLoader} is not null, call {@link ClassLoader#getResource(String)}, otherwise call {@link Class#getResource(String)
+ * IOUtils.class.getResource(name)}.
*
*
- * @param name The resource name.
+ * @param name The resource name.
* @param classLoader Delegate to this class loader if not null.
* @return A URL object for reading the resource.
* @throws IOException if the resource is not found.
@@ -2543,7 +2537,9 @@ public static URL resourceToURL(final String name, final ClassLoader classLoader
* @since 2.0
*/
public static long skip(final InputStream input, final long skip) throws IOException {
- return skip(input, skip, IOUtils::getScratchByteArrayWriteOnly);
+ try (ScratchBytes scratch = ScratchBytes.get()) {
+ return skip(input, skip, scratch::array);
+ }
}
/**
@@ -2563,7 +2559,7 @@ public static long skip(final InputStream input, final long skip) throws IOExcep
*
*
* @param input byte stream to skip.
- * @param skip number of bytes to skip.
+ * @param skip number of bytes to skip.
* @param skipBufferSupplier Supplies the buffer to use for reading.
* @return number of bytes actually skipped.
* @throws IOException if there is a problem reading the file.
@@ -2595,11 +2591,9 @@ public static long skip(final InputStream input, final long skip, final Supplier
}
/**
- * Skips bytes from a ReadableByteChannel.
- * This implementation guarantees that it will read as many bytes
- * as possible before giving up.
+ * Skips bytes from a ReadableByteChannel. This implementation guarantees that it will read as many bytes as possible before giving up.
*
- * @param input ReadableByteChannel to skip.
+ * @param input ReadableByteChannel to skip.
* @param toSkip number of bytes to skip.
* @return number of bytes actually skipped.
* @throws IOException if there is a problem reading the ReadableByteChannel.
@@ -2625,15 +2619,12 @@ public static long skip(final ReadableByteChannel input, final long toSkip) thro
}
/**
- * Skips characters from an input character stream.
- * This implementation guarantees that it will read as many characters
- * as possible before giving up; this may not always be the case for
- * skip() implementations in subclasses of {@link Reader}.
+ * Skips characters from an input character stream. This implementation guarantees that it will read as many characters as possible before giving up; this
+ * may not always be the case for skip() implementations in subclasses of {@link Reader}.
*
- * Note that the implementation uses {@link Reader#read(char[], int, int)} rather
- * than delegating to {@link Reader#skip(long)}.
- * This means that the method may be considerably less efficient than using the actual skip implementation,
- * this is done to guarantee that the correct number of characters are skipped.
+ * Note that the implementation uses {@link Reader#read(char[], int, int)} rather than delegating to {@link Reader#skip(long)}. This means that the method
+ * may be considerably less efficient than using the actual skip implementation, this is done to guarantee that the correct number of characters are
+ * skipped.
*
*
* @param reader character stream to skip.
@@ -2650,14 +2641,16 @@ public static long skip(final Reader reader, final long toSkip) throws IOExcepti
throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip);
}
long remain = toSkip;
- while (remain > 0) {
- // See https://issues.apache.org/jira/browse/IO-203 for why we use read() rather than delegating to skip()
- final char[] charArray = getScratchCharArrayWriteOnly();
- final long n = reader.read(charArray, 0, (int) Math.min(remain, charArray.length));
- if (n < 0) { // EOF
- break;
+ try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
+ final char[] chars = scratch.array();
+ while (remain > 0) {
+ // See https://issues.apache.org/jira/browse/IO-203 for why we use read() rather than delegating to skip()
+ final long n = reader.read(chars, 0, (int) Math.min(remain, chars.length));
+ if (n < 0) { // EOF
+ break;
+ }
+ remain -= n;
}
- remain -= n;
}
return toSkip - remain;
}
@@ -2665,16 +2658,14 @@ public static long skip(final Reader reader, final long toSkip) throws IOExcepti
/**
* Skips the requested number of bytes or fail if there are not enough left.
*
- * This allows for the possibility that {@link InputStream#skip(long)} may
- * not skip as many bytes as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link InputStream#skip(long)} may not skip as many bytes as requested (most likely because of reaching EOF).
*
*
- * Note that the implementation uses {@link #skip(InputStream, long)}.
- * This means that the method may be considerably less efficient than using the actual skip implementation,
- * this is done to guarantee that the correct number of characters are skipped.
+ * Note that the implementation uses {@link #skip(InputStream, long)}. This means that the method may be considerably less efficient than using the actual
+ * skip implementation, this is done to guarantee that the correct number of characters are skipped.
*
*
- * @param input stream to skip.
+ * @param input stream to skip.
* @param toSkip the number of bytes to skip.
* @throws IOException if there is a problem reading the file.
* @throws IllegalArgumentException if toSkip is negative.
@@ -2683,7 +2674,7 @@ public static long skip(final Reader reader, final long toSkip) throws IOExcepti
* @since 2.0
*/
public static void skipFully(final InputStream input, final long toSkip) throws IOException {
- final long skipped = skip(input, toSkip, IOUtils::getScratchByteArrayWriteOnly);
+ final long skipped = skip(input, toSkip);
if (skipped != toSkip) {
throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped);
}
@@ -2725,7 +2716,7 @@ public static void skipFully(final InputStream input, final long toSkip, final S
/**
* Skips the requested number of bytes or fail if there are not enough left.
*
- * @param input ReadableByteChannel to skip.
+ * @param input ReadableByteChannel to skip.
* @param toSkip the number of bytes to skip.
* @throws IOException if there is a problem reading the ReadableByteChannel.
* @throws IllegalArgumentException if toSkip is negative.
@@ -2745,13 +2736,11 @@ public static void skipFully(final ReadableByteChannel input, final long toSkip)
/**
* Skips the requested number of characters or fail if there are not enough left.
*
- * This allows for the possibility that {@link Reader#skip(long)} may
- * not skip as many characters as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link Reader#skip(long)} may not skip as many characters as requested (most likely because of reaching EOF).
*
*
- * Note that the implementation uses {@link #skip(Reader, long)}.
- * This means that the method may be considerably less efficient than using the actual skip implementation,
- * this is done to guarantee that the correct number of characters are skipped.
+ * Note that the implementation uses {@link #skip(Reader, long)}. This means that the method may be considerably less efficient than using the actual skip
+ * implementation, this is done to guarantee that the correct number of characters are skipped.
*
*
* @param reader stream to skip.
@@ -2780,7 +2769,9 @@ public static void skipFully(final Reader reader, final long toSkip) throws IOEx
* It has network timeout associated.
*
*
- * It can be used in favor of {@link #toByteArray(InputStream)}, since it avoids unnecessary allocation and copy of byte[].
+ * It can be used in favor of {@link #toByteArray(InputStream)}, since it avoids unnecessary allocation and copy of byte[].
+ *
+ *
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
@@ -2804,7 +2795,9 @@ public static InputStream toBufferedInputStream(final InputStream input) throws
* It has network timeout associated.
*
*
- * It can be used in favor of {@link #toByteArray(InputStream)}, since it avoids unnecessary allocation and copy of byte[].
+ * It can be used in favor of {@link #toByteArray(InputStream)}, since it avoids unnecessary allocation and copy of byte[].
+ *
+ *
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
@@ -2819,8 +2812,7 @@ public static InputStream toBufferedInputStream(final InputStream input, final i
}
/**
- * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given
- * reader.
+ * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given reader.
*
* @param reader the reader to wrap or return (not null).
* @return the given reader or a new {@link BufferedReader} for the given reader.
@@ -2833,11 +2825,10 @@ public static BufferedReader toBufferedReader(final Reader reader) {
}
/**
- * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given
- * reader.
+ * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given reader.
*
* @param reader the reader to wrap or return (not null).
- * @param size the buffer size, if a new BufferedReader is created.
+ * @param size the buffer size, if a new BufferedReader is created.
* @return the given reader or a new {@link BufferedReader} for the given reader.
* @throws NullPointerException if the input parameter is null.
* @see #buffer(Reader)
@@ -2849,16 +2840,15 @@ public static BufferedReader toBufferedReader(final Reader reader, final int siz
/**
* Reads all the bytes from an input stream in a byte array.
- *
- * The memory used by this method is proportional to the number
- * of bytes read, which is only limited by {@link Integer#MAX_VALUE}. Only streams
- * which fit into a single byte array with roughly 2 GiB limit can be processed
- * with this method.
+ *
+ * The memory used by this method is proportional to the number of bytes read, which is only limited by {@link Integer#MAX_VALUE}. Only
+ * streams which fit into a single byte array with roughly 2 GiB limit can be processed with this method.
+ *
*
* @param inputStream The {@link InputStream} to read; must not be {@code null}.
* @return A new byte array.
- * @throws IOException If an I/O error occurs while reading or if the maximum array size is exceeded.
- * @throws NullPointerException If {@code inputStream} is {@code null}.
+ * @throws IOException If an I/O error occurs while reading or if the maximum array size is exceeded.
+ * @throws NullPointerException If {@code inputStream} is {@code null}.
*/
public static byte[] toByteArray(final InputStream inputStream) throws IOException {
// Using SOFT_MAX_ARRAY_LENGTH guarantees that size() will not overflow
@@ -2871,10 +2861,10 @@ public static byte[] toByteArray(final InputStream inputStream) throws IOExcepti
/**
* Reads exactly {@code size} bytes from the given {@link InputStream} into a new {@code byte[]}.
- *
- * This variant always allocates the whole requested array size,
- * for a dynamic growing variant use {@link #toByteArray(InputStream, int, int)},
- * which enforces stricter memory usage constraints.
+ *
+ * This variant always allocates the whole requested array size, for a dynamic growing variant use {@link #toByteArray(InputStream, int, int)}, which
+ * enforces stricter memory usage constraints.
+ *
*
* @param input the {@link InputStream} to read; must not be {@code null}.
* @param size the exact number of bytes to read; must be {@code >= 0}.
@@ -2891,19 +2881,17 @@ public static byte[] toByteArray(final InputStream input, final int size) throws
/**
* Reads exactly {@code size} bytes from the given {@link InputStream} into a new {@code byte[]}.
+ *
+ * The memory used by this method is proportional to the number of bytes read and limited by the specified {@code size}. This makes it
+ * suitable for processing large input streams, provided that sufficient heap space is available.
+ *
+ *
+ * This method processes the input stream in successive chunks of up to {@code chunkSize} bytes.
+ *
*
- * The memory used by this method is proportional to the number
- * of bytes read and limited by the specified {@code size}. This makes it suitable for
- * processing large input streams, provided that sufficient heap space is
- * available.
- *
- * This method processes the input stream in successive chunks of up to
- * {@code chunkSize} bytes.
- *
- * @param input the {@link InputStream} to read; must not be {@code null}.
- * @param size the exact number of bytes to read; must be {@code >= 0}.
- * The actual bytes read are validated to equal {@code size}.
- * @param chunkSize The chunk size for incremental reading; must be {@code > 0}.
+ * @param input the {@link InputStream} to read; must not be {@code null}.
+ * @param size the exact number of bytes to read; must be {@code >= 0}. The actual bytes read are validated to equal {@code size}.
+ * @param chunkSize The chunk size for incremental reading; must be {@code > 0}.
* @return a new byte array of length {@code size}.
* @throws IllegalArgumentException if {@code size} is negative or {@code chunkSize <= 0}.
* @throws EOFException if the stream ends before {@code size} bytes are read.
@@ -2914,25 +2902,26 @@ public static byte[] toByteArray(final InputStream input, final int size) throws
public static byte[] toByteArray(final InputStream input, final int size, final int chunkSize) throws IOException {
Objects.requireNonNull(input, "input");
if (chunkSize <= 0) {
- throw new IllegalArgumentException("Chunk size must be greater than zero: " + chunkSize);
+ throw new IllegalArgumentException(String.format("chunkSize <= 0, chunkSize = %,d", chunkSize));
}
if (size <= chunkSize) {
// throws if size < 0
return toByteArray(input::read, size);
}
final UnsynchronizedByteArrayOutputStream output = copyToOutputStream(input, size, chunkSize);
- if (output.size() != size) {
- throw new EOFException("Unexpected read size, current: " + output.size() + ", expected: " + size);
+ final int outSize = output.size();
+ if (outSize != size) {
+ throw new EOFException(String.format("Expected read size: %,d, actual: %,d", size, outSize));
}
return output.toByteArray();
}
/**
* Reads exactly {@code size} bytes from the given {@link InputStream} into a new {@code byte[]}.
- *
- * This variant always allocates the whole requested array size,
- * for a dynamic growing variant use {@link #toByteArray(InputStream, int, int)},
- * which enforces stricter memory usage constraints.
+ *
+ * This variant always allocates the whole requested array size, for a dynamic growing variant use {@link #toByteArray(InputStream, int, int)}, which
+ * enforces stricter memory usage constraints.
+ *
*
* @param input the {@link InputStream} to read; must not be {@code null}.
* @param size the exact number of bytes to read; must be {@code >= 0} and {@code <= Integer.MAX_VALUE}.
@@ -2946,7 +2935,7 @@ public static byte[] toByteArray(final InputStream input, final int size, final
*/
public static byte[] toByteArray(final InputStream input, final long size) throws IOException {
if (size > Integer.MAX_VALUE) {
- throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + size);
+ throw new IllegalArgumentException(String.format("size > Integer.MAX_VALUE, size = %,d", size));
}
return toByteArray(input, (int) size);
}
@@ -2955,14 +2944,15 @@ public static byte[] toByteArray(final InputStream input, final long size) throw
* Gets the contents of an input as a {@code byte[]}.
*
* @param input the input to read, not null.
- * @param size the size of the input to read, where 0 < {@code size} <= length of input.
+ * @param size the size of the input to read, where 0 < {@code size} <= length of input.
* @return byte [] of length {@code size}.
- * @throws IOException if an I/O error occurs or input length is smaller than parameter {@code size}.
+ * @throws EOFException if the end of the input is reached before reading {@code size} bytes.
+ * @throws IOException if an I/O error occurs or input length is smaller than parameter {@code size}.
* @throws IllegalArgumentException if {@code size} is less than zero.
*/
static byte[] toByteArray(final IOTriFunction input, final int size) throws IOException {
if (size < 0) {
- throw new IllegalArgumentException("Size must be equal or greater than zero: " + size);
+ throw new IllegalArgumentException(String.format("size < 0, size = %,d", size));
}
if (size == 0) {
return EMPTY_BYTE_ARRAY;
@@ -2974,17 +2964,15 @@ static byte[] toByteArray(final IOTriFunction
offset += read;
}
if (offset != size) {
- throw new IOException("Unexpected read size, current: " + offset + ", expected: " + size);
+ throw new EOFException(String.format("Expected read size: %,d, actual: %,d", size, offset));
}
return data;
}
/**
- * Gets the contents of a {@link Reader} as a {@code byte[]}
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of a {@link Reader} as a {@code byte[]} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to read.
@@ -2999,14 +2987,12 @@ public static byte[] toByteArray(final Reader reader) throws IOException {
}
/**
- * Gets the contents of a {@link Reader} as a {@code byte[]}
- * using the specified character encoding.
+ * Gets the contents of a {@link Reader} as a {@code byte[]} using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
- * @param reader the {@link Reader} to read.
+ * @param reader the {@link Reader} to read.
* @param charset the charset to use, null means platform default.
* @return the requested byte array.
* @throws NullPointerException if the input is null.
@@ -3021,18 +3007,15 @@ public static byte[] toByteArray(final Reader reader, final Charset charset) thr
}
/**
- * Gets the contents of a {@link Reader} as a {@code byte[]}
- * using the specified character encoding.
+ * Gets the contents of a {@link Reader} as a {@code byte[]} using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
- * @param reader the {@link Reader} to read.
+ * @param reader the {@link Reader} to read.
* @param charsetName the name of the requested charset, null means platform default.
* @return the requested byte array.
* @throws NullPointerException if the input is null.
@@ -3045,8 +3028,7 @@ public static byte[] toByteArray(final Reader reader, final String charsetName)
}
/**
- * Gets the contents of a {@link String} as a {@code byte[]}
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of a {@link String} as a {@code byte[]} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* This is the same as {@link String#getBytes()}.
*
@@ -3096,7 +3078,7 @@ public static byte[] toByteArray(final URL url) throws IOException {
* @param urlConnection the {@link URLConnection} to read.
* @return the requested byte array.
* @throws NullPointerException if the urlConn is null.
- * @throws IOException if an I/O exception occurs.
+ * @throws IOException if an I/O exception occurs.
* @since 2.4
*/
public static byte[] toByteArray(final URLConnection urlConnection) throws IOException {
@@ -3106,11 +3088,9 @@ public static byte[] toByteArray(final URLConnection urlConnection) throws IOExc
}
/**
- * Gets the contents of an {@link InputStream} as a character array
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of an {@link InputStream} as a character array using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* @param inputStream the {@link InputStream} to read.
@@ -3118,7 +3098,7 @@ public static byte[] toByteArray(final URLConnection urlConnection) throws IOExc
* @throws NullPointerException if the input is null.
* @throws IOException if an I/O error occurs.
* @since 1.1
- * @deprecated Use {@link #toCharArray(InputStream, Charset)} instead
+ * @deprecated Use {@link #toCharArray(InputStream, Charset)} instead.
*/
@Deprecated
public static char[] toCharArray(final InputStream inputStream) throws IOException {
@@ -3126,37 +3106,31 @@ public static char[] toCharArray(final InputStream inputStream) throws IOExcepti
}
/**
- * Gets the contents of an {@link InputStream} as a character array
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a character array using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* @param inputStream the {@link InputStream} to read.
- * @param charset the charset to use, null means platform default.
+ * @param charset the charset to use, null means platform default.
* @return the requested character array.
* @throws NullPointerException if the input is null.
* @throws IOException if an I/O error occurs.
* @since 2.3
*/
- public static char[] toCharArray(final InputStream inputStream, final Charset charset)
- throws IOException {
+ public static char[] toCharArray(final InputStream inputStream, final Charset charset) throws IOException {
final CharArrayWriter writer = new CharArrayWriter();
copy(inputStream, writer, charset);
return writer.toCharArray();
}
/**
- * Gets the contents of an {@link InputStream} as a character array
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a character array using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* @param inputStream the {@link InputStream} to read.
@@ -3174,8 +3148,7 @@ public static char[] toCharArray(final InputStream inputStream, final String cha
/**
* Gets the contents of a {@link Reader} as a character array.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to read.
@@ -3191,8 +3164,8 @@ public static char[] toCharArray(final Reader reader) throws IOException {
}
/**
- * Converts the specified CharSequence to an input stream, encoded as bytes
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Converts the specified CharSequence to an input stream, encoded as bytes using the virtual machine's {@linkplain Charset#defaultCharset() default
+ * charset}.
*
* @param input the CharSequence to convert.
* @return an input stream.
@@ -3205,10 +3178,9 @@ public static InputStream toInputStream(final CharSequence input) {
}
/**
- * Converts the specified CharSequence to an input stream, encoded as bytes
- * using the specified character encoding.
+ * Converts the specified CharSequence to an input stream, encoded as bytes using the specified character encoding.
*
- * @param input the CharSequence to convert.
+ * @param input the CharSequence to convert.
* @param charset the charset to use, null means platform default.
* @return an input stream.
* @since 2.3
@@ -3218,14 +3190,12 @@ public static InputStream toInputStream(final CharSequence input, final Charset
}
/**
- * Converts the specified CharSequence to an input stream, encoded as bytes
- * using the specified character encoding.
+ * Converts the specified CharSequence to an input stream, encoded as bytes using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * @param input the CharSequence to convert.
+ * @param input the CharSequence to convert.
* @param charsetName the name of the requested charset, null means platform default.
* @return an input stream.
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
@@ -3236,8 +3206,7 @@ public static InputStream toInputStream(final CharSequence input, final String c
}
/**
- * Converts the specified string to an input stream, encoded as bytes
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Converts the specified string to an input stream, encoded as bytes using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @param input the string to convert.
* @return an input stream.
@@ -3250,10 +3219,9 @@ public static InputStream toInputStream(final String input) {
}
/**
- * Converts the specified string to an input stream, encoded as bytes
- * using the specified character encoding.
+ * Converts the specified string to an input stream, encoded as bytes using the specified character encoding.
*
- * @param input the string to convert.
+ * @param input the string to convert.
* @param charset the charset to use, null means platform default.
* @return an input stream.
* @since 2.3
@@ -3263,14 +3231,12 @@ public static InputStream toInputStream(final String input, final Charset charse
}
/**
- * Converts the specified string to an input stream, encoded as bytes
- * using the specified character encoding.
+ * Converts the specified string to an input stream, encoded as bytes using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * @param input the string to convert.
+ * @param input the string to convert.
* @param charsetName the name of the requested charset, null means platform default.
* @return an input stream.
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
@@ -3281,8 +3247,7 @@ public static InputStream toInputStream(final String input, final String charset
}
/**
- * Gets the contents of a {@code byte[]} as a String
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of a {@code byte[]} as a String using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @param input the byte array to read.
* @return the requested String.
@@ -3296,14 +3261,12 @@ public static String toString(final byte[] input) {
}
/**
- * Gets the contents of a {@code byte[]} as a String
- * using the specified character encoding.
+ * Gets the contents of a {@code byte[]} as a String using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * @param input the byte array to read.
+ * @param input the byte array to read.
* @param charsetName the name of the requested charset, null means platform default.
* @return the requested String.
* @throws NullPointerException if the input is null.
@@ -3313,11 +3276,9 @@ public static String toString(final byte[] input, final String charsetName) {
}
/**
- * Gets the contents of an {@link InputStream} as a String
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of an {@link InputStream} as a String using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* @param input the {@link InputStream} to read.
@@ -3332,14 +3293,12 @@ public static String toString(final InputStream input) throws IOException {
}
/**
- * Gets the contents of an {@link InputStream} as a String
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a String using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input the {@link InputStream} to read.
+ * @param input the {@link InputStream} to read.
* @param charset the charset to use, null means platform default.
* @return the requested String.
* @throws NullPointerException if the input is null.
@@ -3354,38 +3313,32 @@ public static String toString(final InputStream input, final Charset charset) th
}
/**
- * Gets the contents of an {@link InputStream} as a String
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a String using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input the {@link InputStream} to read.
+ * @param input the {@link InputStream} to read.
* @param charsetName the name of the requested charset, null means platform default.
* @return the requested String.
* @throws NullPointerException if the input is null.
* @throws IOException if an I/O error occurs.
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
*/
- public static String toString(final InputStream input, final String charsetName)
- throws IOException {
+ public static String toString(final InputStream input, final String charsetName) throws IOException {
return toString(input, Charsets.toCharset(charsetName));
}
/**
- * Gets the contents of an {@link InputStream} from a supplier as a String
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} from a supplier as a String using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input supplies the {@link InputStream} to read.
+ * @param input supplies the {@link InputStream} to read.
* @param charset the charset to use, null means platform default.
* @return the requested String.
* @throws NullPointerException if the input is null.
@@ -3399,15 +3352,13 @@ public static String toString(final IOSupplier input, final Charset
}
/**
- * Gets the contents of an {@link InputStream} from a supplier as a String
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} from a supplier as a String using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input supplies the {@link InputStream} to read.
- * @param charset the charset to use, null means platform default.
+ * @param input supplies the {@link InputStream} to read.
+ * @param charset the charset to use, null means platform default.
* @param defaultString the default return value if the supplier or its value is null.
* @return the requested String.
* @throws NullPointerException if the input is null.
@@ -3426,8 +3377,7 @@ public static String toString(final IOSupplier input, final Charset
/**
* Gets the contents of a {@link Reader} as a String.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to read.
@@ -3443,7 +3393,7 @@ public static String toString(final Reader reader) throws IOException {
}
/**
- * Gets the contents at the given URI using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents at the given URI using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @param uri The URI source.
* @return The contents of the URL as a String.
@@ -3459,7 +3409,7 @@ public static String toString(final URI uri) throws IOException {
/**
* Gets the contents at the given URI.
*
- * @param uri The URI source.
+ * @param uri The URI source.
* @param encoding The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
@@ -3472,7 +3422,7 @@ public static String toString(final URI uri, final Charset encoding) throws IOEx
/**
* Gets the contents at the given URI.
*
- * @param uri The URI source.
+ * @param uri The URI source.
* @param charsetName The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
@@ -3484,7 +3434,7 @@ public static String toString(final URI uri, final String charsetName) throws IO
}
/**
- * Gets the contents at the given URL using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents at the given URL using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @param url The URL source.
* @return The contents of the URL as a String.
@@ -3500,7 +3450,7 @@ public static String toString(final URL url) throws IOException {
/**
* Gets the contents at the given URL.
*
- * @param url The URL source.
+ * @param url The URL source.
* @param encoding The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
@@ -3513,7 +3463,7 @@ public static String toString(final URL url, final Charset encoding) throws IOEx
/**
* Gets the contents at the given URL.
*
- * @param url The URL source.
+ * @param url The URL source.
* @param charsetName The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
@@ -3533,22 +3483,19 @@ public static String toString(final URL url, final String charsetName) throws IO
* @throws IOException if an I/O error occurs.
* @since 1.1
*/
- public static void write(final byte[] data, final OutputStream output)
- throws IOException {
+ public static void write(final byte[] data, final OutputStream output) throws IOException {
if (data != null) {
output.write(data);
}
}
/**
- * Writes bytes from a {@code byte[]} to chars on a {@link Writer}
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Writes bytes from a {@code byte[]} to chars on a {@link Writer} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* This method uses {@link String#String(byte[])}.
*
*
- * @param data the byte array to write, do not modify during output,
- * null ignored
+ * @param data the byte array to write, do not modify during output, null ignored.
* @param writer the {@link Writer} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3561,15 +3508,13 @@ public static void write(final byte[] data, final Writer writer) throws IOExcept
}
/**
- * Writes bytes from a {@code byte[]} to chars on a {@link Writer}
- * using the specified character encoding.
+ * Writes bytes from a {@code byte[]} to chars on a {@link Writer} using the specified character encoding.
*
* This method uses {@link String#String(byte[], String)}.
*
*
- * @param data the byte array to write, do not modify during output,
- * null ignored
- * @param writer the {@link Writer} to write to.
+ * @param data the byte array to write, do not modify during output, null ignored.
+ * @param writer the {@link Writer} to write to.
* @param charset the charset to use, null means platform default.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3584,7 +3529,7 @@ public static void write(final byte[] data, final Writer writer, final Charset c
/**
* Writes bytes from a {@code byte[]} to chars on a {@link Writer} using the specified character encoding.
*
- * Character encoding names can be found at IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link String#String(byte[], String)}.
@@ -3605,7 +3550,7 @@ public static void write(final byte[] data, final Writer writer, final String ch
/**
* Writes chars from a {@code char[]} to bytes on an {@link OutputStream}.
*
- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
*
* @param data the char array to write, do not modify during output, null ignored.
@@ -3616,8 +3561,7 @@ public static void write(final byte[] data, final Writer writer, final String ch
* @deprecated Use {@link #write(char[], OutputStream, Charset)} instead.
*/
@Deprecated
- public static void write(final char[] data, final OutputStream output)
- throws IOException {
+ public static void write(final char[] data, final OutputStream output) throws IOException {
write(data, output, Charset.defaultCharset());
}
@@ -3643,7 +3587,7 @@ public static void write(final char[] data, final OutputStream output, final Cha
/**
* Writes chars from a {@code char[]} to bytes on an {@link OutputStream} using the specified character encoding.
*
- * Character encoding names can be found at IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link String#String(char[])} and {@link String#getBytes(String)}.
@@ -3657,8 +3601,7 @@ public static void write(final char[] data, final OutputStream output, final Cha
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
* @since 1.1
*/
- public static void write(final char[] data, final OutputStream output, final String charsetName)
- throws IOException {
+ public static void write(final char[] data, final OutputStream output, final String charsetName) throws IOException {
write(data, output, Charsets.toCharset(charsetName));
}
@@ -3692,8 +3635,7 @@ public static void write(final char[] data, final Writer writer) throws IOExcept
* @deprecated Use {@link #write(CharSequence, OutputStream, Charset)} instead.
*/
@Deprecated
- public static void write(final CharSequence data, final OutputStream output)
- throws IOException {
+ public static void write(final CharSequence data, final OutputStream output) throws IOException {
write(data, output, Charset.defaultCharset());
}
@@ -3710,8 +3652,7 @@ public static void write(final CharSequence data, final OutputStream output)
* @throws IOException if an I/O error occurs.
* @since 2.3
*/
- public static void write(final CharSequence data, final OutputStream output, final Charset charset)
- throws IOException {
+ public static void write(final CharSequence data, final OutputStream output, final Charset charset) throws IOException {
if (data != null) {
write(data.toString(), output, charset);
}
@@ -3720,7 +3661,7 @@ public static void write(final CharSequence data, final OutputStream output, fin
/**
* Writes chars from a {@link CharSequence} to bytes on an {@link OutputStream} using the specified character encoding.
*
- * Character encoding names can be found at IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link String#getBytes(String)}.
@@ -3734,15 +3675,14 @@ public static void write(final CharSequence data, final OutputStream output, fin
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
* @since 2.0
*/
- public static void write(final CharSequence data, final OutputStream output, final String charsetName)
- throws IOException {
+ public static void write(final CharSequence data, final OutputStream output, final String charsetName) throws IOException {
write(data, output, Charsets.toCharset(charsetName));
}
/**
* Writes chars from a {@link CharSequence} to a {@link Writer}.
*
- * @param data the {@link CharSequence} to write, null ignored.
+ * @param data the {@link CharSequence} to write, null ignored.
* @param writer the {@link Writer} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3755,34 +3695,31 @@ public static void write(final CharSequence data, final Writer writer) throws IO
}
/**
- * Writes chars from a {@link String} to bytes on an
- * {@link OutputStream} using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Writes chars from a {@link String} to bytes on an {@link OutputStream} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* This method uses {@link String#getBytes()}.
*
*
- * @param data the {@link String} to write, null ignored.
+ * @param data the {@link String} to write, null ignored.
* @param output the {@link OutputStream} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
* @since 1.1
- * @deprecated Use {@link #write(String, OutputStream, Charset)} instead
+ * @deprecated Use {@link #write(String, OutputStream, Charset)} instead.
*/
@Deprecated
- public static void write(final String data, final OutputStream output)
- throws IOException {
+ public static void write(final String data, final OutputStream output) throws IOException {
write(data, output, Charset.defaultCharset());
}
/**
- * Writes chars from a {@link String} to bytes on an
- * {@link OutputStream} using the specified character encoding.
+ * Writes chars from a {@link String} to bytes on an {@link OutputStream} using the specified character encoding.
*
* This method uses {@link String#getBytes(String)}.
*
*
- * @param data the {@link String} to write, null ignored.
- * @param output the {@link OutputStream} to write to.
+ * @param data the {@link String} to write, null ignored.
+ * @param output the {@link OutputStream} to write to.
* @param charset the charset to use, null means platform default.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3799,33 +3736,30 @@ public static void write(final String data, final OutputStream output, final Cha
}
/**
- * Writes chars from a {@link String} to bytes on an
- * {@link OutputStream} using the specified character encoding.
+ * Writes chars from a {@link String} to bytes on an {@link OutputStream} using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link String#getBytes(String)}.
*
*
- * @param data the {@link String} to write, null ignored.
- * @param output the {@link OutputStream} to write to.
+ * @param data the {@link String} to write, null ignored.
+ * @param output the {@link OutputStream} to write to.
* @param charsetName the name of the requested charset, null means platform default.
- * @throws NullPointerException if output is null.
- * @throws IOException if an I/O error occurs.
+ * @throws NullPointerException if output is null.
+ * @throws IOException if an I/O error occurs.
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
* @since 1.1
*/
- public static void write(final String data, final OutputStream output, final String charsetName)
- throws IOException {
+ public static void write(final String data, final OutputStream output, final String charsetName) throws IOException {
write(data, output, Charsets.toCharset(charsetName));
}
/**
* Writes chars from a {@link String} to a {@link Writer}.
*
- * @param data the {@link String} to write, null ignored.
+ * @param data the {@link String} to write, null ignored.
* @param writer the {@link Writer} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3838,49 +3772,45 @@ public static void write(final String data, final Writer writer) throws IOExcept
}
/**
- * Writes chars from a {@link StringBuffer} to bytes on an
- * {@link OutputStream} using the default character encoding of the
- * platform.
+ * Writes chars from a {@link StringBuffer} to bytes on an {@link OutputStream} using the default character encoding of the platform.
*
* This method uses {@link String#getBytes()}.
*
*
- * @param data the {@link StringBuffer} to write, null ignored.
+ * @param data the {@link StringBuffer} to write, null ignored.
* @param output the {@link OutputStream} to write to.
* @throws NullPointerException if output is null.
- * @throws IOException if an I/O error occurs
+ * @throws IOException if an I/O error occurs.
* @since 1.1
* @deprecated Use {@link #write(CharSequence, OutputStream)}.
*/
@Deprecated
- public static void write(final StringBuffer data, final OutputStream output) //NOSONAR
+ public static void write(final StringBuffer data, final OutputStream output) // NOSONAR
throws IOException {
write(data, output, (String) null);
}
/**
- * Writes chars from a {@link StringBuffer} to bytes on an
- * {@link OutputStream} using the specified character encoding.
+ * Writes chars from a {@link StringBuffer} to bytes on an {@link OutputStream} using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link String#getBytes(String)}.
*
*
- * @param data the {@link StringBuffer} to write, null ignored.
- * @param output the {@link OutputStream} to write to.
+ * @param data the {@link StringBuffer} to write, null ignored.
+ * @param output the {@link OutputStream} to write to.
* @param charsetName the name of the requested charset, null means platform default.
- * @throws NullPointerException if output is null.
- * @throws IOException if an I/O error occurs.
+ * @throws NullPointerException if output is null.
+ * @throws IOException if an I/O error occurs.
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
* @since 1.1
* @deprecated Use {@link #write(CharSequence, OutputStream, String)}.
*/
@Deprecated
- public static void write(final StringBuffer data, final OutputStream output, final String charsetName) //NOSONAR
- throws IOException {
+ public static void write(final StringBuffer data, final OutputStream output, final String charsetName) // NOSONAR
+ throws IOException {
if (data != null) {
write(data.toString(), output, Charsets.toCharset(charsetName));
}
@@ -3889,7 +3819,7 @@ public static void write(final StringBuffer data, final OutputStream output, fin
/**
* Writes chars from a {@link StringBuffer} to a {@link Writer}.
*
- * @param data the {@link StringBuffer} to write, null ignored.
+ * @param data the {@link StringBuffer} to write, null ignored.
* @param writer the {@link Writer} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3897,7 +3827,7 @@ public static void write(final StringBuffer data, final OutputStream output, fin
* @deprecated Use {@link #write(CharSequence, Writer)}.
*/
@Deprecated
- public static void write(final StringBuffer data, final Writer writer) //NOSONAR
+ public static void write(final StringBuffer data, final Writer writer) // NOSONAR
throws IOException {
if (data != null) {
writer.write(data.toString());
@@ -3905,19 +3835,16 @@ public static void write(final StringBuffer data, final Writer writer) //NOSONAR
}
/**
- * Writes bytes from a {@code byte[]} to an {@link OutputStream} using chunked writes.
- * This is intended for writing very large byte arrays which might otherwise cause excessive
- * memory usage if the native code has to allocate a copy.
+ * Writes bytes from a {@code byte[]} to an {@link OutputStream} using chunked writes. This is intended for writing very large byte arrays which might
+ * otherwise cause excessive memory usage if the native code has to allocate a copy.
*
- * @param data the byte array to write, do not modify during output,
- * null ignored.
+ * @param data the byte array to write, do not modify during output, null ignored.
* @param output the {@link OutputStream} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
* @since 2.5
*/
- public static void writeChunked(final byte[] data, final OutputStream output)
- throws IOException {
+ public static void writeChunked(final byte[] data, final OutputStream output) throws IOException {
if (data != null) {
int bytes = data.length;
int offset = 0;
@@ -3955,7 +3882,7 @@ public static void writeChunked(final char[] data, final Writer writer) throws I
/**
* Writes the {@link #toString()} value of each item in a collection to an {@link OutputStream} line by line, using the virtual machine's
- * {@link Charset#defaultCharset() default charset} and the specified line ending.
+ * {@linkplain Charset#defaultCharset() default charset} and the specified line ending.
*
* @param lines the lines to write, null entries produce blank lines.
* @param lineEnding the line separator to use, null is system default.
@@ -3963,7 +3890,7 @@ public static void writeChunked(final char[] data, final Writer writer) throws I
* @throws NullPointerException if the output is null.
* @throws IOException if an I/O error occurs.
* @since 1.1
- * @deprecated Use {@link #writeLines(Collection, String, OutputStream, Charset)} instead
+ * @deprecated Use {@link #writeLines(Collection, String, OutputStream, Charset)} instead.
*/
@Deprecated
public static void writeLines(final Collection> lines, final String lineEnding, final OutputStream output) throws IOException {
@@ -4009,7 +3936,7 @@ public static void writeLines(final Collection> lines, String lineEnding, fina
* 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.
*
- * Character encoding names can be found at IANA.
+ * Character encoding names can be found at IANA.
*
*
* @param lines the lines to write, null entries produce blank lines.
@@ -4051,11 +3978,10 @@ public static void writeLines(final Collection> lines, String lineEnding, fina
}
/**
- * Returns the given Appendable if it is already a {@link Writer}, otherwise creates a Writer wrapper around the
- * given Appendable.
+ * Returns the given Appendable if it is already a {@link Writer}, otherwise creates a Writer wrapper around the given Appendable.
*
* @param appendable the Appendable to wrap or return (not null).
- * @return the given Appendable or a Writer wrapper around the given Appendable.
+ * @return the given Appendable or a Writer wrapper around the given Appendable.
* @throws NullPointerException if the input parameter is null.
* @since 2.7
*/
@@ -4076,8 +4002,7 @@ public static Writer writer(final Appendable appendable) {
* @deprecated TODO Make private in 3.0.
*/
@Deprecated
- public IOUtils() { //NOSONAR
+ public IOUtils() { // NOSONAR
// empty
}
-
}
diff --git a/src/main/java/org/apache/commons/io/LineIterator.java b/src/main/java/org/apache/commons/io/LineIterator.java
index 293847e7a72..92a8bc7c035 100644
--- a/src/main/java/org/apache/commons/io/LineIterator.java
+++ b/src/main/java/org/apache/commons/io/LineIterator.java
@@ -56,9 +56,9 @@ public class LineIterator implements Iterator, Closeable {
* Closes a {@link LineIterator} quietly.
*
* @param iterator The iterator to close, or {@code null}.
+ * @see Throwable#addSuppressed(Throwable)
* @deprecated As of 2.6 deprecated without replacement. Please use the try-with-resources statement or handle
* suppressed exceptions manually.
- * @see Throwable#addSuppressed(Throwable)
*/
@Deprecated
public static void closeQuietly(final LineIterator iterator) {
@@ -77,17 +77,12 @@ public static void closeQuietly(final LineIterator iterator) {
/**
* Constructs an iterator of the lines for a {@link Reader}.
*
- * @param reader the {@link Reader} to read from, not null
- * @throws NullPointerException if the reader is null
+ * @param reader the {@link Reader} to read from, not null.
+ * @throws NullPointerException if the reader is null.
*/
@SuppressWarnings("resource") // Caller closes Reader
public LineIterator(final Reader reader) {
- Objects.requireNonNull(reader, "reader");
- if (reader instanceof BufferedReader) {
- bufferedReader = (BufferedReader) reader;
- } else {
- bufferedReader = new BufferedReader(reader);
- }
+ bufferedReader = IOUtils.buffer(Objects.requireNonNull(reader, "reader"));
}
/**
@@ -111,8 +106,8 @@ public void close() throws IOException {
* If there is an {@link IOException} then {@link #close()} will
* be called on this instance.
*
- * @return {@code true} if the Reader has more lines
- * @throws IllegalStateException if an IO exception occurs
+ * @return {@code true} if the Reader has more lines.
+ * @throws IllegalStateException if an IO exception occurs.
*/
@Override
public boolean hasNext() {
@@ -135,16 +130,16 @@ public boolean hasNext() {
}
}
} catch (final IOException ioe) {
- IOUtils.closeQuietly(this, ioe::addSuppressed);
- throw new IllegalStateException(ioe);
+ throw new IllegalStateException(IOUtils.closeQuietlySuppress(this, ioe));
}
}
/**
* Overridable method to validate each line that is returned.
* This implementation always returns true.
- * @param line the line that is to be validated
- * @return true if valid, false to remove from the iterator
+ *
+ * @param line the line that is to be validated.
+ * @return true if valid, false to remove from the iterator.
*/
protected boolean isValidLine(final String line) {
return true;
@@ -153,8 +148,8 @@ protected boolean isValidLine(final String line) {
/**
* Returns the next line in the wrapped {@link Reader}.
*
- * @return the next line from the input
- * @throws NoSuchElementException if there is no line to return
+ * @return the next line from the input.
+ * @throws NoSuchElementException if there is no line to return.
*/
@Override
public String next() {
@@ -164,8 +159,8 @@ public String next() {
/**
* Returns the next line in the wrapped {@link Reader}.
*
- * @return the next line from the input
- * @throws NoSuchElementException if there is no line to return
+ * @return the next line from the input.
+ * @throws NoSuchElementException if there is no line to return.
* @deprecated Use {@link #next()}.
*/
@Deprecated
@@ -181,7 +176,7 @@ public String nextLine() {
/**
* Unsupported.
*
- * @throws UnsupportedOperationException always
+ * @throws UnsupportedOperationException always.
*/
@Override
public void remove() {
diff --git a/src/main/java/org/apache/commons/io/RandomAccessFileMode.java b/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
index 88f499d120b..ea44bfa6cba 100644
--- a/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
+++ b/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
@@ -195,8 +195,8 @@ public T apply(final Path file, final IOFunction functi
* Prefer {@link #create(Path)} over this.
*
*
- * @param file the file object
- * @return a random access file
+ * @param file the file object.
+ * @return a random access file.
* @throws FileNotFoundException See {@link IORandomAccessFile#IORandomAccessFile(File, String)}.
*/
public RandomAccessFile create(final File file) throws FileNotFoundException {
@@ -206,8 +206,8 @@ public RandomAccessFile create(final File file) throws FileNotFoundException {
/**
* Constructs a random access file to read from, and optionally to write to, the file specified by the {@link File} argument.
*
- * @param file the file object
- * @return a random access file
+ * @param file the file object.
+ * @return a random access file.
* @throws FileNotFoundException See {@link IORandomAccessFile#IORandomAccessFile(File, String)}.
*/
public RandomAccessFile create(final Path file) throws FileNotFoundException {
@@ -220,8 +220,8 @@ public RandomAccessFile create(final Path file) throws FileNotFoundException {
* Prefer {@link #create(Path)} over this.
*
*
- * @param name the file object
- * @return a random access file
+ * @param name the file object.
+ * @return a random access file.
* @throws FileNotFoundException See {@link IORandomAccessFile#IORandomAccessFile(File, String)}.
*/
public RandomAccessFile create(final String name) throws FileNotFoundException {
@@ -282,8 +282,8 @@ public boolean implies(final RandomAccessFileMode other) {
/**
* Constructs a random access file to read from, and optionally to write to, the file specified by the {@link File} argument.
*
- * @param name the file object
- * @return a random access file
+ * @param name the file object.
+ * @return a random access file.
* @throws FileNotFoundException See {@link IORandomAccessFile#IORandomAccessFile(File, String)}.
* @since 2.18.0
*/
diff --git a/src/main/java/org/apache/commons/io/TaggedIOException.java b/src/main/java/org/apache/commons/io/TaggedIOException.java
index 5eb0b5df596..d997ecc0433 100644
--- a/src/main/java/org/apache/commons/io/TaggedIOException.java
+++ b/src/main/java/org/apache/commons/io/TaggedIOException.java
@@ -57,8 +57,8 @@ public class TaggedIOException extends IOExceptionWithCause {
* }
*
*
- * @param throwable The Throwable object to check
- * @param tag tag object
+ * @param throwable The Throwable object to check.
+ * @param tag tag object.
* @return {@code true} if the throwable has the specified tag,
* otherwise {@code false}
*/
@@ -86,9 +86,9 @@ public static boolean isTaggedWith(final Throwable throwable, final Object tag)
* }
*
*
- * @param throwable an exception
- * @param tag tag object
- * @throws IOException original exception from the tagged decorator, if any
+ * @param throwable an exception.
+ * @param tag tag object.
+ * @throws IOException original exception from the tagged decorator, if any.
*/
public static void throwCauseIfTaggedWith(final Throwable throwable, final Object tag)
throws IOException {
@@ -105,8 +105,8 @@ public static void throwCauseIfTaggedWith(final Throwable throwable, final Objec
/**
* Constructs a tagged wrapper for the given exception.
*
- * @param original the exception to be tagged
- * @param tag tag of this exception
+ * @param original the exception to be tagged.
+ * @param tag tag of this exception.
*/
public TaggedIOException(final IOException original, final Serializable tag) {
super(original.getMessage(), original);
@@ -117,7 +117,7 @@ public TaggedIOException(final IOException original, final Serializable tag) {
* Returns the wrapped exception. The only difference to the overridden
* {@link Throwable#getCause()} method is the narrower return type.
*
- * @return wrapped exception
+ * @return wrapped exception.
*/
@Override
public synchronized IOException getCause() {
@@ -127,7 +127,7 @@ public synchronized IOException getCause() {
/**
* Returns the serializable tag object.
*
- * @return tag object
+ * @return tag object.
*/
public Serializable getTag() {
return tag;
diff --git a/src/main/java/org/apache/commons/io/ThreadMonitor.java b/src/main/java/org/apache/commons/io/ThreadMonitor.java
index 4c2c37a2d3b..f9fe24957c5 100644
--- a/src/main/java/org/apache/commons/io/ThreadMonitor.java
+++ b/src/main/java/org/apache/commons/io/ThreadMonitor.java
@@ -52,7 +52,7 @@ static Thread start(final Duration timeout) {
/**
* Starts monitoring the specified thread.
*
- * @param thread The thread to monitor
+ * @param thread The thread to monitor.
* @param timeout The timeout amount. or no timeout if the value is zero or less.
* @return The monitor thread or {@code null} if the timeout amount is not greater than zero.
*/
@@ -60,7 +60,7 @@ static Thread start(final Thread thread, final Duration timeout) {
if (timeout.isZero() || timeout.isNegative()) {
return null;
}
- final Thread monitor = new Thread(new ThreadMonitor(thread, timeout), ThreadMonitor.class.getSimpleName());
+ final Thread monitor = new Thread(new ThreadMonitor(thread, timeout), "commons-io-ThreadMonitor");
monitor.setDaemon(true);
monitor.start();
return monitor;
@@ -104,6 +104,7 @@ public void run() {
thread.interrupt();
} catch (final InterruptedException ignored) {
// timeout not reached
+ Thread.currentThread().interrupt();
}
}
}
diff --git a/src/main/java/org/apache/commons/io/UncheckedIOExceptions.java b/src/main/java/org/apache/commons/io/UncheckedIOExceptions.java
index f31043769b7..6a5075c52ca 100644
--- a/src/main/java/org/apache/commons/io/UncheckedIOExceptions.java
+++ b/src/main/java/org/apache/commons/io/UncheckedIOExceptions.java
@@ -47,6 +47,7 @@ public static UncheckedIOException create(final Object message) {
*
* This method exists because there is no String constructor in {@link UncheckedIOException}.
*
+ *
* @param e cause the {@link IOException}.
* @param message the detail message.
* @return a new {@link UncheckedIOException}.
diff --git a/src/main/java/org/apache/commons/io/build/AbstractOrigin.java b/src/main/java/org/apache/commons/io/build/AbstractOrigin.java
index d84aefdb79a..e64f4ae732d 100644
--- a/src/main/java/org/apache/commons/io/build/AbstractOrigin.java
+++ b/src/main/java/org/apache/commons/io/build/AbstractOrigin.java
@@ -31,6 +31,7 @@
import java.io.Reader;
import java.io.Writer;
import java.net.URI;
+import java.net.URLConnection;
import java.nio.channels.Channel;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
@@ -43,8 +44,10 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
+import java.time.Duration;
import java.util.Arrays;
import java.util.Objects;
+import java.util.stream.Stream;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.IORandomAccessFile;
@@ -366,6 +369,7 @@ public abstract static class AbstractRandomAccessFileOrigin
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public AbstractRandomAccessFileOrigin(final T origin) {
super(origin);
@@ -437,6 +441,7 @@ public static class ByteArrayOrigin extends AbstractOrigin
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public ChannelOrigin(final Channel origin) {
super(origin);
@@ -563,6 +569,7 @@ public static class CharSequenceOrigin extends AbstractOrigin {
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public FileOrigin(final File origin) {
super(origin);
@@ -689,6 +697,7 @@ public static class InputStreamOrigin extends AbstractOrigin {
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public PathOrigin(final Path origin) {
super(origin);
@@ -892,6 +903,7 @@ public static class ReaderOrigin extends AbstractOrigin {
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public ReaderOrigin(final Reader origin) {
super(origin);
@@ -952,6 +964,80 @@ public Reader getReader(final Charset charset) throws IOException {
*/
public static class URIOrigin extends AbstractOrigin {
+ /**
+ * Options for connect and read from a URI.
+ *
+ * @since 2.22.0
+ */
+ public static final class URIOpenOption implements OpenOption {
+
+ /**
+ * Builds URIOpenOption.
+ */
+ public static class Builder extends AbstractSupplier {
+
+ private Duration connectTimeout;
+ private Duration readTimeout;
+
+ /**
+ * Constructs a new instance.
+ */
+ public Builder() {
+ // empty
+ }
+
+ @Override
+ public URIOpenOption get() {
+ return new URIOpenOption(this);
+ }
+
+ /**
+ * Sets the connect timeout duration.
+ *
+ * @param connectTimeout the connect timeout duration.
+ * @return {@code this instance}.
+ */
+ public Builder setConnectTimeout(final Duration connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ return asThis();
+ }
+
+ /**
+ * Sets the read timeout duration.
+ *
+ * @param readTimeout the read timeout duration.
+ * @return {@code this instance}.
+ */
+ public Builder setReadTimeout(final Duration readTimeout) {
+ this.readTimeout = readTimeout;
+ return asThis();
+ }
+ }
+
+ /**
+ * Creates a new builder.
+ *
+ * @return a new builder.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ private final Duration connectTimeout;
+
+ private final Duration readTimeout;
+
+ private URIOpenOption(final Builder builder) {
+ connectTimeout = builder.connectTimeout;
+ readTimeout = builder.readTimeout;
+ }
+
+ @Override
+ public String toString() {
+ return "URIOpenOption [connectTimeout=" + connectTimeout + ", readTimeout=" + readTimeout + "]";
+ }
+ }
+
private static final String SCHEME_HTTPS = "https";
private static final String SCHEME_HTTP = "http";
@@ -959,17 +1045,23 @@ public static class URIOrigin extends AbstractOrigin {
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public URIOrigin(final URI origin) {
super(origin);
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see URIOpenOption
+ */
@Override
protected Channel getChannel(final OpenOption... options) throws IOException {
final URI uri = get();
final String scheme = uri.getScheme();
if (SCHEME_HTTP.equalsIgnoreCase(scheme) || SCHEME_HTTPS.equalsIgnoreCase(scheme)) {
- return Channels.newChannel(uri.toURL().openStream());
+ return Channels.newChannel(getInputStream(uri, options));
}
return Files.newByteChannel(getPath(), options);
}
@@ -979,20 +1071,52 @@ public File getFile() {
return getPath().toFile();
}
+ /**
+ * {@inheritDoc}
+ *
+ * Set timeouts with a {@link URIOpenOption}.
+ *
+ *
+ * @see URIOpenOption
+ * @see URLConnection#setConnectTimeout(int)
+ * @see URLConnection#setReadTimeout(int)
+ */
@Override
public InputStream getInputStream(final OpenOption... options) throws IOException {
final URI uri = get();
final String scheme = uri.getScheme();
if (SCHEME_HTTP.equalsIgnoreCase(scheme) || SCHEME_HTTPS.equalsIgnoreCase(scheme)) {
- return uri.toURL().openStream();
+ return getInputStream(uri, options);
}
return Files.newInputStream(getPath(), options);
}
+ private InputStream getInputStream(final URI uri, final OpenOption... options) throws IOException {
+ final URLConnection connection = uri.toURL().openConnection();
+ if (options != null) {
+ Stream.of(options).forEach(option -> {
+ if (option instanceof URIOpenOption) {
+ final URIOpenOption connOption = (URIOpenOption) option;
+ if (connOption.connectTimeout != null) {
+ connection.setConnectTimeout(toMillis(connOption.connectTimeout));
+ }
+ if (connOption.readTimeout != null) {
+ connection.setReadTimeout(toMillis(connOption.readTimeout));
+ }
+ }
+ });
+ }
+ return connection.getInputStream();
+ }
+
@Override
public Path getPath() {
return Paths.get(get());
}
+
+ private int toMillis(final Duration duration) {
+ return Math.toIntExact(duration.toMillis());
+ }
}
/**
@@ -1007,6 +1131,7 @@ public static class WriterOrigin extends AbstractOrigin {
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public WriterOrigin(final Writer origin) {
super(origin);
@@ -1057,15 +1182,16 @@ public Writer getWriter(final Charset charset, final OpenOption... options) thro
* Constructs a new instance for subclasses.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
protected AbstractOrigin(final T origin) {
this.origin = Objects.requireNonNull(origin, "origin");
}
/**
- * Gets the origin.
+ * Gets the origin, never null.
*
- * @return the origin.
+ * @return the origin, never null.
*/
@Override
public T get() {
@@ -1090,7 +1216,7 @@ public byte[] getByteArray() throws IOException {
* @param length How many bytes to copy.
* @return this origin as a byte array, if possible.
* @throws UnsupportedOperationException if the origin cannot be converted to a Path.
- * @throws ArithmeticException if the {@code position} overflows an int
+ * @throws ArithmeticException if the {@code position} overflows an int.
* @throws IOException if an I/O error occurs.
* @since 2.13.0
*/
@@ -1113,6 +1239,7 @@ public byte[] getByteArray(final long position, final int length) throws IOExcep
* @param The type of channel to return.
* @throws IOException If an I/O error occurs.
* @throws UnsupportedOperationException If this origin cannot be converted to a channel of the given type.
+ * @see #getChannel(OpenOption...)
* @since 2.21.0
*/
public final C getChannel(final Class channelType, final OpenOption... options) throws IOException {
@@ -1131,6 +1258,7 @@ public final C getChannel(final Class channelType, final
* @return A new Channel on the origin.
* @throws IOException If an I/O error occurs.
* @throws UnsupportedOperationException If this origin cannot be converted to a channel.
+ * @see #getChannel(Class, OpenOption...)
* @since 2.21.0
*/
protected Channel getChannel(final OpenOption... options) throws IOException {
@@ -1162,7 +1290,7 @@ public File getFile() {
/**
* Gets this origin as an InputStream, if possible.
*
- * @param options options specifying how the file is opened
+ * @param options options specifying how the file is opened.
* @return this origin as an InputStream, if possible.
* @throws IOException if an I/O error occurs.
* @throws UnsupportedOperationException if the origin cannot be converted to a Path.
@@ -1174,7 +1302,7 @@ public InputStream getInputStream(final OpenOption... options) throws IOExceptio
/**
* Gets this origin as an OutputStream, if possible.
*
- * @param options options specifying how the file is opened
+ * @param options options specifying how the file is opened.
* @return this origin as an OutputStream, if possible.
* @throws IOException if an I/O error occurs.
* @throws UnsupportedOperationException if the origin cannot be converted to a Path.
@@ -1217,6 +1345,11 @@ public Reader getReader(final Charset charset) throws IOException {
return Files.newBufferedReader(getPath(), Charsets.toCharset(charset));
}
+ /**
+ * Gets simple name of the underlying class.
+ *
+ * @return The simple name of the underlying class.
+ */
private String getSimpleClassName() {
return getClass().getSimpleName();
}
@@ -1224,8 +1357,8 @@ private String getSimpleClassName() {
/**
* Gets a new Writer on the origin, buffered by default.
*
- * @param charset the charset to use for encoding
- * @param options options specifying how the file is opened
+ * @param charset the charset to use for encoding.
+ * @param options options specifying how the file is opened.
* @return a new Writer on the origin.
* @throws IOException if an I/O error occurs opening or creating the file.
* @throws UnsupportedOperationException if the origin cannot be converted to a Path.
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 541548c7295..37986693b48 100644
--- a/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
+++ b/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
@@ -122,6 +122,20 @@ public int getBufferSizeDefault() {
return bufferSizeDefault;
}
+ /**
+ * Gets a byte array from the origin.
+ *
+ * @return A byte array.
+ * @throws IllegalStateException if the {@code origin} is {@code null}.
+ * @throws UnsupportedOperationException if the origin cannot be converted to a byte array.
+ * @throws IOException if an I/O error occurs.
+ * @see AbstractOrigin#getByteArray()
+ * @since 2.22.0
+ */
+ public byte[] getByteArray() throws IOException {
+ return checkOrigin().getByteArray();
+ }
+
/**
* Gets a Channel from the origin with OpenOption[].
*
@@ -142,7 +156,7 @@ public C getChannel(final Class channelType) throws IOExc
/**
* Gets a CharSequence from the origin with a Charset.
*
- * @return An input stream
+ * @return An input stream.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to a CharSequence.
* @throws IOException if an I/O error occurs.
@@ -174,7 +188,7 @@ public Charset getCharsetDefault() {
/**
* Gets a File from the origin.
*
- * @return A File
+ * @return A File.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to a {@link File}.
* @see AbstractOrigin#getPath()
@@ -187,7 +201,7 @@ public File getFile() {
/**
* Gets an InputStream from the origin with OpenOption[].
*
- * @return An input stream
+ * @return An input stream.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}.
* @throws IOException if an I/O error occurs.
@@ -202,7 +216,7 @@ public InputStream getInputStream() throws IOException {
/**
* Gets the OpenOption array.
*
- * @return the OpenOption array.
+ * @return the OpenOption array, this is not a defensive copy, modify at your own risk.
*/
public OpenOption[] getOpenOptions() {
return openOptions;
@@ -211,7 +225,7 @@ public OpenOption[] getOpenOptions() {
/**
* Gets an OutputStream from the origin with OpenOption[].
*
- * @return An OutputStream
+ * @return An OutputStream.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to an {@link OutputStream}.
* @throws IOException if an I/O error occurs.
@@ -226,7 +240,7 @@ public OutputStream getOutputStream() throws IOException {
/**
* Gets a Path from the origin.
*
- * @return A Path
+ * @return A Path.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to a {@link Path}.
* @see AbstractOrigin#getPath()
@@ -239,7 +253,7 @@ public Path getPath() {
/**
* Gets a RandomAccessFile from the origin.
*
- * @return A RandomAccessFile
+ * @return A RandomAccessFile.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to a {@link RandomAccessFile}.
* @throws IOException if an I/O error occurs.
@@ -252,7 +266,7 @@ public RandomAccessFile getRandomAccessFile() throws IOException {
/**
* Gets a Reader from the origin with a Charset.
*
- * @return A Reader
+ * @return A Reader.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to a {@link Reader}.
* @throws IOException if an I/O error occurs.
@@ -285,7 +299,7 @@ public Writer getWriter() throws IOException {
* Subclasses may ignore this setting.
*
*
- * @param bufferSize the buffer size.
+ * @param bufferSize the buffer size, 0 resets to the default from {@link #getBufferSizeDefault()}.
* @return {@code this} instance.
*/
public B setBufferSize(final int bufferSize) {
@@ -299,7 +313,7 @@ public B setBufferSize(final int bufferSize) {
* Subclasses may ignore this setting.
*
*
- * @param bufferSize the buffer size, null resets to the default.
+ * @param bufferSize the buffer size, null resets to the default from {@link #getBufferSizeDefault()}.
* @return {@code this} instance.
*/
public B setBufferSize(final Integer bufferSize) {
@@ -325,11 +339,11 @@ public B setBufferSizeChecker(final IntUnaryOperator bufferSizeChecker) {
* Subclasses may ignore this setting.
*
*
- * @param bufferSizeDefault the buffer size, null resets to the default.
+ * @param bufferSizeDefault the buffer size, 0 resets to the default {@link IOUtils#DEFAULT_BUFFER_SIZE}.
* @return {@code this} instance.
*/
protected B setBufferSizeDefault(final int bufferSizeDefault) {
- this.bufferSizeDefault = bufferSizeDefault;
+ this.bufferSizeDefault = checkBufferSize(bufferSizeDefault > 0 ? bufferSizeDefault : IOUtils.DEFAULT_BUFFER_SIZE);
return asThis();
}
@@ -388,7 +402,7 @@ protected B setCharsetDefault(final Charset defaultCharset) {
}
/**
- * Sets the OpenOption[].
+ * Sets the OpenOption array.
*
* Normally used with InputStream, OutputStream, and Writer.
*
@@ -396,7 +410,7 @@ protected B setCharsetDefault(final Charset defaultCharset) {
* Subclasses may ignore this setting.
*
*
- * @param openOptions the OpenOption[] name, null resets to the default.
+ * @param openOptions the OpenOption[] name, null resets to the default, a defensive copy is made.
* @return {@code this} instance.
* @since 2.13.0
* @see #setInputStream(InputStream)
@@ -404,7 +418,7 @@ protected B setCharsetDefault(final Charset defaultCharset) {
* @see #setWriter(Writer)
*/
public B setOpenOptions(final OpenOption... openOptions) {
- this.openOptions = openOptions != null ? openOptions : DEFAULT_OPEN_OPTIONS;
+ this.openOptions = openOptions != null ? openOptions.clone() : DEFAULT_OPEN_OPTIONS;
return asThis();
}
diff --git a/src/main/java/org/apache/commons/io/build/package-info.java b/src/main/java/org/apache/commons/io/build/package-info.java
index bda177c354c..5eed609d544 100644
--- a/src/main/java/org/apache/commons/io/build/package-info.java
+++ b/src/main/java/org/apache/commons/io/build/package-info.java
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
/**
* Provides classes to implement the builder pattern for IO classes.
*
@@ -49,5 +50,4 @@
*
* @since 2.12.0
*/
-
package org.apache.commons.io.build;
diff --git a/src/main/java/org/apache/commons/io/channels/ByteArraySeekableByteChannel.java b/src/main/java/org/apache/commons/io/channels/ByteArraySeekableByteChannel.java
index 4135a815e83..57c38124875 100644
--- a/src/main/java/org/apache/commons/io/channels/ByteArraySeekableByteChannel.java
+++ b/src/main/java/org/apache/commons/io/channels/ByteArraySeekableByteChannel.java
@@ -24,12 +24,16 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NonWritableChannelException;
import java.nio.channels.SeekableByteChannel;
+import java.nio.file.OpenOption;
+import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.build.AbstractStreamBuilder;
/**
* A {@link SeekableByteChannel} implementation backed by a byte array.
@@ -38,25 +42,79 @@
* and it's not possible to {@link #position(long) set the position} or {@link #truncate(long) truncate} to a value bigger than that. The raw internal buffer is
* accessed via {@link ByteArraySeekableByteChannel#array()}.
*
+ *
+ * Building a read-only channel from an existing byte array is supported with:
+ *
+ * {@code
+ * try (ByteArraySeekableByteChannel channel = ByteArraySeekableByteChannel.builder()
+ * .setByteArray(...)
+ * .setOpenOptions(StandardOpenOption.READ)
+ * .get()) {
+ * // read from channel
+ * }
+ * }
*
* @since 2.21.0
*/
public class ByteArraySeekableByteChannel implements SeekableByteChannel {
+ /**
+ * Builds for {@link ByteArraySeekableByteChannel}.
+ *
+ * Building a read-only channel from an existing byte array is supported with:
+ *
+ * {@code
+ * try (ByteArraySeekableByteChannel channel = ByteArraySeekableByteChannel.builder()
+ * .setByteArray(...)
+ * .setOpenOptions(StandardOpenOption.READ)
+ * .get()) {
+ * // read from channel
+ * }
+ * }
+ *
+ * @since 2.22.0
+ */
+ public static class Builder extends AbstractStreamBuilder {
+
+ /**
+ * Constructs a new builder for {@link ByteArraySeekableByteChannel}.
+ */
+ public Builder() {
+ setByteArray(IOUtils.EMPTY_BYTE_ARRAY);
+ }
+
+ @Override
+ public ByteArraySeekableByteChannel get() throws IOException {
+ return new ByteArraySeekableByteChannel(this);
+ }
+ }
+
private static final int RESIZE_LIMIT = Integer.MAX_VALUE >> 1;
+ /**
+ * Constructs a new builder for {@link ByteArraySeekableByteChannel}.
+ *
+ * @return a new builder for {@link ByteArraySeekableByteChannel}.
+ * @since 2.22.0
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
/**
* Constructs a new channel backed directly by the given byte array.
*
- * The channel initially contains the full contents of the array, with its
- * size set to {@code bytes.length} and its position set to {@code 0}.
+ *
+ * The channel initially contains the full contents of the array, with its size set to {@code bytes.length} and its position set to {@code 0}.
+ *
*
- * Reads and writes operate on the shared array.
- * If a write operation extends beyond the current capacity, the channel will
- * automatically allocate a larger backing array and copy the existing contents.
+ *
+ * Reads and writes operate on the shared array. If a write operation extends beyond the current capacity, the channel will automatically allocate a larger
+ * backing array and copy the existing contents.
+ *
*
* @param bytes The byte array to wrap, must not be {@code null}
- * @return A new channel that uses the given array as its initial backing store
+ * @return A new channel that uses the given array as its initial backing store.
* @throws NullPointerException If {@code bytes} is {@code null}
* @see #array()
* @see ByteArrayInputStream#ByteArrayInputStream(byte[])
@@ -65,11 +123,11 @@ public static ByteArraySeekableByteChannel wrap(final byte[] bytes) {
Objects.requireNonNull(bytes, "bytes");
return new ByteArraySeekableByteChannel(bytes);
}
-
private byte[] data;
private volatile boolean closed;
- private int position;
+ private long position;
private int size;
+ private final boolean isWritable;
private final ReentrantLock lock = new ReentrantLock();
/**
@@ -84,10 +142,19 @@ public ByteArraySeekableByteChannel() {
this(IOUtils.DEFAULT_BUFFER_SIZE);
}
+ private ByteArraySeekableByteChannel(final Builder builder) throws IOException {
+ this.data = builder.getByteArray();
+ this.size = data.length;
+ final OpenOption[] openOptions = builder.getOpenOptions();
+ Arrays.sort(openOptions);
+ this.isWritable = openOptions.length == 0 || Arrays.binarySearch(openOptions, StandardOpenOption.WRITE) >= 0
+ || Arrays.binarySearch(openOptions, StandardOpenOption.APPEND) >= 0;
+ }
+
private ByteArraySeekableByteChannel(final byte[] data) {
this.data = data;
- this.position = 0;
this.size = data.length;
+ this.isWritable = true;
}
/**
@@ -104,8 +171,7 @@ public ByteArraySeekableByteChannel(final int size) {
throw new IllegalArgumentException("Size must be non-negative");
}
this.data = new byte[size];
- this.position = 0;
- this.size = 0;
+ this.isWritable = true;
}
/**
@@ -126,11 +192,16 @@ private void checkOpen() throws ClosedChannelException {
}
}
- private int checkRange(final long newSize, final String method) {
- if (newSize < 0L || newSize > IOUtils.SOFT_MAX_ARRAY_LENGTH) {
- throw new IllegalArgumentException(String.format("%s must be in range [0..%,d]: %,d", method, IOUtils.SOFT_MAX_ARRAY_LENGTH, newSize));
+ private void checkRange(final long newSize, final String method) {
+ if (newSize < 0L) {
+ throw new IllegalArgumentException(String.format("%s must be positive: %,d", method, newSize));
+ }
+ }
+
+ private void checkWritable() {
+ if (!isWritable) {
+ throw new NonWritableChannelException();
}
- return (int) newSize;
}
@Override
@@ -166,10 +237,10 @@ public long position() throws ClosedChannelException {
@Override
public SeekableByteChannel position(final long newPosition) throws IOException {
checkOpen();
- final int intPos = checkRange(newPosition, "position()");
+ checkRange(newPosition, "position()");
lock.lock();
try {
- position = intPos;
+ position = newPosition;
} finally {
lock.unlock();
}
@@ -181,15 +252,18 @@ public int read(final ByteBuffer buf) throws IOException {
checkOpen();
lock.lock();
try {
+ if (position > Integer.MAX_VALUE) {
+ return IOUtils.EOF;
+ }
int wanted = buf.remaining();
- final int possible = size - position;
+ final int possible = size - (int) position;
if (possible <= 0) {
return IOUtils.EOF;
}
if (wanted > possible) {
wanted = possible;
}
- buf.put(data, position, wanted);
+ buf.put(data, (int) position, wanted);
position += wanted;
return wanted;
} finally {
@@ -238,14 +312,15 @@ public byte[] toByteArray() {
@Override
public SeekableByteChannel truncate(final long newSize) throws ClosedChannelException {
checkOpen();
- final int intSize = checkRange(newSize, "truncate()");
+ checkWritable();
+ checkRange(newSize, "truncate()");
lock.lock();
try {
- if (size > intSize) {
- size = intSize;
+ if (size > newSize) {
+ size = (int) newSize;
}
- if (position > intSize) {
- position = intSize;
+ if (position > newSize) {
+ position = newSize;
}
} finally {
lock.unlock();
@@ -256,21 +331,30 @@ public SeekableByteChannel truncate(final long newSize) throws ClosedChannelExce
@Override
public int write(final ByteBuffer b) throws IOException {
checkOpen();
+ checkWritable();
+ //
+ if (position > Integer.MAX_VALUE) {
+ throw new IOException("position > Integer.MAX_VALUE");
+ }
lock.lock();
try {
final int wanted = b.remaining();
- final int possibleWithoutResize = Math.max(0, size - position);
- if (wanted > possibleWithoutResize) {
- final int newSize = position + wanted;
- if (newSize < 0 || newSize > IOUtils.SOFT_MAX_ARRAY_LENGTH) { // overflow
- throw new OutOfMemoryError("required array size " + Integer.toUnsignedString(newSize) + " too large");
- }
- resize(newSize);
+ // intPos <= Integer.MAX_VALUE
+ final int intPos = (int) position;
+ final long newPosition = position + wanted;
+ if (newPosition > IOUtils.SOFT_MAX_ARRAY_LENGTH) {
+ throw new IOException(String.format("Requested array size %,d is too large.", newPosition));
}
- b.get(data, position, wanted);
- position += wanted;
- if (size < position) {
- size = position;
+ if (newPosition > size) {
+ final int newPositionInt = (int) newPosition;
+ // Ensure that newPositionInt ≤ data.length
+ resize(newPositionInt);
+ size = newPositionInt;
+ }
+ b.get(data, intPos, wanted);
+ position = newPosition;
+ if (size < intPos) {
+ size = intPos;
}
return wanted;
} finally {
diff --git a/src/main/java/org/apache/commons/io/channels/CloseShieldChannel.java b/src/main/java/org/apache/commons/io/channels/CloseShieldChannel.java
index a9a462da73b..987e8427c7c 100644
--- a/src/main/java/org/apache/commons/io/channels/CloseShieldChannel.java
+++ b/src/main/java/org/apache/commons/io/channels/CloseShieldChannel.java
@@ -19,7 +19,16 @@
import java.io.Closeable;
import java.lang.reflect.Proxy;
+import java.nio.channels.AsynchronousChannel;
+import java.nio.channels.ByteChannel;
import java.nio.channels.Channel;
+import java.nio.channels.GatheringByteChannel;
+import java.nio.channels.InterruptibleChannel;
+import java.nio.channels.NetworkChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ScatteringByteChannel;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.channels.WritableByteChannel;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
@@ -28,8 +37,24 @@
* Creates a close-shielding proxy for a {@link Channel}.
*
*
- * The returned proxy will implement all {@link Channel} sub-interfaces that the delegate implements.
+ * The returned proxy implements all {@link Channel} sub-interfaces that are both supported by this implementation and actually implemented by the given
+ * delegate.
*
+ *
+ * The following interfaces are supported:
+ *
+ *
+ * - {@link AsynchronousChannel}
+ * - {@link ByteChannel}
+ * - {@link Channel}
+ * - {@link GatheringByteChannel}
+ * - {@link InterruptibleChannel}
+ * - {@link NetworkChannel}
+ * - {@link ReadableByteChannel}
+ * - {@link ScatteringByteChannel}
+ * - {@link SeekableByteChannel}
+ * - {@link WritableByteChannel}
+ *
*
* @see Channel
* @see Closeable
@@ -40,11 +65,15 @@ public final class CloseShieldChannel {
private static final Class>[] EMPTY = {};
private static Set> collectChannelInterfaces(final Class> type, final Set> out) {
+ Class> currentType = type;
// Visit interfaces
- for (final Class> iface : type.getInterfaces()) {
- if (Channel.class.isAssignableFrom(iface) && out.add(iface)) {
- collectChannelInterfaces(iface, out);
+ while (currentType != null) {
+ for (final Class> iface : currentType.getInterfaces()) {
+ if (CloseShieldChannelHandler.isSupported(iface) && out.add(iface)) {
+ collectChannelInterfaces(iface, out);
+ }
}
+ currentType = currentType.getSuperclass();
}
return out;
}
@@ -53,8 +82,10 @@ private static Set> collectChannelInterfaces(final Class> type, final
* Wraps a channel to shield it from being closed.
*
* @param channel The underlying channel to shield, not {@code null}.
- * @param Any Channel type (interface or class).
+ * @param A supported channel type.
* @return A proxy that shields {@code close()} and enforces closed semantics on other calls.
+ * @throws ClassCastException if {@code T} is not a supported channel type.
+ * @throws NullPointerException if {@code channel} is {@code null}.
*/
@SuppressWarnings({ "unchecked", "resource" }) // caller closes
public static T wrap(final T channel) {
diff --git a/src/main/java/org/apache/commons/io/channels/CloseShieldChannelHandler.java b/src/main/java/org/apache/commons/io/channels/CloseShieldChannelHandler.java
index f13b101c197..822c6b6186b 100644
--- a/src/main/java/org/apache/commons/io/channels/CloseShieldChannelHandler.java
+++ b/src/main/java/org/apache/commons/io/channels/CloseShieldChannelHandler.java
@@ -21,14 +21,44 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
+import java.nio.channels.AsynchronousChannel;
+import java.nio.channels.ByteChannel;
import java.nio.channels.Channel;
import java.nio.channels.ClosedChannelException;
+import java.nio.channels.GatheringByteChannel;
+import java.nio.channels.InterruptibleChannel;
import java.nio.channels.NetworkChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ScatteringByteChannel;
import java.nio.channels.SeekableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Objects;
+import java.util.Set;
+/**
+ * An {@link InvocationHandler} supporting the implementation of {@link CloseShieldChannel}.
+ */
final class CloseShieldChannelHandler implements InvocationHandler {
+ private static final Set> SUPPORTED_INTERFACES;
+
+ static {
+ final Set> interfaces = new HashSet<>();
+ interfaces.add(AsynchronousChannel.class);
+ interfaces.add(ByteChannel.class);
+ interfaces.add(Channel.class);
+ interfaces.add(GatheringByteChannel.class);
+ interfaces.add(InterruptibleChannel.class);
+ interfaces.add(NetworkChannel.class);
+ interfaces.add(ReadableByteChannel.class);
+ interfaces.add(ScatteringByteChannel.class);
+ interfaces.add(SeekableByteChannel.class);
+ interfaces.add(WritableByteChannel.class);
+ SUPPORTED_INTERFACES = Collections.unmodifiableSet(interfaces);
+ }
+
/**
* Tests whether the given method is allowed to be called after the shield is closed.
*
@@ -42,6 +72,10 @@ private static boolean isAllowedAfterClose(final Class> declaringClass, final
return parameterCount == 0 && name.equals("supportedOptions") && NetworkChannel.class.equals(declaringClass);
}
+ static boolean isSupported(final Class> interfaceClass) {
+ return SUPPORTED_INTERFACES.contains(interfaceClass);
+ }
+
/**
* Tests whether the given method returns 'this' (the channel) as per JDK spec.
*
@@ -123,7 +157,7 @@ private Object invokeObjectMethod(final Object proxy, final Method method, final
return false;
}
default:
- // Not possible, all non-final Object methods are handled above
+ // Not possible, all non-final Object methods are handled above.
return null;
}
}
diff --git a/src/main/java/org/apache/commons/io/channels/FileChannels.java b/src/main/java/org/apache/commons/io/channels/FileChannels.java
index 30a80e8ab6b..7ef9e3f82c9 100644
--- a/src/main/java/org/apache/commons/io/channels/FileChannels.java
+++ b/src/main/java/org/apache/commons/io/channels/FileChannels.java
@@ -24,6 +24,7 @@
import java.nio.channels.SeekableByteChannel;
import java.util.Objects;
+import org.apache.commons.io.Buffers;
import org.apache.commons.io.IOUtils;
/**
@@ -67,36 +68,38 @@ public static boolean contentEquals(final ReadableByteChannel channel1, final Re
// Don't use ByteBuffer#compact() to avoid extra copying.
final ByteBuffer c1Buffer = ByteBuffer.allocateDirect(bufferCapacity);
final ByteBuffer c2Buffer = ByteBuffer.allocateDirect(bufferCapacity);
- int c1NumRead = 0;
- int c2NumRead = 0;
- boolean c1Read0 = false;
- boolean c2Read0 = false;
- // If a channel is a non-blocking channel, it may return 0 bytes read for any given call.
- while (true) {
- if (!c2Read0) {
- c1NumRead = readToLimit(channel1, c1Buffer);
- c1Buffer.clear();
- c1Read0 = c1NumRead == 0;
- }
- if (!c1Read0) {
- c2NumRead = readToLimit(channel2, c2Buffer);
- c2Buffer.clear();
- c2Read0 = c2NumRead == 0;
- }
- if (c1NumRead == IOUtils.EOF && c2NumRead == IOUtils.EOF) {
- return c1Buffer.equals(c2Buffer);
- }
- if (c1NumRead == 0 || c2NumRead == 0) {
- // 0 may be returned from a non-blocking channel.
- Thread.yield();
- continue;
- }
- if (c1NumRead != c2NumRead) {
- return false;
- }
- if (!c1Buffer.equals(c2Buffer)) {
- return false;
+ try {
+ int c1NumRead = 0;
+ int c2NumRead = 0;
+ boolean c1Read0 = false;
+ boolean c2Read0 = false;
+ // If a channel is a non-blocking channel, it may return 0 bytes read for any given call.
+ while (true) {
+ if (!c2Read0) {
+ c1NumRead = readToLimit(channel1, c1Buffer);
+ c1Buffer.clear();
+ c1Read0 = c1NumRead == 0;
+ }
+ if (!c1Read0) {
+ c2NumRead = readToLimit(channel2, c2Buffer);
+ c2Buffer.clear();
+ c2Read0 = c2NumRead == 0;
+ }
+ if (c1NumRead == IOUtils.EOF && c2NumRead == IOUtils.EOF) {
+ return c1Buffer.equals(c2Buffer);
+ }
+ if (c1NumRead == 0 || c2NumRead == 0) {
+ // 0 may be returned from a non-blocking channel.
+ Thread.yield();
+ continue;
+ }
+ if (c1NumRead != c2NumRead || !c1Buffer.equals(c2Buffer)) {
+ return false;
+ }
}
+ } finally {
+ Buffers.clear(c1Buffer);
+ Buffers.clear(c2Buffer);
}
}
@@ -135,7 +138,7 @@ public static boolean contentEquals(final SeekableByteChannel channel1, final Se
*
* @param channel The source channel.
* @param dst The buffer into which bytes are to be transferred.
- * @return The number of bytes read, never zero, or {@code -1} if the channel has reached end-of-stream
+ * @return The number of bytes read, never zero, or {@code -1} if the channel has reached end-of-stream.
* @throws IOException If some other I/O error occurs.
* @throws IllegalArgumentException If there is room in the given buffer.
*/
diff --git a/src/main/java/org/apache/commons/io/channels/FilterByteChannel.java b/src/main/java/org/apache/commons/io/channels/FilterByteChannel.java
new file mode 100644
index 00000000000..bcce45486b5
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FilterByteChannel.java
@@ -0,0 +1,125 @@
+/*
+ * 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
+ *
+ * https://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.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+
+import org.apache.commons.io.input.ProxyInputStream;
+import org.apache.commons.io.input.ProxyReader;
+import org.apache.commons.io.output.ProxyOutputStream;
+import org.apache.commons.io.output.ProxyWriter;
+
+/**
+ * A {@link ByteChannel} filter which delegates to the wrapped {@link ByteChannel}.
+ *
+ * A {@code FilterByteChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or providing
+ * additional functionality. The class {@code FilterByteChannel} itself simply overrides methods of {@code ByteChannel} with versions that pass all requests to
+ * the wrapped channel. Subclasses of {@code FilterByteChannel} may of course override any methods declared or inherited by {@code FilterByteChannel}, and may
+ * also provide additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterByteChannel#FilterByteChannel(ByteChannel) channel constructor} and more advanced instances through the
+ * {@link Builder}.
+ *
+ *
+ * @param the {@link ByteChannel} type.
+ * @see FilterInputStream
+ * @see FilterOutputStream
+ * @see FilterReader
+ * @see FilterWritableByteChannel
+ * @see ProxyInputStream
+ * @see ProxyOutputStream
+ * @see ProxyReader
+ * @see ProxyWriter
+ * @since 2.22.0
+ */
+public class FilterByteChannel extends FilterChannel implements ByteChannel {
+
+ /**
+ * Builds instances of {@link FilterByteChannel} for subclasses.
+ *
+ * @param The {@link FilterByteChannel} type.
+ * @param The {@link ByteChannel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder, C extends ByteChannel, B extends AbstractBuilder>
+ extends FilterChannel.AbstractBuilder {
+
+ /**
+ * Constructs a new builder for {@link FilterByteChannel}.
+ */
+ protected AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ public static class Builder extends AbstractBuilder, ByteChannel, Builder> {
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterByteChannel get() throws IOException {
+ return new FilterByteChannel<>(this);
+ }
+ }
+
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forByteChannel() {
+ return new Builder();
+ }
+
+ FilterByteChannel(final AbstractBuilder, ?, ?> builder) throws IOException {
+ super(builder);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param byteChannel The channel to wrap.
+ */
+ public FilterByteChannel(final C byteChannel) {
+ super(byteChannel);
+ }
+
+ @Override
+ public int read(final ByteBuffer dst) throws IOException {
+ return channel.read(dst);
+ }
+
+ @Override
+ public int write(final ByteBuffer src) throws IOException {
+ return channel.write(src);
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/channels/FilterChannel.java b/src/main/java/org/apache/commons/io/channels/FilterChannel.java
new file mode 100644
index 00000000000..e76dd962082
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FilterChannel.java
@@ -0,0 +1,146 @@
+/*
+ * 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
+ *
+ * https://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.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.IOException;
+import java.nio.channels.Channel;
+
+import org.apache.commons.io.build.AbstractStreamBuilder;
+import org.apache.commons.io.input.ProxyInputStream;
+import org.apache.commons.io.input.ProxyReader;
+import org.apache.commons.io.output.ProxyOutputStream;
+import org.apache.commons.io.output.ProxyWriter;
+
+/**
+ * A {@link Channel} filter which delegates to the wrapped {@link Channel}.
+ *
+ * A {@code FilterChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or providing
+ * additional functionality. The class {@code FilterChannel} itself simply overrides methods of {@code Channel} with versions that pass all requests to the
+ * wrapped channel. Subclasses of {@code FilterChannel} may of course override any methods declared or inherited by {@code FilterChannel}, and may also provide
+ * additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterChannel#FilterChannel(Channel) channel constructor} and more advanced instances through the
+ * {@link Builder}.
+ *
+ *
+ * @param the {@link Channel} type.
+ * @see FilterInputStream
+ * @see FilterOutputStream
+ * @see FilterReader
+ * @see FilterWritableByteChannel
+ * @see ProxyInputStream
+ * @see ProxyOutputStream
+ * @see ProxyReader
+ * @see ProxyWriter
+ * @since 2.22.0
+ */
+public class FilterChannel implements Channel {
+
+ /**
+ * Builds instances of {@link FilterChannel} for subclasses.
+ *
+ * @param The {@link FilterChannel} type.
+ * @param The {@link Channel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder, C extends Channel, B extends AbstractBuilder>
+ extends AbstractStreamBuilder> {
+
+ /**
+ * Constructs instance for subclasses.
+ */
+ protected AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterChannel}.
+ */
+ public static class Builder extends AbstractBuilder, Channel, Builder> {
+
+ /**
+ * Builds instances of {@link FilterChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterChannel get() throws IOException {
+ return new FilterChannel<>(this);
+ }
+ }
+
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forChannel() {
+ return new Builder();
+ }
+
+ final C channel;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param builder The source builder.
+ * @throws IOException if an I/O error occurs.
+ */
+ @SuppressWarnings("unchecked")
+ FilterChannel(final AbstractBuilder, ?, ?> builder) throws IOException {
+ channel = (C) builder.getChannel(Channel.class);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param channel The channel to wrap.
+ */
+ public FilterChannel(final C channel) {
+ this.channel = channel;
+ }
+
+ @Override
+ public void close() throws IOException {
+ channel.close();
+ }
+
+ @Override
+ public boolean isOpen() {
+ return channel.isOpen();
+ }
+
+ /**
+ * Unwraps this instance by returning the underlying {@link Channel} of type {@code C}.
+ *
+ * Use with caution.
+ *
+ *
+ * @return the underlying channel of type {@code C}.
+ */
+ public C unwrap() {
+ return channel;
+ }
+}
diff --git a/src/test/java/org/apache/commons/io/channels/FileChannelProxy.java b/src/main/java/org/apache/commons/io/channels/FilterFileChannel.java
similarity index 57%
rename from src/test/java/org/apache/commons/io/channels/FileChannelProxy.java
rename to src/main/java/org/apache/commons/io/channels/FilterFileChannel.java
index ce7c0daddf7..c37d30dbf23 100644
--- a/src/test/java/org/apache/commons/io/channels/FileChannelProxy.java
+++ b/src/main/java/org/apache/commons/io/channels/FilterFileChannel.java
@@ -20,20 +20,90 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
+import java.nio.channels.Channel;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
+import java.util.Objects;
+
+import org.apache.commons.io.build.AbstractStreamBuilder;
/**
- * Proxies a FileChannel.
+ * Filters a {@link FileChannel}.
+ *
+ * A {@code FilterFileChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or providing
+ * additional functionality. The class {@code FilterFileChannel} itself simply overrides methods of {@code FileChannel} with versions that pass all requests to
+ * the wrapped channel. Subclasses of {@code FilterFileChannel} may of course override any methods declared or inherited by {@code FilterFileChannel}, and may
+ * also provide additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterFileChannel#FilterFileChannel(FileChannel) channel constructor} and more advanced instances through the
+ * {@link Builder}.
+ *
+ *
+ * @since 2.22.0
*/
-class FileChannelProxy extends FileChannel {
+public class FilterFileChannel extends FileChannel {
+
+ /**
+ * Builds instances of {@link FilterFileChannel} for subclasses.
+ *
+ * @param The {@link FilterFileChannel} type.
+ * @param The {@link Channel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder>
+ extends AbstractStreamBuilder> {
+
+ /**
+ * Constructs instance for subclasses.
+ */
+ protected AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterFileChannel}.
+ */
+ public static class Builder extends AbstractBuilder {
- FileChannel fileChannel;
+ /**
+ * Builds instances of {@link FilterChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterFileChannel get() throws IOException {
+ return new FilterFileChannel(this);
+ }
+ }
- FileChannelProxy(final FileChannel fileChannel) {
- this.fileChannel = fileChannel;
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forFilterFileChannel() {
+ return new Builder();
+ }
+
+ final FileChannel fileChannel;
+
+ private FilterFileChannel(final Builder builder) throws IOException {
+ this.fileChannel = builder.getChannel(FileChannel.class);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param fileChannel the file channel to wrap.
+ */
+ public FilterFileChannel(final FileChannel fileChannel) {
+ this.fileChannel = Objects.requireNonNull(fileChannel, "fileChannel");
}
@Override
@@ -121,6 +191,18 @@ public FileLock tryLock(final long position, final long size, final boolean shar
return fileChannel.tryLock(position, size, shared);
}
+ /**
+ * Unwraps this instance by returning the underlying {@link FileChannel}.
+ *
+ * Use with caution.
+ *
+ *
+ * @return the underlying {@link FileChannel}.
+ */
+ public FileChannel unwrap() {
+ return fileChannel;
+ }
+
@Override
public int write(final ByteBuffer src) throws IOException {
return fileChannel.write(src);
diff --git a/src/main/java/org/apache/commons/io/channels/FilterReadableByteChannel.java b/src/main/java/org/apache/commons/io/channels/FilterReadableByteChannel.java
new file mode 100644
index 00000000000..377d3b1d043
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FilterReadableByteChannel.java
@@ -0,0 +1,120 @@
+/*
+ * 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
+ *
+ * https://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.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+
+import org.apache.commons.io.input.ProxyInputStream;
+import org.apache.commons.io.input.ProxyReader;
+import org.apache.commons.io.output.ProxyOutputStream;
+import org.apache.commons.io.output.ProxyWriter;
+
+/**
+ * A {@link ReadableByteChannel} filter which delegates to the wrapped {@link ReadableByteChannel}.
+ *
+ * A {@code FilterReadableByteChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or
+ * providing additional functionality. The class {@code FilterReadableByteChannel} itself simply overrides methods of {@code ReadableByteChannel} with versions
+ * that pass all requests to the wrapped channel. Subclasses of {@code FilterReadableByteChannel} may of course override any methods declared or inherited by
+ * {@code FilterReadableByteChannel}, and may also provide additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterReadableByteChannel#FilterReadableByteChannel(ReadableByteChannel) channel constructor} and more
+ * advanced instances through the {@link Builder}.
+ *
+ *
+ * @param the {@link ReadableByteChannel} type.
+ * @see FilterInputStream
+ * @see FilterOutputStream
+ * @see FilterReader
+ * @see FilterWritableByteChannel
+ * @see ProxyInputStream
+ * @see ProxyOutputStream
+ * @see ProxyReader
+ * @see ProxyWriter
+ * @since 2.22.0
+ */
+public class FilterReadableByteChannel extends FilterChannel implements ReadableByteChannel {
+
+ /**
+ * Builds instances of {@link FilterReadableByteChannel} for subclasses.
+ *
+ * @param The {@link FilterReadableByteChannel} type.
+ * @param The {@link ReadableByteChannel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder, C extends ReadableByteChannel, B extends AbstractBuilder>
+ extends FilterChannel.AbstractBuilder {
+
+ /**
+ * Constructs a new builder for {@link FilterReadableByteChannel}.
+ */
+ public AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ public static class Builder extends AbstractBuilder, ReadableByteChannel, Builder> {
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterReadableByteChannel get() throws IOException {
+ return new FilterReadableByteChannel<>(this);
+ }
+ }
+
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forReadableByteChannel() {
+ return new Builder();
+ }
+
+ FilterReadableByteChannel(final Builder builder) throws IOException {
+ super(builder);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param channel The channel to wrap.
+ */
+ public FilterReadableByteChannel(final C channel) {
+ super(channel);
+ }
+
+ @Override
+ public int read(final ByteBuffer dst) throws IOException {
+ return channel.read(dst);
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/channels/FilterSeekableByteChannel.java b/src/main/java/org/apache/commons/io/channels/FilterSeekableByteChannel.java
new file mode 100644
index 00000000000..11fbadc2c15
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FilterSeekableByteChannel.java
@@ -0,0 +1,134 @@
+/*
+ * 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
+ *
+ * https://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.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.IOException;
+import java.nio.channels.SeekableByteChannel;
+
+import org.apache.commons.io.input.ProxyInputStream;
+import org.apache.commons.io.input.ProxyReader;
+import org.apache.commons.io.output.ProxyOutputStream;
+import org.apache.commons.io.output.ProxyWriter;
+
+/**
+ * A {@link SeekableByteChannel} filter which delegates to the wrapped {@link SeekableByteChannel}.
+ *
+ * A {@code FilterSeekableByteChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or
+ * providing additional functionality. The class {@code FilterSeekableByteChannel} itself simply overrides methods of {@code SeekableByteChannel} with versions
+ * that pass all requests to the wrapped channel. Subclasses of {@code FilterSeekableByteChannel} may of course override any methods declared or inherited by
+ * {@code FilterSeekableByteChannel}, and may also provide additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterSeekableByteChannel#FilterSeekableByteChannel(SeekableByteChannel) Channel constructor} and more
+ * advanced instances through the {@link Builder}.
+ *
+ *
+ * @param the {@link SeekableByteChannel} type.
+ * @see FilterInputStream
+ * @see FilterOutputStream
+ * @see FilterReader
+ * @see FilterWritableByteChannel
+ * @see ProxyInputStream
+ * @see ProxyOutputStream
+ * @see ProxyReader
+ * @see ProxyWriter
+ * @since 2.22.0
+ */
+public class FilterSeekableByteChannel extends FilterByteChannel implements SeekableByteChannel {
+
+ /**
+ * Builds instances of {@link FilterSeekableByteChannel} for subclasses.
+ *
+ * @param The {@link FilterSeekableByteChannel} type.
+ * @param The {@link SeekableByteChannel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder, C extends SeekableByteChannel, B extends AbstractBuilder>
+ extends FilterByteChannel.AbstractBuilder {
+
+ /**
+ * Constructs a new builder for {@link FilterSeekableByteChannel}.
+ */
+ public AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterSeekableByteChannel}.
+ */
+ public static class Builder extends AbstractBuilder, SeekableByteChannel, Builder> {
+
+ /**
+ * Builds instances of {@link FilterSeekableByteChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterSeekableByteChannel get() throws IOException {
+ return new FilterSeekableByteChannel<>(this);
+ }
+ }
+
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forSeekableByteChannel() {
+ return new Builder();
+ }
+
+ FilterSeekableByteChannel(final Builder builder) throws IOException {
+ super(builder);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param channel The channel to wrap.
+ */
+ public FilterSeekableByteChannel(final C channel) {
+ super(channel);
+ }
+
+ @Override
+ public long position() throws IOException {
+ return channel.position();
+ }
+
+ @Override
+ public SeekableByteChannel position(final long newPosition) throws IOException {
+ return channel.position(newPosition);
+ }
+
+ @Override
+ public long size() throws IOException {
+ return channel.size();
+ }
+
+ @Override
+ public SeekableByteChannel truncate(final long size) throws IOException {
+ return channel.truncate(size);
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/channels/FilterWritableByteChannel.java b/src/main/java/org/apache/commons/io/channels/FilterWritableByteChannel.java
new file mode 100644
index 00000000000..f07e8988c91
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FilterWritableByteChannel.java
@@ -0,0 +1,120 @@
+/*
+ * 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
+ *
+ * https://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.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+
+import org.apache.commons.io.input.ProxyInputStream;
+import org.apache.commons.io.input.ProxyReader;
+import org.apache.commons.io.output.ProxyOutputStream;
+import org.apache.commons.io.output.ProxyWriter;
+
+/**
+ * A {@link WritableByteChannel} filter which delegates to the wrapped {@link WritableByteChannel}.
+ *
+ * A {@code FilterWritableByteChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or
+ * providing additional functionality. The class {@code FilterWritableByteChannel} itself simply overrides methods of {@code WritableByteChannel} with versions
+ * that pass all requests to the wrapped channel. Subclasses of {@code FilterWritableByteChannel} may of course override any methods declared or inherited by
+ * {@code WritableByteChannel}, and may also provide additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterWritableByteChannel#FilterWritableByteChannel(WritableByteChannel) Channel constructor} and more
+ * advanced instances through the {@link Builder}.
+ *
+ *
+ * @param the {@link WritableByteChannel} type.
+ * @see FilterInputStream
+ * @see FilterOutputStream
+ * @see FilterReader
+ * @see FilterWritableByteChannel
+ * @see ProxyInputStream
+ * @see ProxyOutputStream
+ * @see ProxyReader
+ * @see ProxyWriter
+ * @since 2.22.0
+ */
+public class FilterWritableByteChannel extends FilterChannel implements WritableByteChannel {
+
+ /**
+ * Builds instances of {@link FilterWritableByteChannel} for subclasses.
+ *
+ * @param The {@link FilterWritableByteChannel} type.
+ * @param The {@link WritableByteChannel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder, C extends WritableByteChannel, B extends AbstractBuilder>
+ extends FilterChannel.AbstractBuilder {
+
+ /**
+ * Constructs a new builder for {@link FilterWritableByteChannel}.
+ */
+ public AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ public static class Builder extends AbstractBuilder, WritableByteChannel, Builder> {
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterWritableByteChannel get() throws IOException {
+ return new FilterWritableByteChannel<>(this);
+ }
+ }
+
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forWritableByteChannel() {
+ return new Builder();
+ }
+
+ FilterWritableByteChannel(final Builder builder) throws IOException {
+ super(builder);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param channel The channel to wrap.
+ */
+ public FilterWritableByteChannel(final C channel) {
+ super(channel);
+ }
+
+ @Override
+ public int write(final ByteBuffer src) throws IOException {
+ return channel.write(src);
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/charset/CharsetDecoders.java b/src/main/java/org/apache/commons/io/charset/CharsetDecoders.java
index 8595be79e8a..a8aa9a3d50b 100644
--- a/src/main/java/org/apache/commons/io/charset/CharsetDecoders.java
+++ b/src/main/java/org/apache/commons/io/charset/CharsetDecoders.java
@@ -30,7 +30,7 @@ public final class CharsetDecoders {
/**
* Returns the given non-null CharsetDecoder or a new default CharsetDecoder.
*
- * Null input maps to the virtual machine's {@link Charset#defaultCharset() default charset} decoder.
+ * Null input maps to the virtual machine's {@linkplain Charset#defaultCharset() default charset} decoder.
*
*
* @param charsetDecoder The CharsetDecoder to test.
diff --git a/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java b/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java
index d0f9cd04be1..a1fff5cf1f3 100644
--- a/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java
+++ b/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java
@@ -31,7 +31,7 @@ public final class CharsetEncoders {
/**
* Returns the given non-null CharsetEncoder or a new default CharsetEncoder.
*
- * Null input maps to the virtual machine's {@link Charset#defaultCharset() default charset} decoder.
+ * Null input maps to the virtual machine's {@linkplain Charset#defaultCharset() default charset} decoder.
*
*
* @param charsetEncoder The CharsetEncoder to test.
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 0934f895f7a..dcc2d20428e 100644
--- a/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
@@ -58,7 +58,7 @@ public class CompositeFileComparator extends AbstractFileComparator implements S
/**
* Constructs a composite comparator for the set of delegate comparators.
*
- * @param delegates The delegate file comparators
+ * @param delegates The delegate file comparators.
*/
public CompositeFileComparator(@SuppressWarnings("unchecked") final Comparator... delegates) {
this.delegates = delegates == null ? emptyArray() : delegates.clone();
@@ -67,7 +67,7 @@ public CompositeFileComparator(@SuppressWarnings("unchecked") final Comparator> delegates) {
this.delegates = delegates == null ? emptyArray()
@@ -77,8 +77,8 @@ public CompositeFileComparator(final Iterable> delegates) {
/**
* Compares the two files using delegate comparators.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return the first non-zero result returned from the delegate comparators or zero.
*/
@Override
@@ -94,7 +94,7 @@ private Comparator[] emptyArray() {
/**
* String representation of this file comparator.
*
- * @return String representation of this file comparator
+ * @return String representation of this file comparator.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/comparator/DefaultFileComparator.java b/src/main/java/org/apache/commons/io/comparator/DefaultFileComparator.java
index c447f085198..db580a1a2e1 100644
--- a/src/main/java/org/apache/commons/io/comparator/DefaultFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/DefaultFileComparator.java
@@ -69,8 +69,8 @@ public DefaultFileComparator() {
/**
* Compares the two files using the {@link File#compareTo(File)} method.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return the result of calling file1's
* {@link File#compareTo(File)} with file2 as the parameter.
*/
diff --git a/src/main/java/org/apache/commons/io/comparator/ExtensionFileComparator.java b/src/main/java/org/apache/commons/io/comparator/ExtensionFileComparator.java
index 3b4e1e2e115..1d57ec8164f 100644
--- a/src/main/java/org/apache/commons/io/comparator/ExtensionFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/ExtensionFileComparator.java
@@ -93,7 +93,7 @@ public ExtensionFileComparator() {
/**
* Constructs a file extension comparator instance with the specified case-sensitivity.
*
- * @param ioCase how to handle case sensitivity, null means case-sensitive
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
*/
public ExtensionFileComparator(final IOCase ioCase) {
this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE);
@@ -102,8 +102,8 @@ public ExtensionFileComparator(final IOCase ioCase) {
/**
* Compares the extensions of two files the specified case sensitivity.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return a negative value if the first file's extension
* is less than the second, zero if the extensions are the
* same and a positive value if the first files extension
@@ -119,7 +119,7 @@ public int compare(final File file1, final File file2) {
/**
* String representation of this file comparator.
*
- * @return String representation of this file comparator
+ * @return String representation of this file comparator.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/comparator/NameFileComparator.java b/src/main/java/org/apache/commons/io/comparator/NameFileComparator.java
index 41590fa6636..7e92a7fcb74 100644
--- a/src/main/java/org/apache/commons/io/comparator/NameFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/NameFileComparator.java
@@ -89,7 +89,7 @@ public NameFileComparator() {
/**
* Constructs a file name comparator instance with the specified case-sensitivity.
*
- * @param ioCase how to handle case sensitivity, null means case-sensitive
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
*/
public NameFileComparator(final IOCase ioCase) {
this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE);
@@ -98,8 +98,8 @@ public NameFileComparator(final IOCase ioCase) {
/**
* Compares the names of two files with the specified case sensitivity.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return a negative value if the first file's name
* is less than the second, zero if the names are the
* same and a positive value if the first files name
@@ -113,7 +113,7 @@ public int compare(final File file1, final File file2) {
/**
* String representation of this file comparator.
*
- * @return String representation of this file comparator
+ * @return String representation of this file comparator.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/comparator/PathFileComparator.java b/src/main/java/org/apache/commons/io/comparator/PathFileComparator.java
index 1f41eb74185..4ae379add58 100644
--- a/src/main/java/org/apache/commons/io/comparator/PathFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/PathFileComparator.java
@@ -51,6 +51,7 @@
*
* Serialization is deprecated and will be removed in 3.0.
*
+ *
* @since 1.4
*/
public class PathFileComparator extends AbstractFileComparator implements Serializable {
@@ -88,7 +89,7 @@ public PathFileComparator() {
/**
* Constructs a file path comparator instance with the specified case-sensitivity.
*
- * @param ioCase how to handle case sensitivity, null means case-sensitive
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
*/
public PathFileComparator(final IOCase ioCase) {
this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE);
@@ -97,8 +98,8 @@ public PathFileComparator(final IOCase ioCase) {
/**
* Compares the paths of two files the specified case sensitivity.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return a negative value if the first file's path
* is less than the second, zero if the paths are the
* same and a positive value if the first files path
@@ -112,7 +113,7 @@ public int compare(final File file1, final File file2) {
/**
* String representation of this file comparator.
*
- * @return String representation of this file comparator
+ * @return String representation of this file comparator.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/comparator/SizeFileComparator.java b/src/main/java/org/apache/commons/io/comparator/SizeFileComparator.java
index 5154d9b3256..a5ff78c0e59 100644
--- a/src/main/java/org/apache/commons/io/comparator/SizeFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/SizeFileComparator.java
@@ -107,8 +107,8 @@ public SizeFileComparator(final boolean sumDirectoryContents) {
/**
* Compares the length of two files.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return a negative value if the first file's length
* is less than the second, zero if the lengths are the
* same and a positive value if the first files length
@@ -141,7 +141,7 @@ public int compare(final File file1, final File file2) {
/**
* String representation of this file comparator.
*
- * @return String representation of this file comparator
+ * @return String representation of this file comparator.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/doc-files/leaf.svg b/src/main/java/org/apache/commons/io/doc-files/leaf.svg
new file mode 100644
index 00000000000..71de588c648
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/doc-files/leaf.svg
@@ -0,0 +1,45 @@
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/apache/commons/io/doc-files/logo.png b/src/main/java/org/apache/commons/io/doc-files/logo.png
new file mode 100644
index 00000000000..02a758f0ed8
Binary files /dev/null and b/src/main/java/org/apache/commons/io/doc-files/logo.png differ
diff --git a/src/main/java/org/apache/commons/io/file/AccumulatorPathVisitor.java b/src/main/java/org/apache/commons/io/file/AccumulatorPathVisitor.java
index 1551231cfaf..3be7a325315 100644
--- a/src/main/java/org/apache/commons/io/file/AccumulatorPathVisitor.java
+++ b/src/main/java/org/apache/commons/io/file/AccumulatorPathVisitor.java
@@ -195,7 +195,6 @@ public AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter f
* @since 2.12.0
* @deprecated Use {@link #builder()}.
*/
- @SuppressWarnings("deprecation")
@Deprecated
public AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter,
final IOBiFunction visitFileFailed) {
@@ -251,10 +250,10 @@ public int hashCode() {
* Relativizes each directory path with {@link Path#relativize(Path)} against the given {@code parent}, optionally
* sorting the result.
*
- * @param parent A parent path
- * @param sort Whether to sort
+ * @param parent A parent path.
+ * @param sort Whether to sort.
* @param comparator How to sort, null uses default sorting.
- * @return A new list
+ * @return A new list.
*/
public List relativizeDirectories(final Path parent, final boolean sort,
final Comparator super Path> comparator) {
@@ -265,10 +264,10 @@ public List relativizeDirectories(final Path parent, final boolean sort,
* Relativizes each file path with {@link Path#relativize(Path)} against the given {@code parent}, optionally
* sorting the result.
*
- * @param parent A parent path
- * @param sort Whether to sort
+ * @param parent A parent path.
+ * @param sort Whether to sort.
* @param comparator How to sort, null uses default sorting.
- * @return A new list
+ * @return A new list.
*/
public List relativizeFiles(final Path parent, final boolean sort,
final Comparator super Path> comparator) {
diff --git a/src/main/java/org/apache/commons/io/file/CopyDirectoryVisitor.java b/src/main/java/org/apache/commons/io/file/CopyDirectoryVisitor.java
index 7172b2d0671..45b761c971c 100644
--- a/src/main/java/org/apache/commons/io/file/CopyDirectoryVisitor.java
+++ b/src/main/java/org/apache/commons/io/file/CopyDirectoryVisitor.java
@@ -48,8 +48,8 @@ private static CopyOption[] toCopyOption(final CopyOption... copyOptions) {
* Constructs an instance that copies all files.
*
* @param pathCounter How to count visits.
- * @param sourceDirectory The source directory
- * @param targetDirectory The target directory
+ * @param sourceDirectory The source directory.
+ * @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
*/
public CopyDirectoryVisitor(final PathCounters pathCounter, final Path sourceDirectory, final Path targetDirectory, final CopyOption... copyOptions) {
@@ -65,8 +65,8 @@ public CopyDirectoryVisitor(final PathCounters pathCounter, final Path sourceDir
* @param pathCounter How to count visits.
* @param fileFilter How to filter file paths.
* @param dirFilter How to filter directory paths.
- * @param sourceDirectory The source directory
- * @param targetDirectory The target directory
+ * @param sourceDirectory The source directory.
+ * @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
* @since 2.9.0
*/
diff --git a/src/main/java/org/apache/commons/io/file/Counters.java b/src/main/java/org/apache/commons/io/file/Counters.java
index b1abd721d9c..10e05dc48f7 100644
--- a/src/main/java/org/apache/commons/io/file/Counters.java
+++ b/src/main/java/org/apache/commons/io/file/Counters.java
@@ -455,7 +455,7 @@ public static PathCounters noopPathCounters() {
/**
* Construct a new instance.
*
- * @deprecated Will be private in 4.0
+ * @deprecated Will be private in 3.0.
*/
@Deprecated
public Counters() {
diff --git a/src/main/java/org/apache/commons/io/file/CountingPathVisitor.java b/src/main/java/org/apache/commons/io/file/CountingPathVisitor.java
index ab02ad073e2..3f445010e26 100644
--- a/src/main/java/org/apache/commons/io/file/CountingPathVisitor.java
+++ b/src/main/java/org/apache/commons/io/file/CountingPathVisitor.java
@@ -28,7 +28,6 @@
import org.apache.commons.io.file.Counters.PathCounters;
import org.apache.commons.io.filefilter.IOFileFilter;
-import org.apache.commons.io.filefilter.SymbolicLinkFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.io.function.IOBiFunction;
@@ -152,7 +151,7 @@ static UnaryOperator defaultDirectoryTransformer() {
}
static IOFileFilter defaultFileFilter() {
- return new SymbolicLinkFileFilter(FileVisitResult.TERMINATE, FileVisitResult.CONTINUE);
+ return TrueFileFilter.INSTANCE;
}
static PathCounters defaultPathCounters() {
diff --git a/src/main/java/org/apache/commons/io/file/PathFilter.java b/src/main/java/org/apache/commons/io/file/PathFilter.java
index dbeef906261..ee54de29deb 100644
--- a/src/main/java/org/apache/commons/io/file/PathFilter.java
+++ b/src/main/java/org/apache/commons/io/file/PathFilter.java
@@ -34,7 +34,7 @@ public interface PathFilter {
*
* @param path The Path to test.
* @param attributes the path's basic attributes (may be null).
- * @return a FileVisitResult
+ * @return a FileVisitResult.
*/
FileVisitResult accept(Path path, BasicFileAttributes attributes);
}
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 055bbe06a0b..305af952a49 100644
--- a/src/main/java/org/apache/commons/io/file/PathUtils.java
+++ b/src/main/java/org/apache/commons/io/file/PathUtils.java
@@ -137,9 +137,15 @@ private static boolean equalsIgnoreFileSystem(final Path path1, final Path path2
return extractKey(separator1, string1).equals(extractKey(separator2, string2));
}
+ /**
+ * Replaces the file separator in a path string with a string that is not legal in a path on Windows, Linux, and macOS.
+ *
+ * @param separator the file separator.
+ * @param string a path.
+ * @return a key.
+ */
static String extractKey(final String separator, final String string) {
- // Replace the file separator in a path string with a string that is not legal in a path on Windows, Linux, and macOS.
- return string.replaceAll("\\" + separator, ">");
+ return string.replace(separator, ">");
}
final boolean equals;
@@ -200,32 +206,38 @@ private RelativeSortedPaths(final Path dir1, final Path dir2, final int maxDepth
private static final OpenOption[] OPEN_OPTIONS_TRUNCATE = { StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING };
private static final OpenOption[] OPEN_OPTIONS_APPEND = { StandardOpenOption.CREATE, StandardOpenOption.APPEND };
+
/**
* Empty {@link CopyOption} array.
*
* @since 2.8.0
*/
public static final CopyOption[] EMPTY_COPY_OPTIONS = {};
+
/**
* Empty {@link DeleteOption} array.
*
* @since 2.8.0
*/
public static final DeleteOption[] EMPTY_DELETE_OPTION_ARRAY = {};
+
/**
* Empty {@link FileAttribute} array.
*
* @since 2.13.0
*/
public static final FileAttribute>[] EMPTY_FILE_ATTRIBUTE_ARRAY = {};
+
/**
* Empty {@link FileVisitOption} array.
*/
public static final FileVisitOption[] EMPTY_FILE_VISIT_OPTION_ARRAY = {};
+
/**
* Empty {@link LinkOption} array.
*/
public static final LinkOption[] EMPTY_LINK_OPTION_ARRAY = {};
+
/**
* {@link LinkOption} array for {@link LinkOption#NOFOLLOW_LINKS}.
*
@@ -234,16 +246,19 @@ private RelativeSortedPaths(final Path dir1, final Path dir2, final int maxDepth
*/
@Deprecated
public static final LinkOption[] NOFOLLOW_LINK_OPTION_ARRAY = { LinkOption.NOFOLLOW_LINKS };
+
/**
* A LinkOption used to follow link in this class, the inverse of {@link LinkOption#NOFOLLOW_LINKS}.
*
* @since 2.12.0
*/
static final LinkOption NULL_LINK_OPTION = null;
+
/**
* Empty {@link OpenOption} array.
*/
public static final OpenOption[] EMPTY_OPEN_OPTION_ARRAY = {};
+
/**
* Empty {@link Path} array.
*
@@ -266,7 +281,10 @@ private static AccumulatorPathVisitor accumulate(final Path directory, final int
}
/**
- * Cleans a directory by only deleting files, including in subdirectories, but without deleting the directories.
+ * Cleans a directory by only deleting files, including in subdirectories, without deleting directories.
+ *
+ * This leaves a directory empty of files but the directory and any subdirectories remain.
+ *
*
* @param directory directory to clean.
* @return The visitation path counters.
@@ -277,7 +295,10 @@ public static PathCounters cleanDirectory(final Path directory) throws IOExcepti
}
/**
- * Cleans a directory by only deleting files, including in subdirectories, but without deleting the directories.
+ * Cleans a directory by only deleting files, including in subdirectories, without deleting directories.
+ *
+ * This leaves a directory empty of files but the directory and any subdirectories remain.
+ *
*
* @param directory directory to clean.
* @param deleteOptions How to handle deletion.
@@ -378,7 +399,7 @@ public static PathCounters copyDirectory(final Path sourceDirectory, final Path
* @param sourceFile The source URL.
* @param targetFile The target file.
* @param copyOptions Specifies how the copying should be done.
- * @return The target file
+ * @return The target file.
* @throws IOException if an I/O error occurs.
* @see Files#copy(InputStream, Path, CopyOption...)
*/
@@ -393,7 +414,7 @@ public static Path copyFile(final URL sourceFile, final Path targetFile, final C
* @param sourceFile The source file.
* @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
- * @return The target file
+ * @return The target file.
* @throws IOException if an I/O error occurs.
* @see Files#copy(Path, Path, CopyOption...)
*/
@@ -410,7 +431,7 @@ public static Path copyFileToDirectory(final Path sourceFile, final Path targetD
* @param sourceFile The source URL.
* @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
- * @return The target file
+ * @return The target file.
* @throws IOException if an I/O error occurs.
* @see Files#copy(InputStream, Path, CopyOption...)
*/
@@ -499,7 +520,7 @@ public static Path current() {
*
*
* - A directory to delete does not have to be empty.
- * - You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
+ *
- You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
*
*
* @param path file or directory to delete, must not be {@code null}
@@ -518,7 +539,7 @@ public static PathCounters delete(final Path path) throws IOException {
*
*
* - A directory to delete does not have to be empty.
- * - You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
+ *
- You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
*
*
* @param path file or directory to delete, must not be {@code null}
@@ -540,7 +561,7 @@ public static PathCounters delete(final Path path, final DeleteOption... deleteO
*
*
* - A directory to delete does not have to be empty.
- * - You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
+ *
- You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
*
*
* @param path file or directory to delete, must not be {@code null}
@@ -603,7 +624,7 @@ public static PathCounters deleteDirectory(final Path directory, final LinkOptio
* @param file The file to delete.
* @return A visitor with path counts set to 1 file, 0 directories, and the size of the deleted file.
* @throws IOException if an I/O error occurs.
- * @throws NoSuchFileException if the file is a directory
+ * @throws NoSuchFileException if the file is a directory.
*/
public static PathCounters deleteFile(final Path file) throws IOException {
return deleteFile(file, EMPTY_DELETE_OPTION_ARRAY);
@@ -771,7 +792,7 @@ public static boolean directoryContentEquals(final Path path1, final Path path2)
* @param path2 The second directory.
* @param maxDepth See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}.
* @param linkOptions options to follow links.
- * @param fileVisitOptions options to configure the traversal
+ * @param fileVisitOptions options to configure the traversal.
* @return Whether the two directories contain the same files without considering file contents.
* @throws IOException if an I/O error is thrown by a visitor method.
*/
@@ -944,7 +965,7 @@ public static AclFileAttributeView getAclFileAttributeView(final Path path, fina
* Will return the file name itself if it doesn't contain any periods. All leading directories of the {@code file name} parameter are skipped.
*
*
- * @return the base name of file name
+ * @return the base name of file name.
* @param path the path of the file to obtain the base name of.
* @since 2.16.0
*/
@@ -1136,7 +1157,7 @@ public static Path getTempDirectory() {
* {@code Files.isDirectory(Path path, LinkOption... options)}.
*
* @param path the path to the file.
- * @param options options indicating how to handle symbolic links
+ * @param options options indicating how to handle symbolic links.
* @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)
@@ -1240,7 +1261,7 @@ public static boolean isNewer(final Path file, final Instant instant, final Link
* Tests if the given {@link Path} is newer than the given time reference.
*
* @param file the {@link Path} to test.
- * @param timeMillis the time reference measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970)
+ * @param timeMillis the time reference measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970).
* @param options options indicating how to handle symbolic links.
* @return true if the {@link Path} exists and has been modified after the given time reference.
* @throws IOException if an I/O error occurs.
@@ -1301,7 +1322,7 @@ public static boolean isOlder(final Path file, final Instant instant, final Link
* Tests if the given {@link Path} is older than the given time reference.
*
* @param file the {@link Path} to test.
- * @param timeMillis the time reference measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970)
+ * @param timeMillis the time reference measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970).
* @param options options indicating how to handle symbolic links.
* @return true if the {@link Path} exists and has been modified before the given time reference.
* @throws IOException if an I/O error occurs.
@@ -1412,7 +1433,7 @@ private static boolean notExists(final Path path, final LinkOption... options) {
/**
* Returns true if the given options contain {@link StandardDeleteOption#OVERRIDE_READ_ONLY}.
*
- * @param deleteOptions the array to test
+ * @param deleteOptions the array to test.
* @return true if the given options contain {@link StandardDeleteOption#OVERRIDE_READ_ONLY}.
*/
private static boolean overrideReadOnly(final DeleteOption... deleteOptions) {
@@ -1425,7 +1446,7 @@ private static boolean overrideReadOnly(final DeleteOption... deleteOptions) {
/**
* Reads the BasicFileAttributes from the given path. Returns null if the attributes can't be read.
*
- * @param The {@link BasicFileAttributes} type
+ * @param 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.
@@ -1827,7 +1848,7 @@ private static List toSortedList(final Iterable rootDirectories) {
* @param file the file to touch.
* @return The given file.
* @throws NullPointerException if the parameter is {@code null}.
- * @throws IOException if setting the last-modified time failed or an I/O problem occurs.\
+ * @throws IOException if setting the last-modified time failed or an I/O problem occurs.
* @since 2.12.0
*/
public static Path touch(final Path file) throws IOException {
@@ -1957,8 +1978,8 @@ public static boolean waitFor(final Path file, final Duration timeout, final Lin
* closed stream causes a {@link IllegalStateException}.
*
*
- * @param start the start path
- * @param pathFilter the path filter
+ * @param start the start path.
+ * @param pathFilter the path filter.
* @param maxDepth the maximum depth of directories to walk.
* @param readAttributes whether to call the filters with file attributes (false passes null).
* @param options the options to configure the walk.
diff --git a/src/main/java/org/apache/commons/io/file/StandardDeleteOption.java b/src/main/java/org/apache/commons/io/file/StandardDeleteOption.java
index e66dff6473e..0465b77b41b 100644
--- a/src/main/java/org/apache/commons/io/file/StandardDeleteOption.java
+++ b/src/main/java/org/apache/commons/io/file/StandardDeleteOption.java
@@ -22,7 +22,7 @@
import org.apache.commons.io.IOUtils;
/**
- * Defines the standard delete options.
+ * Enumerates the standard delete options.
*
* @since 2.8.0
*/
@@ -38,7 +38,7 @@ public enum StandardDeleteOption implements DeleteOption {
*
* For now, assume the array is not sorted.
*
- * @param options the array to test
+ * @param options the array to test.
* @return true if the given options contain {@link StandardDeleteOption#OVERRIDE_READ_ONLY}.
*/
public static boolean overrideReadOnly(final DeleteOption[] options) {
diff --git a/src/main/java/org/apache/commons/io/file/attribute/FileTimes.java b/src/main/java/org/apache/commons/io/file/attribute/FileTimes.java
index 35725357f9c..2878d8752d7 100644
--- a/src/main/java/org/apache/commons/io/file/attribute/FileTimes.java
+++ b/src/main/java/org/apache/commons/io/file/attribute/FileTimes.java
@@ -308,7 +308,7 @@ static long toNtfsTime(final Instant instant) {
* An NTFS file time is a 64-bit value for the number of 100-nanosecond intervals since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC).
*
*
- * @param javaTime the Java time
+ * @param javaTime the Java time.
* @return the NTFS time, 100-nanosecond units since 1 January 1601.
* @since 2.16.0
*/
diff --git a/src/main/java/org/apache/commons/io/file/spi/FileSystemProviders.java b/src/main/java/org/apache/commons/io/file/spi/FileSystemProviders.java
index 2483cef0a20..4e83ffe1e8c 100644
--- a/src/main/java/org/apache/commons/io/file/spi/FileSystemProviders.java
+++ b/src/main/java/org/apache/commons/io/file/spi/FileSystemProviders.java
@@ -39,7 +39,7 @@ public class FileSystemProviders { // NOPMD Class will be final in 3.0.
/**
* Gets the {@link FileSystemProvider} for the given Path.
*
- * @param path The Path to query
+ * @param path The Path to query.
* @return the {@link FileSystemProvider} for the given Path.
*/
@SuppressWarnings("resource") // FileSystem is not allocated here.
@@ -86,7 +86,7 @@ public FileSystemProvider getFileSystemProvider(final String scheme) {
/**
* Gets the {@link FileSystemProvider} for the given URI.
*
- * @param uri The URI to query
+ * @param uri The URI to query.
* @return the {@link FileSystemProvider} for the given URI or null.
*/
public FileSystemProvider getFileSystemProvider(final URI uri) {
@@ -96,7 +96,7 @@ public FileSystemProvider getFileSystemProvider(final URI uri) {
/**
* Gets the {@link FileSystemProvider} for the given URL.
*
- * @param url The URL to query
+ * @param url The URL to query.
* @return the {@link FileSystemProvider} for the given URI or null.
*/
public FileSystemProvider getFileSystemProvider(final URL url) {
diff --git a/src/main/java/org/apache/commons/io/filefilter/AbstractFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/AbstractFileFilter.java
index c71867d14da..b16e86eaf14 100644
--- a/src/main/java/org/apache/commons/io/filefilter/AbstractFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/AbstractFileFilter.java
@@ -77,8 +77,8 @@ protected AbstractFileFilter(final FileVisitResult onAccept, final FileVisitResu
/**
* Tests to see if the File should be accepted by this filter.
*
- * @param file the File to check
- * @return true if this file matches the test
+ * @param file the File to check.
+ * @return true if this file matches the test.
*/
@Override
public boolean accept(final File file) {
@@ -89,9 +89,9 @@ public boolean accept(final File file) {
/**
* Tests to see if the File should be accepted by this filter.
*
- * @param dir the directory File to check
- * @param name the file name within the directory to check
- * @return true if this file matches the test
+ * @param dir the directory File to check.
+ * @param name the file name within the directory to check.
+ * @return true if this file matches the test.
*/
@Override
public boolean accept(final File dir, final String name) {
@@ -167,7 +167,7 @@ FileVisitResult toFileVisitResult(final boolean accept) {
/**
* Provides a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/AgeFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/AgeFileFilter.java
index 35542cfd486..9d95794ce28 100644
--- a/src/main/java/org/apache/commons/io/filefilter/AgeFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/AgeFileFilter.java
@@ -89,7 +89,7 @@ public class AgeFileFilter extends AbstractFileFilter implements Serializable {
/**
* Constructs a new age file filter for files older than (at or before) a certain cutoff date.
*
- * @param cutoffDate the threshold age of the files
+ * @param cutoffDate the threshold age of the files.
*/
public AgeFileFilter(final Date cutoffDate) {
this(cutoffDate, true);
@@ -98,7 +98,7 @@ public AgeFileFilter(final Date cutoffDate) {
/**
* Constructs a new age file filter for files on any one side of a certain cutoff date.
*
- * @param cutoffDate the threshold age of the files
+ * @param cutoffDate the threshold age of the files.
* @param acceptOlder if true, older files (at or before the cutoff) are accepted, else newer ones (after the
* cutoff).
*/
@@ -110,7 +110,7 @@ public AgeFileFilter(final Date cutoffDate, final boolean acceptOlder) {
* Constructs a new age file filter for files older than (at or before) a certain File (whose last modification time
* will be used as reference).
*
- * @param cutoffReference the file whose last modification time is used as the threshold age of the files
+ * @param cutoffReference the file whose last modification time is used as the threshold age of the files.
*/
public AgeFileFilter(final File cutoffReference) {
this(cutoffReference, true);
@@ -120,7 +120,7 @@ public AgeFileFilter(final File cutoffReference) {
* Constructs a new age file filter for files on any one side of a certain File (whose last modification time will
* be used as reference).
*
- * @param cutoffReference the file whose last modification time is used as the threshold age of the files
+ * @param cutoffReference the file whose last modification time is used as the threshold age of the files.
* @param acceptOlder if true, older files (at or before the cutoff) are accepted, else newer ones (after the
* cutoff).
*/
@@ -179,8 +179,8 @@ public AgeFileFilter(final long cutoffMillis, final boolean acceptOlder) {
* modification time equals cutoff and older files are required, file IS selected.
*
*
- * @param file the File to check
- * @return true if the file name matches
+ * @param file the File to check.
+ * @return true if the file name matches.
*/
@Override
public boolean accept(final File file) {
@@ -194,9 +194,9 @@ public boolean accept(final File file) {
* modification time equals cutoff and older files are required, file IS selected.
*
*
- * @param file the File to check
+ * @param file the File to check.
* @param attributes the path's basic attributes (may be null).
- * @return true if the file name matches
+ * @return true if the file name matches.
* @since 2.9.0
*/
@Override
@@ -207,7 +207,7 @@ public FileVisitResult accept(final Path file, final BasicFileAttributes attribu
/**
* Provide a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/AndFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/AndFileFilter.java
index f8da16bcb0e..5b9a142f70c 100644
--- a/src/main/java/org/apache/commons/io/filefilter/AndFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/AndFileFilter.java
@@ -17,7 +17,6 @@
package org.apache.commons.io.filefilter;
import java.io.File;
-import java.io.FileFilter;
import java.io.Serializable;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
@@ -29,7 +28,7 @@
import java.util.stream.Stream;
/**
- * A {@link FileFilter} providing conditional AND logic across a list of
+ * A {@link ConditionalFileFilter} providing conditional AND logic across a list of
* file filters. This filter returns {@code true} if all filters in the
* list return {@code true}. Otherwise, it returns {@code false}.
* Checking of the file filter list stops when the first filter returns
@@ -90,9 +89,9 @@ public AndFileFilter(final IOFileFilter... fileFilters) {
/**
* Constructs a new file filter that ANDs the result of other filters.
*
- * @param filter1 the first filter, must second be null
- * @param filter2 the first filter, must not be null
- * @throws IllegalArgumentException if either filter is null
+ * @param filter1 the first filter, must second be null.
+ * @param filter2 the first filter, must not be null.
+ * @throws IllegalArgumentException if either filter is null.
*/
public AndFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) {
this(2);
@@ -129,6 +128,7 @@ public boolean accept(final File file, final String name) {
/**
* {@inheritDoc}
+ *
* @since 2.9.0
*/
@Override
@@ -187,7 +187,7 @@ public void setFileFilters(final List fileFilters) {
/**
* Builds a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/CanExecuteFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/CanExecuteFileFilter.java
index 3941a9d74a8..8f262806119 100644
--- a/src/main/java/org/apache/commons/io/filefilter/CanExecuteFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/CanExecuteFileFilter.java
@@ -24,7 +24,7 @@
import java.nio.file.attribute.BasicFileAttributes;
/**
- * This filter accepts {@link File}s that can be executed.
+ * This filter accepts {@link File}s that are executable.
*
* Example, showing how to print out a list of the
* current directory's executable files:
diff --git a/src/main/java/org/apache/commons/io/filefilter/CanReadFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/CanReadFileFilter.java
index da376e0f4f5..58d2ad7a50c 100644
--- a/src/main/java/org/apache/commons/io/filefilter/CanReadFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/CanReadFileFilter.java
@@ -24,7 +24,7 @@
import java.nio.file.attribute.BasicFileAttributes;
/**
- * This filter accepts {@link File}s that can be read.
+ * This filter accepts {@link File}s that are readable.
*
* Example, showing how to print out a list of the current directory's readable files:
*
diff --git a/src/main/java/org/apache/commons/io/filefilter/CanWriteFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/CanWriteFileFilter.java
index 899481c6465..db209b4a50e 100644
--- a/src/main/java/org/apache/commons/io/filefilter/CanWriteFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/CanWriteFileFilter.java
@@ -24,7 +24,7 @@
import java.nio.file.attribute.BasicFileAttributes;
/**
- * This filter accepts {@link File}s that can be written to.
+ * This filter accepts {@link File}s that are writable.
*
* Example, showing how to print out a list of the current directory's writable files:
*
@@ -54,6 +54,7 @@
* Serialization is deprecated and will be removed in 3.0.
*
*
+ * @see Files#isWritable(Path)
* @since 1.3
*/
public class CanWriteFileFilter extends AbstractFileFilter implements Serializable {
@@ -75,7 +76,7 @@ protected CanWriteFileFilter() {
/**
* Tests to see if the file can be written to.
*
- * @param file the File to check
+ * @param file the File to check.
* @return {@code true} if the file can be written to, otherwise {@code false}.
*/
@Override
@@ -86,7 +87,7 @@ public boolean accept(final File file) {
/**
* Tests to see if the file can be written to.
*
- * @param file the File to check
+ * @param file the File to check.
* @param attributes the path's basic attributes (may be null).
* @return {@code true} if the file can be written to, otherwise {@code false}.
* @since 2.9.0
diff --git a/src/main/java/org/apache/commons/io/filefilter/ConditionalFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/ConditionalFileFilter.java
index d59996a0461..96ff4947b5c 100644
--- a/src/main/java/org/apache/commons/io/filefilter/ConditionalFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/ConditionalFileFilter.java
@@ -29,7 +29,7 @@ public interface ConditionalFileFilter {
* Adds the specified file filter to the list of file filters at the end of
* the list.
*
- * @param ioFileFilter the filter to be added
+ * @param ioFileFilter the filter to be added.
* @since 1.1
*/
void addFileFilter(IOFileFilter ioFileFilter);
@@ -37,7 +37,7 @@ public interface ConditionalFileFilter {
/**
* Gets this conditional file filter's list of file filters.
*
- * @return the file filter list
+ * @return the file filter list.
* @since 1.1
*/
List getFileFilters();
@@ -45,9 +45,9 @@ public interface ConditionalFileFilter {
/**
* Removes the specified file filter.
*
- * @param ioFileFilter filter to be removed
+ * @param ioFileFilter filter to be removed.
* @return {@code true} if the filter was found in the list,
- * {@code false} otherwise
+ * {@code false} otherwise.
* @since 1.1
*/
boolean removeFileFilter(IOFileFilter ioFileFilter);
@@ -56,7 +56,7 @@ public interface ConditionalFileFilter {
* Sets the list of file filters, replacing any previously configured
* file filters on this filter.
*
- * @param fileFilters the list of filters
+ * @param fileFilters the list of filters.
* @since 1.1
*/
void setFileFilters(List fileFilters);
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 4137644ca1d..dd8674f3916 100644
--- a/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java
@@ -39,13 +39,14 @@ public class DelegateFileFilter extends AbstractFileFilter implements Serializab
/** The File filter */
private final transient FileFilter fileFilter;
+
/** The Filename filter */
private final transient FilenameFilter fileNameFilter;
/**
* Constructs a delegate file filter around an existing FileFilter.
*
- * @param fileFilter the filter to decorate
+ * @param fileFilter the filter to decorate.
*/
public DelegateFileFilter(final FileFilter fileFilter) {
Objects.requireNonNull(fileFilter, "filter");
@@ -56,7 +57,7 @@ public DelegateFileFilter(final FileFilter fileFilter) {
/**
* 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");
@@ -67,8 +68,8 @@ public DelegateFileFilter(final FilenameFilter fileNameFilter) {
/**
* Tests the filter.
*
- * @param file the file to check
- * @return true if the filter matches
+ * @param file the file to check.
+ * @return true if the filter matches.
*/
@Override
public boolean accept(final File file) {
@@ -81,9 +82,9 @@ public boolean accept(final File file) {
/**
* Tests the filter.
*
- * @param dir the directory
- * @param name the file name in the directory
- * @return true if the filter matches
+ * @param dir the directory.
+ * @param name the file name in the directory.
+ * @return true if the filter matches.
*/
@Override
public boolean accept(final File dir, final String name) {
@@ -96,7 +97,7 @@ public boolean accept(final File dir, final String name) {
/**
* Provide a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/DirectoryFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/DirectoryFileFilter.java
index bb3d615bd43..b0c54b42ec4 100644
--- a/src/main/java/org/apache/commons/io/filefilter/DirectoryFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/DirectoryFileFilter.java
@@ -92,8 +92,8 @@ protected DirectoryFileFilter() {
/**
* Tests to see if the file is a directory.
*
- * @param file the File to check
- * @return true if the file is a directory
+ * @param file the File to check.
+ * @return true if the file is a directory.
*/
@Override
public boolean accept(final File file) {
@@ -103,9 +103,9 @@ public boolean accept(final File file) {
/**
* Tests to see if the file is a directory.
*
- * @param file the File to check
+ * @param file the File to check.
* @param attributes the path's basic attributes (may be null).
- * @return true if the file is a directory
+ * @return true if the file is a directory.
* @since 2.9.0
*/
@Override
diff --git a/src/main/java/org/apache/commons/io/filefilter/EmptyFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/EmptyFileFilter.java
index a5cdd676bb1..392d2cf0f12 100644
--- a/src/main/java/org/apache/commons/io/filefilter/EmptyFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/EmptyFileFilter.java
@@ -99,7 +99,7 @@ protected EmptyFileFilter() {
/**
* Tests to see if the file is empty.
*
- * @param file the file or directory to check
+ * @param file the file or directory to check.
* @return {@code true} if the file or directory is empty, otherwise {@code false}.
*/
@Override
@@ -117,7 +117,7 @@ public boolean accept(final File file) {
/**
* Tests to see if the file is empty.
*
- * @param file the file or directory to check
+ * @param file the file or directory to check.
* @param attributes the path's basic attributes (may be null).
* @return {@code true} if the file or directory is empty, otherwise {@code false}.
* @since 2.9.0
diff --git a/src/main/java/org/apache/commons/io/filefilter/FalseFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/FalseFileFilter.java
index ebaa77b2007..7054a7c68f2 100644
--- a/src/main/java/org/apache/commons/io/filefilter/FalseFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/FalseFileFilter.java
@@ -60,8 +60,8 @@ protected FalseFileFilter() {
/**
* Returns false.
*
- * @param file the file to check (ignored)
- * @return false
+ * @param file the file to check (ignored).
+ * @return false.
*/
@Override
public boolean accept(final File file) {
@@ -71,9 +71,9 @@ public boolean accept(final File file) {
/**
* Returns false.
*
- * @param dir the directory to check (ignored)
- * @param name the file name (ignored)
- * @return false
+ * @param dir the directory to check (ignored).
+ * @param name the file name (ignored).
+ * @return false.
*/
@Override
public boolean accept(final File dir, final String name) {
@@ -83,9 +83,9 @@ public boolean accept(final File dir, final String name) {
/**
* Returns false.
*
- * @param file the file to check (ignored)
+ * @param file the file to check (ignored).
* @param attributes the path's basic attributes (may be null).
- * @return false
+ * @return {@link FileVisitResult#TERMINATE}.
* @since 2.9.0
*/
@Override
diff --git a/src/main/java/org/apache/commons/io/filefilter/FileFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/FileFileFilter.java
index 801d39f07b4..4bab6adf49e 100644
--- a/src/main/java/org/apache/commons/io/filefilter/FileFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/FileFileFilter.java
@@ -92,8 +92,8 @@ protected FileFileFilter() {
/**
* Tests to see if the file is a file.
*
- * @param file the File to check
- * @return true if the file is a file
+ * @param file the File to check.
+ * @return true if the file is a file.
*/
@Override
public boolean accept(final File file) {
@@ -103,9 +103,9 @@ public boolean accept(final File file) {
/**
* Tests to see if the file is a file.
*
- * @param file the File to check
+ * @param file the File to check.
* @param attributes the path's basic attributes (may be null).
- * @return true if the file is a file
+ * @return true if the file is a file.
* @since 2.9.0
*/
@Override
diff --git a/src/main/java/org/apache/commons/io/filefilter/FileFilterUtils.java b/src/main/java/org/apache/commons/io/filefilter/FileFilterUtils.java
index 5e37676ac9c..74715ef6158 100644
--- a/src/main/java/org/apache/commons/io/filefilter/FileFilterUtils.java
+++ b/src/main/java/org/apache/commons/io/filefilter/FileFilterUtils.java
@@ -55,8 +55,8 @@ public class FileFilterUtils {
* Returns a filter that returns true if the file was last modified before
* or at the specified cutoff date.
*
- * @param cutoffDate the time threshold
- * @return an appropriately configured age file filter
+ * @param cutoffDate the time threshold.
+ * @return an appropriately configured age file filter.
* @see AgeFileFilter
* @since 1.2
*/
@@ -67,9 +67,9 @@ public static IOFileFilter ageFileFilter(final Date cutoffDate) {
/**
* Returns a filter that filters files based on a cutoff date.
*
- * @param cutoffDate the time threshold
- * @param acceptOlder if true, older files get accepted, if false, newer
- * @return an appropriately configured age file filter
+ * @param cutoffDate the time threshold.
+ * @param acceptOlder if true, older files get accepted, if false, newer.
+ * @return an appropriately configured age file filter.
* @see AgeFileFilter
* @since 1.2
*/
@@ -82,8 +82,8 @@ public static IOFileFilter ageFileFilter(final Date cutoffDate, final boolean ac
* or at the same time as the specified reference file.
*
* @param cutoffReference the file whose last modification
- * time is used as the threshold age of the files
- * @return an appropriately configured age file filter
+ * time is used as the threshold age of the files.
+ * @return an appropriately configured age file filter.
* @see AgeFileFilter
* @since 1.2
*/
@@ -95,9 +95,9 @@ public static IOFileFilter ageFileFilter(final File cutoffReference) {
* Returns a filter that filters files based on a cutoff reference file.
*
* @param cutoffReference the file whose last modification
- * time is used as the threshold age of the files
- * @param acceptOlder if true, older files get accepted, if false, newer
- * @return an appropriately configured age file filter
+ * time is used as the threshold age of the files.
+ * @param acceptOlder if true, older files get accepted, if false, newer.
+ * @return an appropriately configured age file filter.
* @see AgeFileFilter
* @since 1.2
*/
@@ -109,8 +109,8 @@ public static IOFileFilter ageFileFilter(final File cutoffReference, final boole
* Returns a filter that returns true if the file was last modified before
* or at the specified cutoff time.
*
- * @param cutoffMillis the time threshold
- * @return an appropriately configured age file filter
+ * @param cutoffMillis the time threshold.
+ * @return an appropriately configured age file filter.
* @see AgeFileFilter
* @since 1.2
*/
@@ -121,9 +121,9 @@ public static IOFileFilter ageFileFilter(final long cutoffMillis) {
/**
* Returns a filter that filters files based on a cutoff time.
*
- * @param cutoffMillis the time threshold
- * @param acceptOlder if true, older files get accepted, if false, newer
- * @return an appropriately configured age file filter
+ * @param cutoffMillis the time threshold.
+ * @param acceptOlder if true, older files get accepted, if false, newer.
+ * @return an appropriately configured age file filter.
* @see AgeFileFilter
* @since 1.2
*/
@@ -135,7 +135,7 @@ public static IOFileFilter ageFileFilter(final long cutoffMillis, final boolean
* Returns a filter that ANDs the specified filters.
*
* @param filters the IOFileFilters that will be ANDed together.
- * @return a filter that ANDs the specified filters
+ * @return a filter that ANDs the specified filters.
* @throws IllegalArgumentException if the filters are null or contain a
* null value.
* @see AndFileFilter
@@ -148,12 +148,12 @@ public static IOFileFilter and(final IOFileFilter... filters) {
/**
* Returns a filter that ANDs the two specified filters.
*
- * @param filter1 the first filter
- * @param filter2 the second filter
- * @return a filter that ANDs the two specified filters
+ * @param filter1 the first filter.
+ * @param filter2 the second filter.
+ * @return a filter that ANDs the two specified filters.
* @see #and(IOFileFilter...)
* @see AndFileFilter
- * @deprecated use {@link #and(IOFileFilter...)}
+ * @deprecated Use {@link #and(IOFileFilter...)}
*/
@Deprecated
public static IOFileFilter andFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) {
@@ -164,8 +164,8 @@ public static IOFileFilter andFileFilter(final IOFileFilter filter1, final IOFil
* Returns an {@link IOFileFilter} that wraps the
* {@link FileFilter} instance.
*
- * @param filter the filter to be wrapped
- * @return a new filter that implements IOFileFilter
+ * @param filter the filter to be wrapped.
+ * @return a new filter that implements IOFileFilter.
* @see DelegateFileFilter
*/
public static IOFileFilter asFileFilter(final FileFilter filter) {
@@ -176,8 +176,8 @@ public static IOFileFilter asFileFilter(final FileFilter filter) {
* Returns an {@link IOFileFilter} that wraps the
* {@link FilenameFilter} instance.
*
- * @param filter the filter to be wrapped
- * @return a new filter that implements IOFileFilter
+ * @param filter the filter to be wrapped.
+ * @return a new filter that implements IOFileFilter.
* @see DelegateFileFilter
*/
public static IOFileFilter asFileFilter(final FilenameFilter filter) {
@@ -187,7 +187,7 @@ public static IOFileFilter asFileFilter(final FilenameFilter filter) {
/**
* Returns a filter that checks if the file is a directory.
*
- * @return file filter that accepts only directories and not files
+ * @return file filter that accepts only directories and not files.
* @see DirectoryFileFilter#DIRECTORY
*/
public static IOFileFilter directoryFileFilter() {
@@ -197,7 +197,7 @@ public static IOFileFilter directoryFileFilter() {
/**
* Returns a filter that always returns false.
*
- * @return a false filter
+ * @return a false filter.
* @see FalseFileFilter#FALSE
*/
public static IOFileFilter falseFileFilter() {
@@ -207,7 +207,7 @@ public static IOFileFilter falseFileFilter() {
/**
* Returns a filter that checks if the file is a file (and not a directory).
*
- * @return file filter that accepts only files and not directories
+ * @return file filter that accepts only files and not directories.
* @see FileFileFilter#INSTANCE
*/
public static IOFileFilter fileFileFilter() {
@@ -226,13 +226,13 @@ public static IOFileFilter fileFileFilter() {
* Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
* FileFilterUtils.suffixFileFilter(".java"));
*
+ *
* @param filter the filter to apply to the set of files.
* @param files the array of files to apply the filter to.
* @return a subset of {@code files} that is accepted by the
* file filter.
* @throws NullPointerException if the filter is {@code null}
* or {@code files} contains a {@code null} value.
- *
* @since 2.0
*/
public static File[] filter(final IOFileFilter filter, final File... files) {
@@ -259,13 +259,13 @@ public static File[] filter(final IOFileFilter filter, final File... files) {
* Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
* FileFilterUtils.suffixFileFilter(".java"));
*
+ *
* @param filter the filter to apply to the set of files.
* @param files 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.
- *
* @since 2.0
*/
public static File[] filter(final IOFileFilter filter, final Iterable- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset}. + * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset}. *
* * @param magicNumber the magic number to look for in the file. @@ -270,6 +270,7 @@ public boolean accept(final File file) { * be rejected. * * + * * @param file the file to accept or reject. * @param attributes the path's basic attributes (may be null). * @return {@code true} if the file contains the filter's magic number diff --git a/src/main/java/org/apache/commons/io/filefilter/NameFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/NameFileFilter.java index 7eda934d906..5aa3c38a21b 100644 --- a/src/main/java/org/apache/commons/io/filefilter/NameFileFilter.java +++ b/src/main/java/org/apache/commons/io/filefilter/NameFileFilter.java @@ -83,9 +83,9 @@ public class NameFileFilter extends AbstractFileFilter implements Serializable { /** * Constructs a new case-sensitive name file filter for a list of names. * - * @param names the names to allow, must not be null - * @throws IllegalArgumentException if the name list is null - * @throws ClassCastException if the list does not contain Strings + * @param names the names to allow, must not be null. + * @throws IllegalArgumentException if the name list is null. + * @throws ClassCastException if the list does not contain Strings. */ public NameFileFilter(final List* Implementations may not have anything to unwrap and that behavior is undefined for now. *
+ * * @return the underlying Iterable. */ Iterable* Implementations may not have anything to unwrap and that behavior is undefined for now. *
+ * * @return the underlying Iterator. */ Iterator- * This class detects these bytes and, if required, can automatically skip them and return the subsequent byte as the - * first byte in the stream. + * This class detects these bytes and, if required, can automatically skip them and return the subsequent byte as the first byte in the stream. *
** The {@link ByteOrderMark} implementation has the following predefined BOMs: @@ -60,10 +60,7 @@ * *
* boolean include = true;
- * BOMInputStream bomIn = BOMInputStream.builder()
- * .setInputStream(in)
- * .setInclude(include)
- * .get();
+ * BOMInputStream bomIn = BOMInputStream.builder().setInputStream(in).setInclude(include).get();
* if (bomIn.hasBOM()) {
* // has a UTF-8 BOM
* }
@@ -72,10 +69,8 @@
* Example 3 - Detecting Multiple BOMs
*
*
- * BOMInputStream bomIn = BOMInputStream.builder()
- * .setInputStream(in)
- * .setByteOrderMarks(ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE)
- * .get();
+ * BOMInputStream bomIn = BOMInputStream.builder().setInputStream(in)
+ * .setByteOrderMarks(ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE).get();
* if (bomIn.hasBOM() == false) {
* // No BOM found
* } else if (bomIn.hasBOM(ByteOrderMark.UTF_16LE)) {
@@ -134,14 +129,13 @@ public static class Builder extends AbstractBuilder {
/**
* For test access.
*
- * @return the default byte order mark
+ * @return the default byte order mark.
*/
static ByteOrderMark getDefaultByteOrderMark() {
return DEFAULT[0];
}
private ByteOrderMark[] byteOrderMarks = DEFAULT;
-
private boolean include;
/**
@@ -200,14 +194,13 @@ public Builder setByteOrderMarks(final ByteOrderMark... byteOrderMarks) {
* The default is false.
*
*
- * @param include true to include the UTF-8 BOM or false to exclude it. return this;
+ * @param include true to include the UTF-8 BOM or false to exclude it. return this;.
* @return {@code this} instance.
*/
public Builder setInclude(final boolean include) {
this.include = include;
return this;
}
-
}
/**
@@ -229,65 +222,68 @@ public static Builder builder() {
* BOMs are sorted from longest to shortest.
*/
private final List bomList;
-
- private ByteOrderMark byteOrderMark;
+ private final ByteOrderMark byteOrderMark;
private int fbIndex;
private int[] firstBytes;
private final boolean include;
private boolean markedAtStart;
private int markFbIndex;
+ /**
+ * Constructs a new instance.
+ *
+ * @param builder The builder.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
+ */
private BOMInputStream(final Builder builder) throws IOException {
super(builder);
if (IOUtils.length(builder.byteOrderMarks) == 0) {
throw new IllegalArgumentException("No ByteOrderMark specified.");
}
this.include = builder.include;
- final List list = Arrays.asList(builder.byteOrderMarks);
+ final List bomList = Arrays.asList(builder.byteOrderMarks);
// Sort the BOMs to match the longest BOM first because some BOMs have the same starting two bytes.
- list.sort(ByteOrderMarkLengthComparator);
- this.bomList = list;
+ bomList.sort(ByteOrderMarkLengthComparator);
+ this.bomList = bomList;
+ this.byteOrderMark = readBom();
}
/**
* Constructs a new BOM InputStream that excludes a {@link ByteOrderMark#UTF_8} BOM.
*
- * @param delegate
- * the InputStream to delegate to
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param delegate the InputStream to delegate to.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
- public BOMInputStream(final InputStream delegate) {
+ public BOMInputStream(final InputStream delegate) throws IOException {
this(delegate, false, Builder.DEFAULT);
}
/**
* Constructs a new BOM InputStream that detects a {@link ByteOrderMark#UTF_8} and optionally includes it.
*
- * @param delegate
- * the InputStream to delegate to
- * @param include
- * true to include the UTF-8 BOM or false to exclude it
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param delegate the InputStream to delegate to.
+ * @param include true to include the UTF-8 BOM or false to exclude it.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
- public BOMInputStream(final InputStream delegate, final boolean include) {
+ public BOMInputStream(final InputStream delegate, final boolean include) throws IOException {
this(delegate, include, Builder.DEFAULT);
}
/**
* Constructs a new BOM InputStream that detects the specified BOMs and optionally includes them.
*
- * @param delegate
- * the InputStream to delegate to
- * @param include
- * true to include the specified BOMs or false to exclude them
- * @param boms
- * The BOMs to detect and optionally exclude
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param delegate the InputStream to delegate to.
+ * @param include true to include the specified BOMs or false to exclude them.
+ * @param boms The BOMs to detect and optionally exclude.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
- public BOMInputStream(final InputStream delegate, final boolean include, final ByteOrderMark... boms) {
+ public BOMInputStream(final InputStream delegate, final boolean include, final ByteOrderMark... boms) throws IOException {
super(delegate);
if (IOUtils.length(boms) == 0) {
throw new IllegalArgumentException("No BOMs specified");
@@ -297,19 +293,19 @@ public BOMInputStream(final InputStream delegate, final boolean include, final B
// Sort the BOMs to match the longest BOM first because some BOMs have the same starting two bytes.
list.sort(ByteOrderMarkLengthComparator);
this.bomList = list;
+ this.byteOrderMark = readBom();
}
/**
* Constructs a new BOM InputStream that excludes the specified BOMs.
*
- * @param delegate
- * the InputStream to delegate to
- * @param boms
- * The BOMs to detect and exclude
+ * @param delegate the InputStream to delegate to.
+ * @param boms The BOMs to detect and exclude.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
- public BOMInputStream(final InputStream delegate, final ByteOrderMark... boms) {
+ public BOMInputStream(final InputStream delegate, final ByteOrderMark... boms) throws IOException {
this(delegate, false, boms);
}
@@ -326,34 +322,26 @@ private ByteOrderMark find() {
* Gets the ByteOrderMark (Byte Order Mark).
*
* @return The BOM or null if none matched.
- * @throws IOException
- * if an error reading the first bytes of the stream occurs.
*/
- public ByteOrderMark getBOM() throws IOException {
- if (firstBytes == null) {
- byteOrderMark = readBom();
- }
+ public ByteOrderMark getBOM() {
return byteOrderMark;
}
/**
* Gets the BOM charset Name - {@link ByteOrderMark#getCharsetName()}.
*
- * @return The BOM charset Name or null if no BOM found
- * @throws IOException
- * if an error reading the first bytes of the stream occurs
+ * @return The BOM charset Name or null if no BOM found.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
*/
public String getBOMCharsetName() throws IOException {
- getBOM();
return byteOrderMark == null ? null : byteOrderMark.getCharsetName();
}
/**
* Tests whether the stream contains one of the specified BOMs.
*
- * @return true if the stream has one of the specified BOMs, otherwise false if it does not
- * @throws IOException
- * if an error reading the first bytes of the stream occurs
+ * @return true if the stream has one of the specified BOMs, otherwise false if it does not.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
*/
public boolean hasBOM() throws IOException {
return getBOM() != null;
@@ -362,13 +350,10 @@ public boolean hasBOM() throws IOException {
/**
* Tests whether the stream contains the specified BOM.
*
- * @param bom
- * The BOM to check for
- * @return true if the stream has the specified BOM, otherwise false if it does not
- * @throws IllegalArgumentException
- * if the BOM is not one the stream is configured to detect
- * @throws IOException
- * if an error reading the first bytes of the stream occurs
+ * @param bom The BOM to check for.
+ * @return true if the stream has the specified BOM, otherwise false if it does not.
+ * @throws IllegalArgumentException if the BOM is not one the stream is configured to detect.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
*/
public boolean hasBOM(final ByteOrderMark bom) throws IOException {
if (!bomList.contains(bom)) {
@@ -378,10 +363,9 @@ public boolean hasBOM(final ByteOrderMark bom) throws IOException {
}
/**
- * Invokes the delegate's {@code mark(int)} method.
+ * Invokes the delegate's {@link InputStream#mark(int)} method.
*
- * @param readLimit
- * read ahead limit
+ * @param readLimit read ahead limit.
*/
@Override
public synchronized void mark(final int readLimit) {
@@ -393,9 +377,8 @@ public synchronized void mark(final int readLimit) {
/**
* Checks if the bytes match a BOM.
*
- * @param bom
- * The BOM
- * @return true if the bytes match the bom, otherwise false
+ * @param bom The BOM.
+ * @return true if the bytes match the BOM, otherwise false.
*/
private boolean matches(final ByteOrderMark bom) {
return bom.matches(firstBytes);
@@ -404,9 +387,8 @@ private boolean matches(final ByteOrderMark bom) {
/**
* Invokes the delegate's {@code read()} method, detecting and optionally skipping BOM.
*
- * @return the byte read (excluding BOM) or -1 if the end of stream
- * @throws IOException
- * if an I/O error occurs
+ * @return the byte read (excluding BOM) or -1 if the end of stream.
+ * @throws IOException if an I/O error occurs.
*/
@Override
public int read() throws IOException {
@@ -416,15 +398,12 @@ public int read() throws IOException {
}
/**
- * Invokes the delegate's {@code read(byte[])} method, detecting and optionally skipping BOM.
+ * Invokes the delegate's {@link InputStream#read(byte[])} method, detecting and optionally skipping BOM.
*
- * @param buf
- * the buffer to read the bytes into, never {@code null}
- * @return the number of bytes read (excluding BOM) or -1 if the end of stream
- * @throws NullPointerException
- * if the buffer is {@code null}
- * @throws IOException
- * if an I/O error occurs
+ * @param buf the buffer to read the bytes into, never {@code null}
+ * @return the number of bytes read (excluding BOM) or -1 if the end of stream.
+ * @throws NullPointerException if the buffer is {@code null}
+ * @throws IOException if an I/O error occurs.
*/
@Override
public int read(final byte[] buf) throws IOException {
@@ -432,21 +411,15 @@ public int read(final byte[] buf) throws IOException {
}
/**
- * Invokes the delegate's {@code read(byte[], int, int)} method, detecting and optionally skipping BOM.
+ * Invokes the delegate's {@link InputStream#read(byte[], int, int)} method, detecting and optionally skipping BOM.
*
- * @param buf
- * the buffer to read the bytes into
- * @param off
- * The start offset
- * @param len
- * The number of bytes to read (excluding BOM)
- * @return the number of bytes read or -1 if the end of stream
- * @throws NullPointerException
- * if the buffer is {@code null}
- * @throws IndexOutOfBoundsException
- * if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code buf.length}
- * @throws IOException
- * if an I/O error occurs
+ * @param buf the buffer to read the bytes into.
+ * @param off The start offset.
+ * @param len The number of bytes to read (excluding BOM).
+ * @return the number of bytes read or -1 if the end of stream.
+ * @throws NullPointerException if the buffer is {@code null}.
+ * @throws IndexOutOfBoundsException if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code buf.length}.
+ * @throws IOException if an I/O error occurs.
*/
@Override
public int read(final byte[] buf, int off, int len) throws IOException {
@@ -469,6 +442,12 @@ public int read(final byte[] buf, int off, int len) throws IOException {
return secondCount < 0 ? firstCount > 0 ? firstCount : EOF : firstCount + secondCount;
}
+ /**
+ * Reads the byte order mark.
+ *
+ * @return the byte order mark.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
+ */
private ByteOrderMark readBom() throws IOException {
int fbLength = 0;
// BOMs are sorted from longest to shortest
@@ -501,18 +480,16 @@ private ByteOrderMark readBom() throws IOException {
* valid byte or -1 to indicate that the initial bytes have been processed already.
*
* @return the byte read (excluding BOM) or -1 if at the end of first bytes.
- * @throws IOException if an I/O error occurs
+ * @throws IOException if an I/O error occurs.
*/
private int readFirstBytes() throws IOException {
- getBOM();
return fbIndex < firstBytes.length ? firstBytes[fbIndex++] : EOF;
}
/**
- * Invokes the delegate's {@code reset()} method.
+ * Invokes the delegate's {@link InputStream#reset()} method.
*
- * @throws IOException
- * if an I/O error occurs
+ * @throws IOException if an I/O error occurs.
*/
@Override
public synchronized void reset() throws IOException {
@@ -524,13 +501,11 @@ public synchronized void reset() throws IOException {
}
/**
- * Invokes the delegate's {@code skip(long)} method, detecting and optionally skipping BOM.
+ * Invokes the delegate's {@link InputStream#skip(long)} method, detecting and optionally skipping BOM.
*
- * @param n
- * the number of bytes to skip
- * @return the number of bytes to skipped or -1 if the end of stream
- * @throws IOException
- * if an I/O error occurs
+ * @param n the number of bytes to skip.
+ * @return the number of bytes to skipped or -1 if the end of stream.
+ * @throws IOException if an I/O error occurs.
*/
@Override
public long skip(final long n) throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/BoundedInputStream.java b/src/main/java/org/apache/commons/io/input/BoundedInputStream.java
index e3e2d86bf0f..d9fbac8b104 100644
--- a/src/main/java/org/apache/commons/io/input/BoundedInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/BoundedInputStream.java
@@ -82,6 +82,7 @@
* .get();
* }
*
+ *
* @see Builder
* @since 2.0
*/
diff --git a/src/main/java/org/apache/commons/io/input/BoundedReader.java b/src/main/java/org/apache/commons/io/input/BoundedReader.java
index 5c1c255c0fe..5ba0dfe6b18 100644
--- a/src/main/java/org/apache/commons/io/input/BoundedReader.java
+++ b/src/main/java/org/apache/commons/io/input/BoundedReader.java
@@ -36,12 +36,10 @@
*
* @since 2.5
*/
-public class BoundedReader extends Reader {
+public class BoundedReader extends ProxyReader {
private static final int INVALID = -1;
- private final Reader target;
-
private int charsRead;
private int markedAt = INVALID;
@@ -53,24 +51,14 @@ public class BoundedReader extends Reader {
/**
* Constructs a bounded reader
*
- * @param target The target stream that will be used
- * @param maxCharsFromTargetReader The maximum number of characters that can be read from target
+ * @param target The target stream that will be used.
+ * @param maxCharsFromTargetReader The maximum number of characters that can be read from target.
*/
public BoundedReader(final Reader target, final int maxCharsFromTargetReader) {
- this.target = target;
+ super(target);
this.maxCharsFromTargetReader = maxCharsFromTargetReader;
}
- /**
- * Closes the target
- *
- * @throws IOException If an I/O error occurs while calling the underlying reader's close method
- */
- @Override
- public void close() throws IOException {
- target.close();
- }
-
/**
* marks the target stream
*
@@ -78,49 +66,42 @@ public void close() throws IOException {
* Note that this parameter is not validated with respect to maxCharsFromTargetReader. There
* is no way to pass past maxCharsFromTargetReader, even if this value is greater.
*
- * @throws IOException If an I/O error occurs while calling the underlying reader's mark method
+ * @throws IOException If an I/O error occurs while calling the underlying reader's mark method.
* @see Reader#mark(int)
*/
@Override
public void mark(final int readAheadLimit) throws IOException {
this.readAheadLimit = readAheadLimit - charsRead;
-
markedAt = charsRead;
-
- target.mark(readAheadLimit);
+ super.mark(readAheadLimit);
}
/**
* Reads a single character
*
- * @return -1 on EOF or the character read
- * @throws IOException If an I/O error occurs while calling the underlying reader's read method
+ * @return -1 on EOF or the character read.
+ * @throws IOException If an I/O error occurs while calling the underlying reader's read method.
* @see Reader#read()
*/
@Override
public int read() throws IOException {
-
- if (charsRead >= maxCharsFromTargetReader) {
- return EOF;
- }
-
- if (markedAt >= 0 && charsRead - markedAt >= readAheadLimit) {
+ if (charsRead >= maxCharsFromTargetReader || markedAt >= 0 && charsRead - markedAt >= readAheadLimit) {
return EOF;
}
charsRead++;
- return target.read();
+ return super.read();
}
/**
* Reads into an array
*
- * @param cbuf The buffer to fill
- * @param off The offset
- * @param len The number of chars to read
- * @return the number of chars read
+ * @param cbuf The buffer to fill.
+ * @param off The offset.
+ * @param len The number of chars to read.
+ * @return the number of chars read.
* @throws NullPointerException if the buffer is {@code null}.
* @throws IndexOutOfBoundsException if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code cbuf.length}.
- * @throws IOException If an I/O error occurs while calling the underlying reader's read method
+ * @throws IOException If an I/O error occurs while calling the underlying reader's read method.
* @see Reader#read(char[], int, int)
*/
@Override
@@ -140,12 +121,18 @@ public int read(final char[] cbuf, final int off, final int len) throws IOExcept
/**
* Resets the target to the latest mark,
*
- * @throws IOException If an I/O error occurs while calling the underlying reader's reset method
+ * @throws IOException If an I/O error occurs while calling the underlying reader's reset method.
* @see Reader#reset()
*/
@Override
public void reset() throws IOException {
charsRead = markedAt;
- target.reset();
+ super.reset();
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ charsRead += n;
+ return super.skip(n);
}
}
diff --git a/src/main/java/org/apache/commons/io/input/BrokenInputStream.java b/src/main/java/org/apache/commons/io/input/BrokenInputStream.java
index bc491637dee..cd2e2fce9c3 100644
--- a/src/main/java/org/apache/commons/io/input/BrokenInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/BrokenInputStream.java
@@ -106,7 +106,7 @@ public void close() throws IOException {
/**
* Gets the Throwable to throw. Package-private for testing.
*
- * @return the Throwable to throw.
+ * @return the Throwable to throw.
*/
Throwable getThrowable() {
return exceptionSupplier.get();
diff --git a/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java b/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java
index 8e81b34508a..4fab37a9838 100644
--- a/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java
@@ -137,6 +137,8 @@ public static Builder builder() {
private final ByteBuffer byteBuffer;
+ private boolean clean;
+
private final FileChannel fileChannel;
@SuppressWarnings("resource")
@@ -150,7 +152,7 @@ private BufferedFileChannelInputStream(final Builder builder) throws IOException
* Constructs a new instance for the given File.
*
* @param file The file to stream.
- * @throws IOException If an I/O error occurs
+ * @throws IOException If an I/O error occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
@@ -163,7 +165,7 @@ public BufferedFileChannelInputStream(final File file) throws IOException {
*
* @param file The file to stream.
* @param bufferSize buffer size.
- * @throws IOException If an I/O error occurs
+ * @throws IOException If an I/O error occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
@@ -175,7 +177,7 @@ public BufferedFileChannelInputStream(final File file, final int bufferSize) thr
* Constructs a new instance for the given Path.
*
* @param path The path to stream.
- * @throws IOException If an I/O error occurs
+ * @throws IOException If an I/O error occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
@@ -188,7 +190,7 @@ public BufferedFileChannelInputStream(final Path path) throws IOException {
*
* @param path The path to stream.
* @param bufferSize buffer size.
- * @throws IOException If an I/O error occurs
+ * @throws IOException If an I/O error occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
@@ -198,10 +200,7 @@ public BufferedFileChannelInputStream(final Path path, final int bufferSize) thr
@Override
public synchronized int available() throws IOException {
- if (!fileChannel.isOpen()) {
- return 0;
- }
- if (!refill()) {
+ if (!fileChannel.isOpen() || !refill()) {
return 0;
}
return byteBuffer.remaining();
@@ -212,26 +211,18 @@ public synchronized int available() throws IOException {
* disposed buffer. However, neither the bytes allocated to direct buffers nor file descriptors opened for memory-mapped buffers put pressure on the garbage
* collector. Waiting for garbage collection may lead to the depletion of off-heap memory or huge numbers of open files. There's unfortunately no standard
* API to manually dispose of these kinds of buffers.
- *
- * @param buffer the buffer to clean.
- */
- private void clean(final ByteBuffer buffer) {
- if (buffer.isDirect()) {
- cleanDirectBuffer(buffer);
- }
- }
-
- /**
+ *
* In Java 8, the type of {@code sun.nio.ch.DirectBuffer.cleaner()} was {@code sun.misc.Cleaner}, and it was possible to access the method
* {@code sun.misc.Cleaner.clean()} to invoke it. The type changed to {@code jdk.internal.ref.Cleaner} in later JDKs, and the {@code clean()} method is not
* accessible even with reflection. However {@code sun.misc.Unsafe} added an {@code invokeCleaner()} method in JDK 9+ and this is still accessible with
* reflection.
- *
- * @param buffer the buffer to clean. must be a DirectBuffer.
+ *
+ * @param buffer the buffer to clean.
*/
- private void cleanDirectBuffer(final ByteBuffer buffer) {
- if (ByteBufferCleaner.isSupported()) {
+ private void clean(final ByteBuffer buffer) {
+ if (!clean && ByteBufferCleaner.isSupported()) {
ByteBufferCleaner.clean(buffer);
+ clean = true;
}
}
@@ -244,6 +235,10 @@ public synchronized void close() throws IOException {
}
}
+ boolean isClean() {
+ return clean;
+ }
+
@Override
public synchronized int read() throws IOException {
if (!refill()) {
@@ -269,7 +264,7 @@ public synchronized int read(final byte[] b, final int offset, int len) throws I
/**
* Checks whether data is left to be read from the input stream.
*
- * @return true if data is left, false otherwise
+ * @return true if data is left, false otherwise.
* @throws IOException if an I/O error occurs.
*/
private boolean refill() throws IOException {
@@ -304,6 +299,7 @@ public synchronized long skip(final long n) throws IOException {
return skippedFromBuffer + skipFromFileChannel(toSkipFromFileChannel);
}
+
private long skipFromFileChannel(final long n) throws IOException {
final long currentFilePosition = fileChannel.position();
final long size = fileChannel.size();
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 743ea44253c..6debbfb8449 100644
--- a/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
+++ b/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
@@ -14,19 +14,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.apache.commons.io.input;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
+import org.apache.commons.io.Buffers;
+
/**
- * Cleans a direct {@link ByteBuffer}. Without manual intervention, direct ByteBuffers will be cleaned eventually upon
- * garbage collection. However, this should not be relied upon since it may not occur in a timely fashion -
- * especially since off heap ByeBuffers don't put pressure on the garbage collector.
+ * Cleans a direct {@link ByteBuffer}. Without manual intervention, direct ByteBuffers will be cleaned eventually upon garbage collection. However, this should
+ * not be relied upon since it may not occur in a timely fashion - especially since off heap ByeBuffers don't put pressure on the garbage collector.
*
- * Warning: Do not attempt to use a direct {@link ByteBuffer} that has been cleaned or bad things will happen.
- * Don't use this class unless you can ensure that the cleaned buffer will not be accessed anymore.
+ * Warning: Do not attempt to use a direct {@link ByteBuffer} that has been cleaned or bad things will happen. Don't use this class unless you
+ * can ensure that the cleaned buffer will not be accessed anymore.
*
*
* See JDK-4724038
@@ -35,6 +37,7 @@
final class ByteBufferCleaner {
private interface Cleaner {
+
void clean(ByteBuffer buffer) throws ReflectiveOperationException;
}
@@ -86,7 +89,10 @@ public void clean(final ByteBuffer buffer) throws ReflectiveOperationException {
*/
static void clean(final ByteBuffer buffer) {
try {
- INSTANCE.clean(buffer);
+ if (buffer.isDirect()) {
+ Buffers.clearWritable(buffer);
+ INSTANCE.clean(buffer);
+ }
} catch (final Exception e) {
throw new IllegalStateException("Failed to clean direct buffer.", e);
}
@@ -105,8 +111,8 @@ private static Cleaner getCleaner() {
}
/**
- * Tests if were able to load a suitable cleaner for the current JVM. Attempting to call
- * {@code ByteBufferCleaner#clean(ByteBuffer)} when this method returns false will result in an exception.
+ * Tests if were able to load a suitable cleaner for the current JVM. Attempting to call {@code ByteBufferCleaner#clean(ByteBuffer)} when this method
+ * returns false will result in an exception.
*
* @return {@code true} if cleaning is supported, {@code false} otherwise.
*/
diff --git a/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java b/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java
index 874dcf1cb39..689424c062f 100644
--- a/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java
@@ -281,6 +281,7 @@ CharsetEncoder getCharsetEncoder() {
/**
* {@inheritDoc}
+ *
* @param readLimit max read limit (ignored).
*/
@Override
diff --git a/src/main/java/org/apache/commons/io/input/CharSequenceReader.java b/src/main/java/org/apache/commons/io/input/CharSequenceReader.java
index bb2be3692c9..60026b84429 100644
--- a/src/main/java/org/apache/commons/io/input/CharSequenceReader.java
+++ b/src/main/java/org/apache/commons/io/input/CharSequenceReader.java
@@ -99,8 +99,8 @@ public CharSequenceReader(final CharSequence charSequence) {
*
*
* @param charSequence The character sequence, may be {@code null}
- * @param start The start index in the character sequence, inclusive
- * @throws IllegalArgumentException if the start index is negative
+ * @param start The start index in the character sequence, inclusive.
+ * @throws IllegalArgumentException if the start index is negative.
* @since 2.7
*/
public CharSequenceReader(final CharSequence charSequence, final int start) {
@@ -120,9 +120,9 @@ public CharSequenceReader(final CharSequence charSequence, final int start) {
*
*
* @param charSequence The character sequence, may be {@code null}
- * @param start The start index in the character sequence, inclusive
- * @param end The end index in the character sequence, exclusive
- * @throws IllegalArgumentException if the start index is negative, or if the end index is smaller than the start index
+ * @param start The start index in the character sequence, inclusive.
+ * @param end The end index in the character sequence, exclusive.
+ * @throws IllegalArgumentException if the start index is negative, or if the end index is smaller than the start index.
* @since 2.7
*/
public CharSequenceReader(final CharSequence charSequence, final int start, final int end) {
@@ -168,7 +168,7 @@ private int end() {
/**
* Mark the current position.
*
- * @param readAheadLimit ignored
+ * @param readAheadLimit ignored.
*/
@Override
public void mark(final int readAheadLimit) {
@@ -202,10 +202,10 @@ public int read() {
/**
* Reads the specified number of characters into the array.
*
- * @param array The array to store the characters in
- * @param offset The starting position in the array to store
- * @param length The maximum number of characters to read
- * @return The number of characters read or -1 if there are no more
+ * @param array The array to store the characters in.
+ * @param offset The starting position in the array to store.
+ * @param length The maximum number of characters to read.
+ * @return The number of characters read or -1 if there are no more.
* @throws NullPointerException if the array is {@code null}.
* @throws IndexOutOfBoundsException if {@code offset} or {@code length} are negative, or if {@code offset + length} is greater than {@code array.length}.
*/
@@ -272,8 +272,8 @@ public void reset() {
/**
* Skip the specified number of characters.
*
- * @param n The number of characters to skip
- * @return The actual number of characters skipped
+ * @param n The number of characters to skip.
+ * @return The actual number of characters skipped.
*/
@Override
public long skip(final long n) {
@@ -302,7 +302,7 @@ private int start() {
* Gets a String representation of the underlying
* character sequence.
*
- * @return The contents of the character sequence
+ * @return The contents of the character sequence.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/input/ClassLoaderObjectInputStream.java b/src/main/java/org/apache/commons/io/input/ClassLoaderObjectInputStream.java
index fef0d6cf17b..4b2828390e8 100644
--- a/src/main/java/org/apache/commons/io/input/ClassLoaderObjectInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ClassLoaderObjectInputStream.java
@@ -40,10 +40,10 @@ public class ClassLoaderObjectInputStream extends ObjectInputStream {
/**
* Constructs a new ClassLoaderObjectInputStream.
*
- * @param classLoader the ClassLoader from which classes should be loaded
- * @param inputStream the InputStream to work on
- * @throws IOException in case of an I/O error
- * @throws StreamCorruptedException if the stream is corrupted
+ * @param classLoader the ClassLoader from which classes should be loaded.
+ * @param inputStream the InputStream to work on.
+ * @throws IOException in case of an I/O error.
+ * @throws StreamCorruptedException if the stream is corrupted.
*/
public ClassLoaderObjectInputStream(
final ClassLoader classLoader, final InputStream inputStream)
@@ -56,10 +56,10 @@ public ClassLoaderObjectInputStream(
* Resolve a class specified by the descriptor using the
* specified ClassLoader or the super ClassLoader.
*
- * @param objectStreamClass descriptor of the class
- * @return the Class object described by the ObjectStreamClass
- * @throws IOException in case of an I/O error
- * @throws ClassNotFoundException if the Class cannot be found
+ * @param objectStreamClass descriptor of the class.
+ * @return the Class object described by the ObjectStreamClass.
+ * @throws IOException in case of an I/O error.
+ * @throws ClassNotFoundException if the Class cannot be found.
*/
@Override
protected Class> resolveClass(final ObjectStreamClass objectStreamClass)
@@ -76,10 +76,10 @@ protected Class> resolveClass(final ObjectStreamClass objectStreamClass)
* Create a proxy class that implements the specified interfaces using
* the specified ClassLoader or the super ClassLoader.
*
- * @param interfaces the interfaces to implement
- * @return a proxy class implementing the interfaces
- * @throws IOException in case of an I/O error
- * @throws ClassNotFoundException if the Class cannot be found
+ * @param interfaces the interfaces to implement.
+ * @return a proxy class implementing the interfaces.
+ * @throws IOException in case of an I/O error.
+ * @throws ClassNotFoundException if the Class cannot be found.
* @see ObjectInputStream#resolveProxyClass(String[])
* @since 2.1
*/
diff --git a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java b/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java
index 001bfca6f55..b58c6a891ac 100644
--- a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java
@@ -16,8 +16,11 @@
*/
package org.apache.commons.io.input;
+import java.io.IOException;
import java.io.InputStream;
+import org.apache.commons.io.function.IOUnaryOperator;
+
/**
* Proxy stream that prevents the underlying input stream from being closed.
*
@@ -30,6 +33,50 @@
*/
public class CloseShieldInputStream extends ProxyInputStream {
+ /**
+ * Constructs a new builder for {@link CloseShieldInputStream}.
+ *
+ * @since 2.22.0
+ */
+ public static class Builder extends AbstractBuilder {
+
+ private IOUnaryOperator onClose = is -> ClosedInputStream.INSTANCE;
+
+ /**
+ * Constructs a new instance.
+ */
+ public Builder() {
+ // empty
+ }
+
+ @Override
+ public CloseShieldInputStream get() throws IOException {
+ return new CloseShieldInputStream(this);
+ }
+
+ /**
+ * Sets the {@code onClose} function. By default, replaces the underlying input stream when {@link #close()} is called.
+ *
+ * @param onClose the onClose function.
+ * @return {@code this} instance.
+ */
+ public Builder setOnClose(final IOUnaryOperator onClose) {
+ this.onClose = onClose;
+ return asThis();
+ }
+
+ }
+
+ /**
+ * Constructs a new builder for {@link CloseShieldInputStream}.
+ *
+ * @return the new builder.
+ * @since 2.22.0
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
/**
* Constructs a proxy that only shields {@link System#in} from closing.
*
@@ -44,18 +91,25 @@ public static InputStream systemIn(final InputStream inputStream) {
/**
* Constructs a proxy that shields the given input stream from being closed.
*
- * @param inputStream the input stream to wrap
- * @return the created proxy
+ * @param inputStream the input stream to wrap.
+ * @return the created proxy.
* @since 2.9.0
*/
public static CloseShieldInputStream wrap(final InputStream inputStream) {
return new CloseShieldInputStream(inputStream);
}
+ private final IOUnaryOperator onClose;
+
+ private CloseShieldInputStream(final Builder builder) throws IOException {
+ super(builder.getInputStream());
+ this.onClose = builder.onClose;
+ }
+
/**
* Constructs a proxy that shields the given input stream from being closed.
*
- * @param inputStream underlying input stream
+ * @param inputStream underlying input stream.
* @deprecated Using this constructor prevents IDEs from warning if the
* underlying input stream is never closed. Use
* {@link #wrap(InputStream)} instead.
@@ -63,16 +117,21 @@ public static CloseShieldInputStream wrap(final InputStream inputStream) {
@Deprecated
public CloseShieldInputStream(final InputStream inputStream) {
super(inputStream);
+ this.onClose = builder().onClose;
}
/**
- * Replaces the underlying input stream with a {@link ClosedInputStream}
- * sentinel. The original input stream will remain open, but this proxy will
- * appear closed.
+ * Applies the {@code onClose} function to the underlying input stream, replacing it with the result.
+ *
+ * By default, replaces the underlying input stream with a {@link ClosedInputStream} sentinel. The original input stream will remain open, but this proxy
+ * will appear closed.
+ *
+ *
+ * @throws IOException Thrown by the {@code onClose} function.
*/
@Override
- public void close() {
- in = ClosedInputStream.INSTANCE;
+ public void close() throws IOException {
+ in = onClose.apply(in);
}
}
diff --git a/src/main/java/org/apache/commons/io/input/CloseShieldReader.java b/src/main/java/org/apache/commons/io/input/CloseShieldReader.java
index c6f116db765..e271627ceea 100644
--- a/src/main/java/org/apache/commons/io/input/CloseShieldReader.java
+++ b/src/main/java/org/apache/commons/io/input/CloseShieldReader.java
@@ -33,8 +33,8 @@ public class CloseShieldReader extends ProxyReader {
/**
* Constructs a proxy that shields the given reader from being closed.
*
- * @param reader the reader to wrap
- * @return the created proxy
+ * @param reader the reader to wrap.
+ * @return the created proxy.
* @since 2.9.0
*/
public static CloseShieldReader wrap(final Reader reader) {
@@ -44,7 +44,7 @@ public static CloseShieldReader wrap(final Reader reader) {
/**
* Constructs a proxy that shields the given reader from being closed.
*
- * @param reader underlying reader
+ * @param reader underlying reader.
* @deprecated Using this constructor prevents IDEs from warning if the
* underlying reader is never closed. Use {@link #wrap(Reader)}
* instead.
diff --git a/src/main/java/org/apache/commons/io/input/CountingInputStream.java b/src/main/java/org/apache/commons/io/input/CountingInputStream.java
index f14e7130507..1182309f07f 100644
--- a/src/main/java/org/apache/commons/io/input/CountingInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/CountingInputStream.java
@@ -40,7 +40,7 @@ public class CountingInputStream extends ProxyInputStream {
/**
* Constructs a new CountingInputStream.
*
- * @param in the InputStream to delegate to
+ * @param in the InputStream to delegate to.
*/
public CountingInputStream(final InputStream in) {
super(in);
@@ -57,7 +57,7 @@ public CountingInputStream(final InputStream in) {
/**
* Adds the number of read bytes to the count.
*
- * @param n number of bytes read, or -1 if no more bytes are available
+ * @param n number of bytes read, or -1 if no more bytes are available.
* @throws IOException Not thrown here but subclasses may throw.
* @since 2.0
*/
@@ -77,7 +77,7 @@ protected synchronized void afterRead(final int n) throws IOException {
* result in incorrect count for files over 2GB.
*
*
- * @return the number of bytes accumulated
+ * @return the number of bytes accumulated.
* @since 1.3
*/
public synchronized long getByteCount() {
@@ -92,8 +92,8 @@ public synchronized long getByteCount() {
* See {@link #getByteCount()} for a method using a {@code long}.
*
*
- * @return the number of bytes accumulated
- * @throws ArithmeticException if the byte count is too large
+ * @return the number of bytes accumulated.
+ * @throws ArithmeticException if the byte count is too large.
* @deprecated Use {@link #getByteCount()}.
*/
@Deprecated
@@ -113,7 +113,7 @@ public int getCount() {
* result in incorrect count for files over 2GB.
*
*
- * @return the count previous to resetting
+ * @return the count previous to resetting.
* @since 1.3
*/
public synchronized long resetByteCount() {
@@ -130,8 +130,8 @@ public synchronized long resetByteCount() {
* See {@link #resetByteCount()} for a method using a {@code long}.
*
*
- * @return the count previous to resetting
- * @throws ArithmeticException if the byte count is too large
+ * @return the count previous to resetting.
+ * @throws ArithmeticException if the byte count is too large.
* @deprecated Use {@link #resetByteCount()}.
*/
@Deprecated
@@ -147,8 +147,8 @@ public int resetCount() {
* Skips the stream over the specified number of bytes, adding the skipped
* amount to the count.
*
- * @param length the number of bytes to skip
- * @return the actual number of bytes skipped
+ * @param length the number of bytes to skip.
+ * @return the actual number of bytes skipped.
* @throws IOException if an I/O error occurs.
* @see InputStream#skip(long)
*/
diff --git a/src/main/java/org/apache/commons/io/input/DemuxInputStream.java b/src/main/java/org/apache/commons/io/input/DemuxInputStream.java
index ad49dca2793..3a0132dc8e6 100644
--- a/src/main/java/org/apache/commons/io/input/DemuxInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/DemuxInputStream.java
@@ -40,8 +40,8 @@ public DemuxInputStream() {
/**
* Binds the specified stream to the current thread.
*
- * @param input the stream to bind
- * @return the InputStream that was previously active
+ * @param input the stream to bind.
+ * @return the InputStream that was previously active.
*/
public InputStream bindStream(final InputStream input) {
final InputStream oldValue = inputStreamLocal.get();
@@ -52,7 +52,7 @@ public InputStream bindStream(final InputStream input) {
/**
* Closes stream associated with current thread.
*
- * @throws IOException if an error occurs
+ * @throws IOException if an error occurs.
*/
@SuppressWarnings("resource") // we actually close the stream here
@Override
@@ -63,8 +63,8 @@ public void close() throws IOException {
/**
* Reads byte from stream associated with current thread.
*
- * @return the byte read from stream
- * @throws IOException if an error occurs
+ * @return the byte read from stream.
+ * @throws IOException if an error occurs.
*/
@Override
public int read() throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/Input.java b/src/main/java/org/apache/commons/io/input/Input.java
index 70147681178..b5b626a42c6 100644
--- a/src/main/java/org/apache/commons/io/input/Input.java
+++ b/src/main/java/org/apache/commons/io/input/Input.java
@@ -18,14 +18,15 @@
package org.apache.commons.io.input;
import java.io.IOException;
+import java.io.InterruptedIOException;
/**
* Package-wide internals for input.
*/
-class Input {
+final class Input {
/**
- * Throws an IOException on false input.
+ * Throws an {@link IOException} on false input.
*
* @param isOpen whether an input is open or not.
* @throws IOException if {@code isOpen} is false indicating an input is closed.
@@ -36,4 +37,21 @@ static void checkOpen(final boolean isOpen) throws IOException {
}
}
+ /**
+ * Converts an {@link InterruptedException} to an {@link InterruptedIOException}.
+ *
+ * The cause of the returned InterruptedIOException is set to the original.
+ *
+ *
+ * @param e The InterruptedException to convert.
+ * @return The converted InterruptedIOException.
+ * @see InterruptedIOException
+ * @see Throwable#initCause(Throwable)
+ * @see Throwable#getCause()
+ */
+ static InterruptedIOException toInterruptedIOException(final InterruptedException e) {
+ final InterruptedIOException iio = new InterruptedIOException(e.getMessage());
+ iio.initCause(e);
+ return iio;
+ }
}
diff --git a/src/main/java/org/apache/commons/io/input/MarkShieldInputStream.java b/src/main/java/org/apache/commons/io/input/MarkShieldInputStream.java
index 44fb12ff56e..0ed0b0bfda6 100644
--- a/src/main/java/org/apache/commons/io/input/MarkShieldInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MarkShieldInputStream.java
@@ -40,7 +40,7 @@ public class MarkShieldInputStream extends ProxyInputStream {
* Constructs a proxy that shields the given input stream from being
* marked or rest.
*
- * @param in underlying input stream
+ * @param in underlying input stream.
*/
public MarkShieldInputStream(final InputStream in) {
super(in);
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 22fae70ca75..b8ddda491ec 100644
--- a/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
@@ -172,7 +172,7 @@ public int available() throws IOException {
}
private void cleanBuffer() {
- if (ByteBufferCleaner.isSupported() && buffer.isDirect()) {
+ if (ByteBufferCleaner.isSupported()) {
ByteBufferCleaner.clean(buffer);
}
}
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 5f2fb452ef0..7188c564502 100644
--- a/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
@@ -148,7 +148,7 @@ public static class MessageDigestMaintainingObserver extends Observer {
/**
* Constructs an MessageDigestMaintainingObserver for the given MessageDigest.
*
- * @param messageDigest the message digest to use
+ * @param messageDigest the message digest to use.
* @throws NullPointerException if messageDigest is null.
*/
public MessageDigestMaintainingObserver(final MessageDigest messageDigest) {
@@ -211,7 +211,7 @@ private MessageDigestCalculatingInputStream(final Builder builder) throws IOExce
* The MD5 algorithm is weak and should not be used.
*
*
- * @param inputStream the stream to calculate the message digest for
+ * @param inputStream the stream to calculate the message digest for.
* @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation for the specified algorithm.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@@ -226,8 +226,8 @@ public MessageDigestCalculatingInputStream(final InputStream inputStream) throws
* The MD5 cryptographic algorithm is weak and should not be used.
*
*
- * @param inputStream the stream to calculate the message digest for
- * @param messageDigest the message digest to use
+ * @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()}.
*/
@@ -243,7 +243,7 @@ public MessageDigestCalculatingInputStream(final InputStream inputStream, final
* The MD5 cryptographic algorithm is weak and should not be used.
*
*
- * @param inputStream the stream to calculate the message digest for
+ * @param inputStream the stream to calculate the message digest for.
* @param algorithm the name of the algorithm requested. See the MessageDigest section in the
* Java Cryptography
* Architecture Standard Algorithm Name Documentation for information about standard algorithm names.
@@ -262,7 +262,7 @@ public MessageDigestCalculatingInputStream(final InputStream inputStream, final
* data has been read, if that is what you want. The easiest way to do so is by invoking {@link #consume()}.
*
*
- * @return the message digest used
+ * @return the message digest used.
*/
public MessageDigest getMessageDigest() {
return messageDigest;
diff --git a/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java b/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java
index dac3f2afb5e..c8c3af88347 100644
--- a/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java
@@ -152,7 +152,7 @@ public static class MessageDigestMaintainingObserver extends Observer {
/**
* Constructs an MessageDigestMaintainingObserver for the given MessageDigest.
*
- * @param messageDigest the message digest to use
+ * @param messageDigest the message digest to use.
* @throws NullPointerException if messageDigest is null.
*/
public MessageDigestMaintainingObserver(final MessageDigest messageDigest) {
@@ -190,7 +190,7 @@ public static Builder builder() {
* The MD5 cryptographic algorithm is weak and should not be used.
*
*
- * @param builder A builder use to get the stream to calculate the message digest and the message digest to use
+ * @param builder A builder use to get the stream to calculate the message digest and the message digest to use.
* @throws NullPointerException if messageDigest is null.
*/
private MessageDigestInputStream(final Builder builder) throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/NullInputStream.java b/src/main/java/org/apache/commons/io/input/NullInputStream.java
index 5fa9b817b5c..1f05410f636 100644
--- a/src/main/java/org/apache/commons/io/input/NullInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/NullInputStream.java
@@ -272,7 +272,7 @@ public int read() throws IOException {
/**
* Reads some bytes into the specified array.
*
- * @param bytes The byte array to read into
+ * @param bytes The byte array to read into.
* @return The number of bytes read or {@code -1} if the end of file has been reached and {@code throwEofException} is set to {@code false}.
* @throws NullPointerException if the byte array is {@code null}.
* @throws EOFException if the end of file is reached and {@code throwEofException} is set to {@code true}.
diff --git a/src/main/java/org/apache/commons/io/input/NullReader.java b/src/main/java/org/apache/commons/io/input/NullReader.java
index 28f3d37eb21..0405f3943d0 100644
--- a/src/main/java/org/apache/commons/io/input/NullReader.java
+++ b/src/main/java/org/apache/commons/io/input/NullReader.java
@@ -217,7 +217,7 @@ protected int processChar() {
* This implementation leaves the character array unchanged.
*
*
- * @param chars The character array
+ * @param chars The character array.
* @param offset The offset to start at.
* @param length The number of characters.
*/
@@ -250,7 +250,7 @@ public int read() throws IOException {
/**
* Reads some characters into the specified array.
*
- * @param chars The character array to read into
+ * @param chars The character array to read into.
* @return The number of characters read or {@code -1}
* if the end of file has been reached and
* {@code throwEofException} is set to {@code false}.
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 a1287b857f7..1909f859a65 100644
--- a/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
@@ -144,7 +144,7 @@ public void data(final int value) throws IOException {
/**
* Called to indicate that an error occurred on the underlying stream.
*
- * @param exception the exception to throw
+ * @param exception the exception to throw.
* @throws IOException if an I/O error occurs.
*/
public void error(final IOException exception) throws IOException {
@@ -361,7 +361,7 @@ public int read(final byte[] buffer, final int offset, final int length) throws
/**
* Removes an Observer.
*
- * @param observer the observer to remove
+ * @param observer the observer to remove.
*/
public void remove(final Observer observer) {
observers.remove(observer);
diff --git a/src/main/java/org/apache/commons/io/input/ProxyInputStream.java b/src/main/java/org/apache/commons/io/input/ProxyInputStream.java
index b2e04c334b5..fdff24eac0e 100644
--- a/src/main/java/org/apache/commons/io/input/ProxyInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ProxyInputStream.java
@@ -27,7 +27,7 @@
import org.apache.commons.io.function.IOIntConsumer;
/**
- * A proxy stream which acts as a {@link FilterInputStream}, by passing all method calls on to the proxied stream, not changing which methods are called.
+ * An input stream proxy which delegates to the wrapped input stream.
*
* It is an alternative base class to {@link FilterInputStream} to increase reusability, because {@link FilterInputStream} changes the methods being called,
* such as read(byte[]) to read(byte[], int, int).
@@ -298,7 +298,7 @@ public int read() throws IOException {
* @return the number of bytes read or {@link IOUtils#EOF EOF} if we reached the end of stream.
* @throws IOException
*
+ * Use with caution. + *
* * @param in The input stream to set in {@link java.io.FilterInputStream#in}. * @return {@code this} instance. @@ -389,7 +392,7 @@ public long skip(final long n) throws IOException { /** * Unwraps this instance by returning the underlying {@link InputStream}. *- * Use with caution; useful to query the underlying {@link InputStream}. + * Use with caution. *
* * @return the underlying {@link InputStream}. diff --git a/src/main/java/org/apache/commons/io/input/ProxyReader.java b/src/main/java/org/apache/commons/io/input/ProxyReader.java index 7bfed636497..b450891ef27 100644 --- a/src/main/java/org/apache/commons/io/input/ProxyReader.java +++ b/src/main/java/org/apache/commons/io/input/ProxyReader.java @@ -26,9 +26,7 @@ import org.apache.commons.io.IOUtils; /** - * A Proxy stream which acts as expected, that is it passes the method - * calls on to the proxied stream and doesn't change which methods are - * being called. + * A reader proxy which delegates to the wrapped reader. ** It is an alternative base class to FilterReader * to increase reusability, because FilterReader changes the @@ -40,7 +38,7 @@ public abstract class ProxyReader extends FilterReader { /** * Constructs a new ProxyReader. * - * @param delegate the Reader to delegate to + * @param delegate the Reader to delegate to. */ public ProxyReader(final Reader delegate) { // the delegate is stored in a protected superclass variable named 'in' @@ -55,13 +53,15 @@ public ProxyReader(final Reader delegate) { * Subclasses can override this method to add common post-processing * functionality without having to override all the read methods. * The default implementation does nothing. + *
** Note this method is not called from {@link #skip(long)} or * {@link #reset()}. You need to explicitly override those methods if * you want to add post-processing steps also to them. + *
* - * @param n number of chars read, or -1 if the end of stream was reached - * @throws IOException if the post-processing fails + * @param n number of chars read, or -1 if the end of stream was reached. + * @throws IOException if the post-processing fails. * @since 2.0 */ @SuppressWarnings("unused") // Possibly thrown from subclasses. @@ -78,13 +78,15 @@ protected void afterRead(final int n) throws IOException { * Subclasses can override this method to add common pre-processing * functionality without having to override all the read methods. * The default implementation does nothing. + * ** Note this method is not called from {@link #skip(long)} or * {@link #reset()}. You need to explicitly override those methods if * you want to add pre-processing steps also to them. + *
* - * @param n number of chars that the caller asked to be read - * @throws IOException if the pre-processing fails + * @param n number of chars that the caller asked to be read. + * @throws IOException if the pre-processing fails. * @since 2.0 */ @SuppressWarnings("unused") // Possibly thrown from subclasses. @@ -94,6 +96,7 @@ protected void beforeRead(final int n) throws IOException { /** * Invokes the delegate's {@code close()} method. + * * @throws IOException if an I/O error occurs. */ @Override @@ -110,7 +113,9 @@ public void close() throws IOException { ** This method provides a point to implement custom exception * handling. The default behavior is to re-throw the exception. - * @param e The IOException thrown + *
+ * + * @param e The IOException thrown. * @throws IOException if an I/O error occurs. * @since 2.0 */ @@ -120,7 +125,8 @@ protected void handleIOException(final IOException e) throws IOException { /** * Invokes the delegate's {@code mark(int)} method. - * @param readAheadLimit read ahead limit + * + * @param readAheadLimit read ahead limit. * @throws IOException if an I/O error occurs. */ @Override @@ -134,7 +140,8 @@ public synchronized void mark(final int readAheadLimit) throws IOException { /** * Invokes the delegate's {@code markSupported()} method. - * @return true if mark is supported, otherwise false + * + * @return true if mark is supported, otherwise false. */ @Override public boolean markSupported() { @@ -143,7 +150,8 @@ public boolean markSupported() { /** * Invokes the delegate's {@code read()} method. - * @return the character read or -1 if the end of stream + * + * @return the character read or -1 if the end of stream. * @throws IOException if an I/O error occurs. */ @Override @@ -161,8 +169,9 @@ public int read() throws IOException { /** * Invokes the delegate's {@code read(char[])} method. - * @param chr the buffer to read the characters into - * @return the number of characters read or -1 if the end of stream + * + * @param chr the buffer to read the characters into. + * @return the number of characters read or -1 if the end of stream. * @throws IOException if an I/O error occurs. */ @Override @@ -180,10 +189,11 @@ public int read(final char[] chr) throws IOException { /** * Invokes the delegate's {@code read(char[], int, int)} method. - * @param chr the buffer to read the characters into - * @param st The start offset - * @param len The number of bytes to read - * @return the number of characters read or -1 if the end of stream + * + * @param chr the buffer to read the characters into. + * @param st The start offset. + * @param len The number of bytes to read. + * @return the number of characters read or -1 if the end of stream. * @throws IOException if an I/O error occurs. */ @Override @@ -201,8 +211,9 @@ public int read(final char[] chr, final int st, final int len) throws IOExceptio /** * Invokes the delegate's {@code read(CharBuffer)} method. - * @param target the char buffer to read the characters into - * @return the number of characters read or -1 if the end of stream + * + * @param target the char buffer to read the characters into. + * @return the number of characters read or -1 if the end of stream. * @throws IOException if an I/O error occurs. * @since 2.0 */ @@ -221,7 +232,8 @@ public int read(final CharBuffer target) throws IOException { /** * Invokes the delegate's {@code ready()} method. - * @return true if the stream is ready to be read + * + * @return true if the stream is ready to be read. * @throws IOException if an I/O error occurs. */ @Override @@ -236,6 +248,7 @@ public boolean ready() throws IOException { /** * Invokes the delegate's {@code reset()} method. + * * @throws IOException if an I/O error occurs. */ @Override @@ -247,10 +260,27 @@ public synchronized void reset() throws IOException { } } + /** + * Sets the underlying reader. + *+ * Use with caution. + *
+ * + * @param in The input stream to set in {@code java.io.Reader#in}. + * @return {@code this} instance. + * @since 2.22.0 + */ + public ProxyReader setReference(final Reader in) { + this.in = in; + return this; + } + + /** * Invokes the delegate's {@code skip(long)} method. - * @param ln the number of bytes to skip - * @return the number of bytes to skipped or EOF if the end of stream + * + * @param ln the number of bytes to skip. + * @return the number of bytes to skipped or EOF if the end of stream. * @throws IOException if an I/O error occurs. */ @Override @@ -263,4 +293,17 @@ public long skip(final long ln) throws IOException { } } + /** + * Unwraps this instance by returning the underlying {@link Reader}. + *+ * Use with caution. + *
+ * + * @return the underlying {@link Reader}. + * @since 2.22.0 + */ + public Reader unwrap() { + return in; + } + } diff --git a/src/main/java/org/apache/commons/io/input/QueueInputStream.java b/src/main/java/org/apache/commons/io/input/QueueInputStream.java index 5f701945cb3..d672d23fa2b 100644 --- a/src/main/java/org/apache/commons/io/input/QueueInputStream.java +++ b/src/main/java/org/apache/commons/io/input/QueueInputStream.java @@ -229,7 +229,7 @@ public int read() { /** * Reads up to {@code length} bytes of data from the input stream into - * an array of bytes. The first byte is read while honoring the timeout; the rest are read while not honoring + * an array of bytes. The first byte is read while honoring the timeout; the rest are read while not honoring * the timeout. The number of bytes actually read is returned as an integer. * * @param b the buffer into which the data is read. diff --git a/src/main/java/org/apache/commons/io/input/ReadAheadInputStream.java b/src/main/java/org/apache/commons/io/input/ReadAheadInputStream.java index bcee009a431..152cd42a586 100644 --- a/src/main/java/org/apache/commons/io/input/ReadAheadInputStream.java +++ b/src/main/java/org/apache/commons/io/input/ReadAheadInputStream.java @@ -20,7 +20,6 @@ import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InterruptedIOException; import java.nio.ByteBuffer; import java.util.Objects; import java.util.concurrent.ExecutorService; @@ -63,6 +62,9 @@ public class ReadAheadInputStream extends FilterInputStream { * .setExecutorService(Executors.newSingleThreadExecutor(ReadAheadInputStream::newThread)) * .get();} * + *+ * If an {@link ExecutorService} is not set, then a single-threaded daemon executor service is used. + *
* * @see #get() * @since 2.12.0 @@ -90,7 +92,7 @@ public Builder() { *+ * If not set, a single-threaded daemon executor service is used. + *
* - * @param executorService the executor service for the read-ahead thread. + * @param executorService the executor service for the read-ahead thread, may be {@code null}. * @return {@code this} instance. */ public Builder setExecutorService(final ExecutorService executorService) { @@ -203,7 +208,7 @@ private ReadAheadInputStream(final Builder builder) throws IOException { } /** - * Constructs an instance with the specified buffer size and read-ahead threshold + * Constructs an instance with the specified buffer size and read-ahead threshold. * * @param inputStream The underlying input stream. * @param bufferSizeInBytes The buffer size. @@ -215,7 +220,7 @@ public ReadAheadInputStream(final InputStream inputStream, final int bufferSizeI } /** - * Constructs an instance with the specified buffer size and read-ahead threshold + * Constructs an instance with the specified buffer size and read-ahead threshold. * * @param inputStream The underlying input stream. * @param bufferSizeInBytes The buffer size. @@ -228,7 +233,7 @@ public ReadAheadInputStream(final InputStream inputStream, final int bufferSizeI } /** - * Constructs an instance with the specified buffer size and read-ahead threshold + * Constructs an instance with the specified buffer size and read-ahead threshold. * * @param inputStream The underlying input stream. * @param bufferSizeInBytes The buffer size. @@ -239,7 +244,7 @@ private ReadAheadInputStream(final InputStream inputStream, final int bufferSize final boolean shutdownExecutorService) { super(Objects.requireNonNull(inputStream, "inputStream")); if (bufferSizeInBytes <= 0) { - throw new IllegalArgumentException("bufferSizeInBytes should be greater than 0, but the value is " + bufferSizeInBytes); + throw new IllegalArgumentException(String.format("bufferSizeInBytes <= 0, bufferSizeInBytes = %,d", bufferSizeInBytes)); } this.executorService = Objects.requireNonNull(executorService, "executorService"); this.shutdownExecutorService = shutdownExecutorService; @@ -287,21 +292,21 @@ public void close() throws IOException { } finally { stateChangeLock.unlock(); } - if (shutdownExecutorService) { try { - executorService.shutdownNow(); - executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); + shutdownAwait(); } catch (final InterruptedException e) { - final InterruptedIOException iio = new InterruptedIOException(e.getMessage()); - iio.initCause(e); - throw iio; + Thread.currentThread().interrupt(); + throw Input.toInterruptedIOException(e); } finally { if (isSafeToCloseUnderlyingInputStream) { super.close(); } } } + if (isSafeToCloseUnderlyingInputStream) { + super.close(); + } } private void closeUnderlyingInputStreamIfNecessary() { @@ -346,7 +351,6 @@ public int read(final byte[] b, final int offset, int len) throws IOException { if (len == 0) { return 0; } - if (!activeBuffer.hasRemaining()) { // No remaining in active buffer - lock and switch to write ahead buffer. stateChangeLock.lock(); @@ -459,6 +463,11 @@ private void readAsync() throws IOException { }); } + boolean shutdownAwait() throws InterruptedException { + executorService.shutdownNow(); + return executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); + } + private void signalAsyncReadComplete() { stateChangeLock.lock(); try { @@ -532,7 +541,7 @@ private long skipInternal(final long n) throws IOException { } /** - * Flips the active and read ahead buffer + * Flips the active and read ahead buffers. */ private void swapBuffers() { final ByteBuffer temp = activeBuffer; @@ -550,9 +559,8 @@ private void waitForAsyncReadComplete() throws IOException { asyncReadComplete.await(); } } catch (final InterruptedException e) { - final InterruptedIOException iio = new InterruptedIOException(e.getMessage()); - iio.initCause(e); - throw iio; + Thread.currentThread().interrupt(); + throw Input.toInterruptedIOException(e); } finally { try { isWaiting.set(false); diff --git a/src/main/java/org/apache/commons/io/input/ReaderInputStream.java b/src/main/java/org/apache/commons/io/input/ReaderInputStream.java index 4d22d28f891..7e7379e9216 100644 --- a/src/main/java/org/apache/commons/io/input/ReaderInputStream.java +++ b/src/main/java/org/apache/commons/io/input/ReaderInputStream.java @@ -209,6 +209,7 @@ private static CharsetEncoder newEncoder(final Charset charset) { * CharBuffer used as input for the decoder. It should be reasonably large as we read data from the underlying Reader into this buffer. */ private final CharBuffer encoderIn; + /** * ByteBuffer used as output for the decoder. This buffer can be small as it is only used to transfer data from the decoder to the buffer provided by the * caller. @@ -225,11 +226,11 @@ private ReaderInputStream(final Builder builder) throws IOException { } /** - * Constructs a new {@link ReaderInputStream} that uses the virtual machine's {@link Charset#defaultCharset() default charset} with a default input buffer - * size of {@value IOUtils#DEFAULT_BUFFER_SIZE} characters. + * Constructs a new {@link ReaderInputStream} that uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} with a default input + * buffer size of {@value IOUtils#DEFAULT_BUFFER_SIZE} characters. * * @param reader the target {@link Reader} - * @deprecated Use {@link ReaderInputStream#builder()} instead + * @deprecated Use {@link ReaderInputStream#builder()} instead. */ @Deprecated public ReaderInputStream(final Reader reader) { @@ -244,7 +245,7 @@ public ReaderInputStream(final Reader reader) { * * * @param reader the target {@link Reader} - * @param charset the charset encoding + * @param charset the charset encoding. * @deprecated Use {@link ReaderInputStream#builder()} instead, will be protected for subclasses. */ @Deprecated @@ -262,17 +263,11 @@ public ReaderInputStream(final Reader reader, final Charset charset) { * @param reader the target {@link Reader}. * @param charset the charset encoding. * @param bufferSize the size of the input buffer in number of characters. - * @deprecated Use {@link ReaderInputStream#builder()} instead + * @deprecated Use {@link ReaderInputStream#builder()} instead. */ @Deprecated public ReaderInputStream(final Reader reader, final Charset charset, final int bufferSize) { - // @formatter:off - this(reader, - Charsets.toCharset(charset).newEncoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE), - bufferSize); - // @formatter:on + this(reader, newEncoder(charset), bufferSize); } /** @@ -284,9 +279,9 @@ public ReaderInputStream(final Reader reader, final Charset charset, final int b * * * @param reader the target {@link Reader} - * @param charsetEncoder the charset encoder + * @param charsetEncoder the charset encoder. * @since 2.1 - * @deprecated Use {@link ReaderInputStream#builder()} instead + * @deprecated Use {@link ReaderInputStream#builder()} instead. */ @Deprecated public ReaderInputStream(final Reader reader, final CharsetEncoder charsetEncoder) { @@ -303,9 +298,9 @@ public ReaderInputStream(final Reader reader, final CharsetEncoder charsetEncode * * @param reader the target {@link Reader} * @param charsetEncoder the charset encoder, null defaults to the default Charset encoder. - * @param bufferSize the size of the input buffer in number of characters + * @param bufferSize the size of the input buffer in number of characters. * @since 2.1 - * @deprecated Use {@link ReaderInputStream#builder()} instead + * @deprecated Use {@link ReaderInputStream#builder()} instead. */ @Deprecated public ReaderInputStream(final Reader reader, final CharsetEncoder charsetEncoder, final int bufferSize) { @@ -325,8 +320,8 @@ public ReaderInputStream(final Reader reader, final CharsetEncoder charsetEncode * * * @param reader the target {@link Reader} - * @param charsetName the name of the charset encoding - * @deprecated Use {@link ReaderInputStream#builder()} instead + * @param charsetName the name of the charset encoding. + * @deprecated Use {@link ReaderInputStream#builder()} instead. */ @Deprecated public ReaderInputStream(final Reader reader, final String charsetName) { @@ -342,8 +337,8 @@ public ReaderInputStream(final Reader reader, final String charsetName) { * * @param reader the target {@link Reader} * @param charsetName the name of the charset encoding, null maps to the default Charset. - * @param bufferSize the size of the input buffer in number of characters - * @deprecated Use {@link ReaderInputStream#builder()} instead + * @param bufferSize the size of the input buffer in number of characters. + * @deprecated Use {@link ReaderInputStream#builder()} instead. */ @Deprecated public ReaderInputStream(final Reader reader, final String charsetName, final int bufferSize) { @@ -372,7 +367,7 @@ public void close() throws IOException { /** * Fills the internal char buffer from the reader. * - * @throws IOException If an I/O error occurs + * @throws IOException If an I/O error occurs. */ private void fillBuffer() throws IOException { if (endOfInput) { @@ -415,7 +410,7 @@ CharsetEncoder getCharsetEncoder() { /** * Reads a single byte. * - * @return either the byte read or {@code -1} if the end of the stream has been reached + * @return either the byte read or {@code -1} if the end of the stream has been reached. * @throws IOException if an I/O error occurs. */ @Override @@ -436,7 +431,7 @@ public int read() throws IOException { * Reads the specified number of bytes into an array. * * @param b the byte array to read into, must not be {@code null} - * @return the number of bytes read or {@code -1} if the end of the stream has been reached + * @return the number of bytes read or {@code -1} if the end of the stream has been reached. * @throws NullPointerException if the byte array is {@code null}. * @throws IOException if an I/O error occurs. */ @@ -448,10 +443,10 @@ public int read(final byte[] b) throws IOException { /** * Reads the specified number of bytes into an array. * - * @param array the byte array to read into - * @param off the offset to start reading bytes into - * @param len the number of bytes to read - * @return the number of bytes read or {@code -1} if the end of the stream has been reached + * @param array the byte array to read into. + * @param off the offset to start reading bytes into. + * @param len the number of bytes to read. + * @return the number of bytes read or {@code -1} if the end of the stream has been reached. * @throws NullPointerException if the byte array is {@code null}. * @throws IndexOutOfBoundsException if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code array.length}. * @throws IOException if an I/O error occurs. 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 949ff8cbd8e..43ad4da1040 100644 --- a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java +++ b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java @@ -25,7 +25,6 @@ import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; @@ -93,6 +92,7 @@ public static class Builder extends AbstractStreamBuilder+ * Package private for testing. + *
+ * + * @return The maximum bytes per second. + */ double getMaxBytesPerSecond() { return maxBytesPerSecond; } - private long getSleepMillis() { + /** + * Gets the number of milliseconds to sleep to match to the maximum bytes per second. + *+ * Package private for testing. + *
+ * + * @return the number of milliseconds to sleep to match to the maximum bytes per second. + */ + long getSleepMillis() { return toSleepMillis(getByteCount(), System.currentTimeMillis() - startTime, maxBytesPerSecond); } /** * Gets the total duration spent in sleep. + *+ * Package private for testing + *
* * @return Duration spent in sleep. */ - // package private for testing Duration getTotalSleepDuration() { return totalSleepDuration; } @@ -271,7 +288,8 @@ private void throttle() throws InterruptedIOException { try { TimeUnit.MILLISECONDS.sleep(sleepMillis); } catch (final InterruptedException e) { - throw new InterruptedIOException("Thread aborted"); + Thread.currentThread().interrupt(); + throw Input.toInterruptedIOException(e); } } } diff --git a/src/main/java/org/apache/commons/io/input/UncheckedFilterInputStream.java b/src/main/java/org/apache/commons/io/input/UncheckedFilterInputStream.java index ac6e003ab1f..eb6cf216251 100644 --- a/src/main/java/org/apache/commons/io/input/UncheckedFilterInputStream.java +++ b/src/main/java/org/apache/commons/io/input/UncheckedFilterInputStream.java @@ -110,7 +110,7 @@ public static Builder builder() { * Constructs a {@link UncheckedFilterInputStream}. * * @param builder A builder providing the underlying input stream. - * @throws IOException + * @throws IOException if an I/O error occurs. */ @SuppressWarnings("resource") // caller closes private UncheckedFilterInputStream(final Builder builder) throws IOException { diff --git a/src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java b/src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java index 3d0400fca71..88f31b7854f 100644 --- a/src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java +++ b/src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java @@ -28,37 +28,16 @@ * * @since 2.5 */ -public class UnixLineEndingInputStream extends InputStream { - - private boolean atEos; - - private boolean atSlashCr; - - private boolean atSlashLf; - - private final InputStream in; - - private final boolean lineFeedAtEndOfFile; +public class UnixLineEndingInputStream extends AbstractLineEndingInputStream { /** * Constructs an input stream that filters another stream * - * @param inputStream The input stream to wrap - * @param ensureLineFeedAtEndOfFile true to ensure that the file ends with LF - */ - public UnixLineEndingInputStream(final InputStream inputStream, final boolean ensureLineFeedAtEndOfFile) { - this.in = inputStream; - this.lineFeedAtEndOfFile = ensureLineFeedAtEndOfFile; - } - - /** - * Closes the stream. Also closes the underlying stream. - * @throws IOException If an I/O error occurs. + * @param inputStream The input stream to wrap. + * @param lineFeedAtEos true to ensure that the file ends with LF. */ - @Override - public void close() throws IOException { - super.close(); - in.close(); + public UnixLineEndingInputStream(final InputStream inputStream, final boolean lineFeedAtEos) { + super(inputStream, lineFeedAtEos); } /** @@ -68,7 +47,7 @@ public void close() throws IOException { * @return The next char to output to the stream. */ private int handleEos(final boolean previousWasSlashCr) { - if (previousWasSlashCr || !lineFeedAtEndOfFile) { + if (previousWasSlashCr || !lineFeedAtEos) { return EOF; } if (!atSlashLf) { @@ -78,14 +57,6 @@ private int handleEos(final boolean previousWasSlashCr) { return EOF; } - /** - * {@inheritDoc} - */ - @Override - public synchronized void mark(final int readLimit) { - throw UnsupportedOperationExceptions.mark(); - } - /** * {@inheritDoc} */ @@ -95,7 +66,7 @@ public synchronized int read() throws IOException { if (atEos) { return handleEos(previousWasSlashR); } - final int target = readWithUpdate(); + final int target = readUpdate(); if (atEos) { return handleEos(previousWasSlashR); } @@ -112,10 +83,11 @@ public synchronized int read() throws IOException { /** * Reads the next item from the target, updating internal flags in the process - * @return the next int read from the target stream + * + * @return the next int read from the target stream. * @throws IOException If an I/O error occurs. */ - private int readWithUpdate() throws IOException { + private int readUpdate() throws IOException { final int target = this.in.read(); atEos = target == EOF; if (atEos) { diff --git a/src/main/java/org/apache/commons/io/input/UnsupportedOperationExceptions.java b/src/main/java/org/apache/commons/io/input/UnsupportedOperationExceptions.java index 63874faabb7..fea13e7c4cc 100644 --- a/src/main/java/org/apache/commons/io/input/UnsupportedOperationExceptions.java +++ b/src/main/java/org/apache/commons/io/input/UnsupportedOperationExceptions.java @@ -31,7 +31,7 @@ final class UnsupportedOperationExceptions { /** * Constructs a new instance of UnsupportedOperationException for a {@code mark} method. * - * @return a new instance of UnsupportedOperationException + * @return a new instance of UnsupportedOperationException. */ static UnsupportedOperationException mark() { // Use the same message as in java.io.InputStream.reset() in OpenJDK 8.0.275-1. @@ -41,8 +41,8 @@ static UnsupportedOperationException mark() { /** * Constructs a new instance of UnsupportedOperationException for the given unsupported a {@code method} name. * - * @param method A method name - * @return a new instance of UnsupportedOperationException + * @param method A method name. + * @return a new instance of UnsupportedOperationException. */ static UnsupportedOperationException method(final String method) { return new UnsupportedOperationException(method + " not supported"); @@ -51,7 +51,7 @@ static UnsupportedOperationException method(final String method) { /** * Constructs a new instance of UnsupportedOperationException for a {@code reset} method. * - * @return a new instance of UnsupportedOperationException + * @return a new instance of UnsupportedOperationException. */ static UnsupportedOperationException reset() { // Use the same message as in java.io.InputStream.reset() in OpenJDK 8.0.275-1. diff --git a/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java b/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java index bde55873f24..b67d9f5254a 100644 --- a/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java +++ b/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java @@ -77,7 +77,7 @@ public class UnsynchronizedBufferedReader extends UnsynchronizedReader { */ private char[] buf; - private int pos; + private int bufPos; private int end; @@ -85,6 +85,9 @@ public class UnsynchronizedBufferedReader extends UnsynchronizedReader { private int markLimit = -1; + private long pos; + private long posMark; + /** * Constructs a new BufferedReader on the Reader {@code in}. The buffer gets the default size (8 KB). * @@ -113,8 +116,8 @@ public UnsynchronizedBufferedReader(final Reader in, final int size) { * Peeks at the next input character, refilling the buffer if necessary. If this character is a newline character ("\n"), it is discarded. */ final void chompNewline() throws IOException { - if ((pos != end || fillBuf() != EOF) && buf[pos] == LF) { - pos++; + if ((bufPos != end || fillBuf() != EOF) && buf[bufPos] == LF) { + bufPos++; } } @@ -134,24 +137,22 @@ public void close() throws IOException { } /** - * Populates the buffer with data. It is an error to call this method when the buffer still contains data; ie. if {@code pos < end}. + * Fills the buffer with characters. It is an error to call this method when the buffer still contains data, that is, if {@code pos < end}. * * @return the number of bytes read into the buffer, or -1 if the end of the source stream has been reached. */ private int fillBuf() throws IOException { // assert(pos == end); - - if (mark == EOF || pos - mark >= markLimit) { + if (mark == EOF || bufPos - mark >= markLimit) { /* mark isn't set or has exceeded its limit. use the whole buffer */ final int result = in.read(buf, 0, buf.length); if (result > 0) { mark = -1; - pos = 0; + bufPos = 0; end = result; } return result; } - if (mark == 0 && markLimit > buf.length) { /* the only way to make room when mark=0 is by growing the buffer */ int newLength = buf.length * 2; @@ -164,19 +165,48 @@ private int fillBuf() throws IOException { } else if (mark > 0) { /* make room by shifting the buffered data to left mark positions */ System.arraycopy(buf, mark, buf, 0, buf.length - mark); - pos -= mark; + bufPos -= mark; end -= mark; mark = 0; } - /* Set the new position and mark position */ - final int count = in.read(buf, pos, buf.length - pos); + final int count = in.read(buf, bufPos, buf.length - bufPos); if (count != EOF) { end += count; } return count; } + /** + * Gets the character position in the reader. + *+ * Returns {@link Long#MAX_VALUE} instead of overflowing. + *
+ *+ * Since this is a Reader, this is the character position, not the byte position (use an InputStream to count bytes). + *
+ * + * @return the character position in the reader. + * @since 2.23.0 + */ + public long getPosition() { + return pos; + } + + /** + * Increments the position by a given value, overflow sets the value to {@link Long#MAX_VALUE}; + * + * @param v a value. + * @return the new position. + * @since 2.23.0 + */ + protected long incPos(final long v) { + // Like Math.addExact(long, long) but clamp to Long.MAX_VALUE. + final long r = pos + v; + // Overflow iff both arguments have the opposite sign of the result. + return pos = ((pos ^ r) & (v ^ r)) < 0 ? Long.MAX_VALUE : r; + } + /** * Sets a mark position in this reader. The parameter {@code markLimit} indicates how many characters can be read before the mark is invalidated. Calling * {@link #reset()} will reposition the reader back to the marked position if {@code markLimit} has not been surpassed. @@ -194,7 +224,8 @@ public void mark(final int markLimit) throws IOException { } checkOpen(); this.markLimit = markLimit; - mark = pos; + mark = bufPos; + posMark = pos; } /** @@ -212,8 +243,8 @@ public boolean markSupported() { /** * Returns the next character in the current reader without consuming it. So the next call to {@link #read()} will still return this value. * - * @return the next character - * @throws IOException If an I/O error occurs + * @return the next character. + * @throws IOException If an I/O error occurs. */ public int peek() throws IOException { mark(1); @@ -227,8 +258,8 @@ public int peek() throws IOException { * still return the next value. * * @param buf the buffer to fill for the look ahead. - * @return the buffer itself - * @throws IOException If an I/O error occurs + * @return the buffer itself. + * @throws IOException If an I/O error occurs. */ public int peek(final char[] buf) throws IOException { final int n = buf.length; @@ -250,8 +281,9 @@ public int peek(final char[] buf) throws IOException { public int read() throws IOException { checkOpen(); /* Are there buffered characters available? */ - if (pos < end || fillBuf() != EOF) { - return buf[pos++]; + if (bufPos < end || fillBuf() != EOF) { + incPos(1); + return buf[bufPos++]; } return EOF; } @@ -281,22 +313,19 @@ public int read(final char[] buffer, int offset, final int length) throws IOExce if (length == 0) { return 0; } - int outstanding = length; while (outstanding > 0) { - /* * If there are bytes in the buffer, grab those first. */ - final int available = end - pos; + final int available = end - bufPos; if (available > 0) { final int count = available >= outstanding ? outstanding : available; - System.arraycopy(buf, pos, buffer, offset, count); - pos += count; + System.arraycopy(buf, bufPos, buffer, offset, count); + bufPos += count; offset += count; outstanding -= count; } - /* * Before attempting to read from the underlying stream, make sure we really, really want to. We won't bother if we're done, or if we've already got * some bytes and reading from the underlying stream would block. @@ -304,35 +333,31 @@ public int read(final char[] buffer, int offset, final int length) throws IOExce if (outstanding == 0 || outstanding < length && !in.ready()) { break; } - // assert(pos == end); - /* * If we're unmarked and the requested size is greater than our buffer, read the bytes directly into the caller's buffer. We don't read into smaller * buffers because that could result in a many reads. */ - if ((mark == -1 || pos - mark >= markLimit) && outstanding >= buf.length) { + if ((mark == -1 || bufPos - mark >= markLimit) && outstanding >= buf.length) { final int count = in.read(buffer, offset, outstanding); if (count > 0) { outstanding -= count; mark = -1; } - break; // assume the source stream gave us all that it could } - if (fillBuf() == EOF) { break; // source is exhausted } } - final int count = length - outstanding; + incPos(count); return count > 0 || count == length ? count : EOF; } /** * Returns the next line of text available from this reader. A line is represented by zero or more characters followed by {@code LF}, {@code CR}, - * {@code "\r\n"} or the end of the reader. The string does not include the newline sequence. + * {@code "\r\n"}, or the end of the reader. The string does not include the newline sequence. * * @return the contents of the line or {@code null} if no characters were read before the end of the reader has been reached. * @throws IOException if this reader is closed or some other I/O error occurs. @@ -340,37 +365,37 @@ public int read(final char[] buffer, int offset, final int length) throws IOExce public String readLine() throws IOException { checkOpen(); /* has the underlying stream been exhausted? */ - if (pos == end && fillBuf() == EOF) { + if (bufPos == end && fillBuf() == EOF) { return null; } - for (int charPos = pos; charPos < end; charPos++) { + final int startPos = bufPos; + for (int charPos = bufPos; charPos < end; charPos++) { final char ch = buf[charPos]; if (ch > CR) { continue; } if (ch == LF) { - final String res = new String(buf, pos, charPos - pos); - pos = charPos + 1; + final String res = new String(buf, bufPos, charPos - bufPos); + bufPos = charPos + 1; + incPos(bufPos - startPos); return res; } if (ch == CR) { - final String res = new String(buf, pos, charPos - pos); - pos = charPos + 1; - if ((pos < end || fillBuf() != EOF) && buf[pos] == LF) { - pos++; + final String res = new String(buf, bufPos, charPos - bufPos); + bufPos = charPos + 1; + if ((bufPos < end || fillBuf() != EOF) && buf[bufPos] == LF) { + bufPos++; } + incPos(bufPos - startPos); return res; } } - char eol = NUL; + // Typical Line Length final StringBuilder result = new StringBuilder(80); - /* Typical Line Length */ - - result.append(buf, pos, end - pos); + result.append(buf, bufPos, end - bufPos); while (true) { - pos = end; - + bufPos = end; /* Are there buffered characters available? */ if (eol == LF) { return result.toString(); @@ -380,19 +405,19 @@ public String readLine() throws IOException { // characters or null. return result.length() > 0 || eol != NUL ? result.toString() : null; } - for (int charPos = pos; charPos < end; charPos++) { + for (int charPos = bufPos; charPos < end; charPos++) { final char c = buf[charPos]; if (eol != NUL) { if (eol == CR && c == LF) { - if (charPos > pos) { - result.append(buf, pos, charPos - pos - 1); + if (charPos > bufPos) { + result.append(buf, bufPos, charPos - bufPos - 1); } - pos = charPos + 1; + bufPos = charPos + 1; } else { - if (charPos > pos) { - result.append(buf, pos, charPos - pos - 1); + if (charPos > bufPos) { + result.append(buf, bufPos, charPos - bufPos - 1); } - pos = charPos; + bufPos = charPos; } return result.toString(); } @@ -401,9 +426,9 @@ public String readLine() throws IOException { } } if (eol == NUL) { - result.append(buf, pos, end - pos); + result.append(buf, bufPos, end - bufPos); } else { - result.append(buf, pos, end - pos - 1); + result.append(buf, bufPos, end - bufPos - 1); } } } @@ -420,7 +445,7 @@ public String readLine() throws IOException { @Override public boolean ready() throws IOException { checkOpen(); - return end - pos > 0 || in.ready(); + return end - bufPos > 0 || in.ready(); } /** @@ -436,7 +461,8 @@ public void reset() throws IOException { if (mark == -1) { throw new IOException("mark == -1"); } - pos = mark; + bufPos = mark; + pos = posMark; } /** @@ -460,26 +486,39 @@ public long skip(final long amount) throws IOException { if (amount < 1) { return 0; } - if (end - pos >= amount) { - pos += Math.toIntExact(amount); - return amount; + if (end - bufPos >= amount) { + bufPos += Math.toIntExact(amount); + return incPos(amount); } - - long read = end - pos; - pos = end; + long read = end - bufPos; + bufPos = end; while (read < amount) { if (fillBuf() == EOF) { - return read; + return incPos(read); } - if (end - pos >= amount - read) { - pos += Math.toIntExact(amount - read); - return amount; + if (end - bufPos >= amount - read) { + bufPos += Math.toIntExact(amount - read); + return incPos(amount); } // Couldn't get all the characters, skip what we read - read += end - pos; - pos = end; + read += end - bufPos; + bufPos = end; } - return amount; + return incPos(amount); + } + + + /** + * Unwraps this instance by returning the underlying {@link Reader}. + *+ * Use with caution. + *
+ * + * @return the underlying {@link Reader}. + * @since 2.23.0 + */ + public Reader unwrap() { + return in; } } 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 a56dec7206c..96c47e7b9af 100644 --- a/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java +++ b/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java @@ -92,10 +92,6 @@ public Builder() { // empty } - private byte[] checkOriginByteArray() throws IOException { - return checkOrigin().getByteArray(); - } - /** * Builds a new {@link UnsynchronizedByteArrayInputStream}. *@@ -207,13 +203,13 @@ private static int requireNonNegative(final int value, final String name) { private int markedOffset; private UnsynchronizedByteArrayInputStream(final Builder builder) throws IOException { - this(builder.checkOriginByteArray(), builder.offset, builder.length); + this(builder.getByteArray(), builder.offset, builder.length); } /** * Constructs a new byte array input stream. * - * @param data the buffer + * @param data the buffer. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated @@ -224,9 +220,9 @@ public UnsynchronizedByteArrayInputStream(final byte[] data) { /** * Constructs a new byte array input stream. * - * @param data the buffer - * @param offset the offset into the buffer - * @throws IllegalArgumentException if the offset is less than zero + * @param data the buffer. + * @param offset the offset into the buffer. + * @throws IllegalArgumentException if the offset is less than zero. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated @@ -237,10 +233,10 @@ public UnsynchronizedByteArrayInputStream(final byte[] data, final int offset) { /** * Constructs a new byte array input stream. * - * @param data the buffer - * @param offset the offset into the buffer - * @param length the length of the buffer - * @throws IllegalArgumentException if the offset or length less than zero + * @param data the buffer. + * @param offset the offset into the buffer. + * @param length the length of the buffer. + * @throws IllegalArgumentException if the offset or length less than zero. * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. */ @Deprecated diff --git a/src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java b/src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java index b09deec0d3e..24285adb6d3 100644 --- a/src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java +++ b/src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java @@ -28,20 +28,10 @@ * * @since 2.5 */ -public class WindowsLineEndingInputStream extends InputStream { - - private boolean atEos; - - private boolean atSlashCr; - - private boolean atSlashLf; - - private final InputStream in; +public class WindowsLineEndingInputStream extends AbstractLineEndingInputStream { private boolean injectSlashLf; - private final boolean lineFeedAtEos; - /** * Constructs an input stream that filters another stream. * @@ -49,19 +39,7 @@ public class WindowsLineEndingInputStream extends InputStream { * @param lineFeedAtEos true to ensure that the stream ends with CRLF. */ public WindowsLineEndingInputStream(final InputStream in, final boolean lineFeedAtEos) { - this.in = in; - this.lineFeedAtEos = lineFeedAtEos; - } - - /** - * Closes the stream. Also closes the underlying stream. - * - * @throws IOException If an I/O error occurs. - */ - @Override - public void close() throws IOException { - super.close(); - in.close(); + super(in, lineFeedAtEos); } /** @@ -85,14 +63,6 @@ private int handleEos() { return EOF; } - /** - * {@inheritDoc} - */ - @Override - public synchronized void mark(final int readLimit) { - throw UnsupportedOperationExceptions.mark(); - } - /** * {@inheritDoc} */ 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 7f5102e8218..3b667ef1655 100644 --- a/src/main/java/org/apache/commons/io/input/XmlStreamReader.java +++ b/src/main/java/org/apache/commons/io/input/XmlStreamReader.java @@ -42,7 +42,6 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.io.build.AbstractStreamBuilder; import org.apache.commons.io.function.IOConsumer; -import org.apache.commons.io.output.XmlStreamWriter; /** * Character stream that handles all the necessary Voodoo to figure out the charset encoding of the XML document within the stream. @@ -76,7 +75,7 @@ public class XmlStreamReader extends Reader { // @formatter:off /** - * Builds a new {@link XmlStreamWriter}. + * Builds a new {@link XmlStreamReader}. * * Constructs a Reader using an InputStream and the associated content-type header. This constructor is lenient regarding the encoding detection. *
@@ -131,7 +130,7 @@ public Builder() { } /** - * Builds a new {@link XmlStreamWriter}. + * Builds a new {@link XmlStreamReader}. *
* You must set an aspect that supports {@link #getInputStream()}, otherwise, this method throws an exception. *
@@ -278,8 +277,8 @@ public static Builder builder() { /** * Gets the charset parameter value, {@code null} if not present, {@code null} if httpContentType is {@code null}. * - * @param httpContentType the HTTP content type - * @return The content type encoding (upcased) + * @param httpContentType the HTTP content type. + * @return The content type encoding (upcased). */ static String getContentTypeEncoding(final String httpContentType) { String encoding = null; @@ -298,8 +297,8 @@ static String getContentTypeEncoding(final String httpContentType) { /** * Gets the MIME type or {@code null} if httpContentType is {@code null}. * - * @param httpContentType the HTTP content type - * @return The mime content type + * @param httpContentType the HTTP content type. + * @return The mime content type. */ static String getContentTypeMime(final String httpContentType) { String mime = null; @@ -315,8 +314,8 @@ static String getContentTypeMime(final String httpContentType) { * Gets the encoding declared in the , {@code null} if none. * * @param inputStream InputStream to create the reader from. - * @param guessedEnc guessed encoding - * @return the encoding declared in the + * @param guessedEnc guessed encoding. + * @return the encoding declared in the . * @throws IOException thrown if there is a problem reading the stream. */ private static String getXmlProlog(final InputStream inputStream, final String guessedEnc) throws IOException { @@ -361,8 +360,8 @@ private static String getXmlProlog(final InputStream inputStream, final String g /** * Tests if the MIME type belongs to the APPLICATION XML family. * - * @param mime The mime type - * @return true if the mime type belongs to the APPLICATION XML family, otherwise false + * @param mime The mime type. + * @return true if the mime type belongs to the APPLICATION XML family, otherwise false. */ static boolean isAppXml(final String mime) { return mime != null && (mime.equals("application/xml") || mime.equals("application/xml-dtd") || mime.equals("application/xml-external-parsed-entity") @@ -372,8 +371,8 @@ static boolean isAppXml(final String mime) { /** * Tests if the MIME type belongs to the TEXT XML family. * - * @param mime The mime type - * @return true if the mime type belongs to the TEXT XML family, otherwise false + * @param mime The mime type. + * @return true if the mime type belongs to the TEXT XML family, otherwise false. */ static boolean isTextXml(final String mime) { return mime != null && (mime.equals("text/xml") || mime.equals("text/xml-external-parsed-entity") || mime.startsWith("text/") && mime.endsWith("+xml")); @@ -485,7 +484,7 @@ public XmlStreamReader(final InputStream inputStream, final boolean lenient) thr * * @param inputStream InputStream to create a Reader from. * @param lenient indicates if the charset encoding detection should be relaxed. - * @param defaultEncoding The default encoding + * @param defaultEncoding The default encoding. * @throws NullPointerException if the input stream is {@code null}. * @throws IOException thrown if there is a problem reading the stream. * @throws XmlStreamReaderException thrown if the charset encoding could not be determined according to the specification. @@ -498,7 +497,7 @@ public XmlStreamReader(final InputStream inputStream, final boolean lenient, fin final BOMInputStream bom = new BOMInputStream(new BufferedInputStream(Objects.requireNonNull(inputStream, "inputStream"), IOUtils.DEFAULT_BUFFER_SIZE), false, BOMS); final BOMInputStream pis = new BOMInputStream(bom, true, XML_GUESS_BYTES); - this.encoding = processHttpStream(bom, pis, lenient); + this.encoding = toEncoding(bom, pis, lenient); this.reader = new InputStreamReader(pis, encoding); } @@ -589,7 +588,7 @@ public XmlStreamReader(final InputStream inputStream, final String httpContentTy * @param inputStream InputStream to create the reader from. * @param httpContentType content-type header to use for the resolution of the charset encoding. * @param lenient indicates if the charset encoding detection should be relaxed. - * @param defaultEncoding The default encoding + * @param defaultEncoding The default encoding. * @throws NullPointerException if the input stream is {@code null}. * @throws IOException thrown if there is a problem reading the file. * @throws XmlStreamReaderException thrown if the charset encoding could not be determined according to the specification. @@ -603,7 +602,7 @@ public XmlStreamReader(final InputStream inputStream, final String httpContentTy final BOMInputStream bom = new BOMInputStream(new BufferedInputStream(Objects.requireNonNull(inputStream, "inputStream"), IOUtils.DEFAULT_BUFFER_SIZE), false, BOMS); final BOMInputStream pis = new BOMInputStream(bom, true, XML_GUESS_BYTES); - this.encoding = processHttpStream(bom, pis, lenient, httpContentType); + this.encoding = toEncoding(bom, pis, lenient, httpContentType); this.reader = new InputStreamReader(pis, encoding); } @@ -662,7 +661,7 @@ public XmlStreamReader(final URL url) throws IOException { * * * @param urlConnection URLConnection to create a Reader from. - * @param defaultEncoding The default encoding + * @param defaultEncoding The default encoding. * @throws NullPointerException if the input is {@code null}. * @throws IOException thrown if there is a problem reading the stream of the URLConnection. */ @@ -687,51 +686,168 @@ public XmlStreamReader(final URLConnection urlConnection, final String defaultEn .get(); // @formatter:on if (urlConnection instanceof HttpURLConnection || contentType != null) { - this.encoding = processHttpStream(bomInput, piInput, lenient, contentType); + this.encoding = toEncoding(bomInput, piInput, lenient, contentType); } else { - this.encoding = processHttpStream(bomInput, piInput, lenient); + this.encoding = toEncoding(bomInput, piInput, lenient); } this.reader = new InputStreamReader(piInput, encoding); } /** - * Calculates the HTTP encoding. - * @param bomEnc BOM encoding - * @param xmlGuessEnc XML Guess encoding - * @param xmlEnc XML encoding + * Closes the XmlStreamReader stream. + * + * @throws IOException thrown if there was a problem closing the stream. + */ + @Override + public void close() throws IOException { + reader.close(); + } + + /** + * Gets the default encoding to use if none is set in HTTP content-type, XML prolog and the rules based on content-type are not adequate. + *+ * If it is {@code null} the content-type based rules are used. + *
+ * + * @return the default encoding to use. + */ + public String getDefaultEncoding() { + return defaultEncoding; + } + + /** + * Gets the charset encoding of the XmlStreamReader. + * + * @return charset encoding. + */ + public String getEncoding() { + return encoding; + } + + /** + * Reads the underlying reader's {@code read(char[], int, int)} method. + * + * @param buf the buffer to read the characters into. + * @param offset The start offset. + * @param len The number of bytes to read. + * @return the number of characters read or -1 if the end of stream. + * @throws IOException if an I/O error occurs. + */ + @Override + public int read(final char[] buf, final int offset, final int len) throws IOException { + return reader.read(buf, offset, len); + } + + /** + * Process the raw stream. + * + * @param bomInput BOMInputStream to detect byte order marks. + * @param piInput BOMInputStream to guess XML encoding. + * @param lenient indicates if the charset encoding detection should be relaxed. + * @return the encoding to be used. + * @throws IOException thrown if there is a problem reading the stream. + */ + private String toEncoding(final BOMInputStream bomInput, final BOMInputStream piInput, final boolean lenient) throws IOException { + final String bomEnc = bomInput.getBOMCharsetName(); + final String xmlGuessEnc = piInput.getBOMCharsetName(); + final String xmlEnc = getXmlProlog(piInput, xmlGuessEnc); + try { + return toRawEncoding(bomEnc, xmlGuessEnc, xmlEnc); + } catch (final XmlStreamReaderException ex) { + if (lenient) { + return toEncodingLenient(null, ex); + } + throw ex; + } + } + + /** + * Processes an HTTP stream. + * + * @param bomInput BOMInputStream to detect byte order marks. + * @param piInput BOMInputStream to guess XML encoding. * @param lenient indicates if the charset encoding detection should be relaxed. - * @param httpContentType The HTTP content type - * @return the HTTP encoding + * @param httpContentType The HTTP content type. + * @return the encoding to be used. * @throws IOException thrown if there is a problem reading the stream. */ - String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final boolean lenient, final String httpContentType) + private String toEncoding(final BOMInputStream bomInput, final BOMInputStream piInput, final boolean lenient, final String httpContentType) throws IOException { + final String bomEnc = bomInput.getBOMCharsetName(); + final String xmlGuessEnc = piInput.getBOMCharsetName(); + final String xmlEnc = getXmlProlog(piInput, xmlGuessEnc); + try { + return toHttpEncoding(bomEnc, xmlGuessEnc, xmlEnc, lenient, httpContentType); + } catch (final XmlStreamReaderException ex) { + if (lenient) { + return toEncodingLenient(httpContentType, ex); + } + throw ex; + } + } + /** + * Detects the encoding in lenient mode. + * + * @param httpContentType content-type header to use for the resolution of the charset encoding. + * @param ex The thrown exception. + * @return the encoding. + * @throws IOException thrown if there is a problem reading the stream. + */ + private String toEncodingLenient(String httpContentType, XmlStreamReaderException ex) throws IOException { + if (httpContentType != null && httpContentType.startsWith("text/html")) { + httpContentType = httpContentType.substring("text/html".length()); + httpContentType = "text/xml" + httpContentType; + try { + return toHttpEncoding(ex.getBomEncoding(), ex.getXmlGuessEncoding(), ex.getXmlEncoding(), true, httpContentType); + } catch (final XmlStreamReaderException ex2) { + ex = ex2; + } + } + String encoding = ex.getXmlEncoding(); + if (encoding == null) { + encoding = ex.getContentTypeEncoding(); + } + if (encoding == null) { + encoding = defaultEncoding == null ? UTF_8 : defaultEncoding; + } + return encoding; + } + + /** + * Calculates the HTTP encoding. + * + * @param bomEnc BOM encoding. + * @param xmlGuessEnc XML Guess encoding. + * @param xmlEnc XML encoding. + * @param lenient indicates if the charset encoding detection should be relaxed. + * @param httpContentType The HTTP content type. + * @return the HTTP encoding. + * @throws IOException thrown if there is a problem reading the stream. + */ + String toHttpEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final boolean lenient, final String httpContentType) + throws IOException { // Lenient and has XML encoding if (lenient && xmlEnc != null) { return xmlEnc; } - // Determine mime/encoding content types from HTTP Content Type final String cTMime = getContentTypeMime(httpContentType); final String cTEnc = getContentTypeEncoding(httpContentType); final boolean appXml = isAppXml(cTMime); final boolean textXml = isTextXml(cTMime); - // Mime type NOT "application/xml" or "text/xml" if (!appXml && !textXml) { final String msg = MessageFormat.format(HTTP_EX_3, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); } - // No content type encoding if (cTEnc == null) { if (appXml) { - return calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc); + return toRawEncoding(bomEnc, xmlGuessEnc, xmlEnc); } return defaultEncoding == null ? US_ASCII : defaultEncoding; } - // UTF-16BE or UTF-16LE content type encoding if (cTEnc.equals(UTF_16BE) || cTEnc.equals(UTF_16LE)) { if (bomEnc != null) { @@ -740,7 +856,6 @@ String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, fina } return cTEnc; } - // UTF-16 content type encoding if (cTEnc.equals(UTF_16)) { if (bomEnc != null && bomEnc.startsWith(UTF_16)) { @@ -749,7 +864,6 @@ String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, fina final String msg = MessageFormat.format(HTTP_EX_2, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); } - // UTF-32BE or UTF-132E content type encoding if (cTEnc.equals(UTF_32BE) || cTEnc.equals(UTF_32LE)) { if (bomEnc != null) { @@ -758,7 +872,6 @@ String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, fina } return cTEnc; } - // UTF-32 content type encoding if (cTEnc.equals(UTF_32)) { if (bomEnc != null && bomEnc.startsWith(UTF_32)) { @@ -767,20 +880,19 @@ String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, fina final String msg = MessageFormat.format(HTTP_EX_2, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); } - return cTEnc; } /** * Calculate the raw encoding. * - * @param bomEnc BOM encoding - * @param xmlGuessEnc XML Guess encoding - * @param xmlEnc XML encoding - * @return the raw encoding + * @param bomEnc BOM encoding. + * @param xmlGuessEnc XML Guess encoding. + * @param xmlEnc XML encoding. + * @return the raw encoding. * @throws IOException thrown if there is a problem reading the stream. */ - String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc) throws IOException { + String toRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc) throws IOException { // BOM is Null if (bomEnc == null) { @@ -795,11 +907,7 @@ String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final // BOM is UTF-8 if (bomEnc.equals(UTF_8)) { - if (xmlGuessEnc != null && !xmlGuessEnc.equals(UTF_8)) { - final String msg = MessageFormat.format(RAW_EX_1, bomEnc, xmlGuessEnc, xmlEnc); - throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc); - } - if (xmlEnc != null && !xmlEnc.equals(UTF_8)) { + if (xmlGuessEnc != null && !xmlGuessEnc.equals(UTF_8) || xmlEnc != null && !xmlEnc.equals(UTF_8)) { final String msg = MessageFormat.format(RAW_EX_1, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc); } @@ -837,125 +945,4 @@ String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc); } - /** - * Closes the XmlStreamReader stream. - * - * @throws IOException thrown if there was a problem closing the stream. - */ - @Override - public void close() throws IOException { - reader.close(); - } - - /** - * Does lenient detection. - * - * @param httpContentType content-type header to use for the resolution of the charset encoding. - * @param ex The thrown exception - * @return the encoding - * @throws IOException thrown if there is a problem reading the stream. - */ - private String doLenientDetection(String httpContentType, XmlStreamReaderException ex) throws IOException { - if (httpContentType != null && httpContentType.startsWith("text/html")) { - httpContentType = httpContentType.substring("text/html".length()); - httpContentType = "text/xml" + httpContentType; - try { - return calculateHttpEncoding(ex.getBomEncoding(), ex.getXmlGuessEncoding(), ex.getXmlEncoding(), true, httpContentType); - } catch (final XmlStreamReaderException ex2) { - ex = ex2; - } - } - String encoding = ex.getXmlEncoding(); - if (encoding == null) { - encoding = ex.getContentTypeEncoding(); - } - if (encoding == null) { - encoding = defaultEncoding == null ? UTF_8 : defaultEncoding; - } - return encoding; - } - - /** - * Gets the default encoding to use if none is set in HTTP content-type, XML prolog and the rules based on content-type are not adequate. - *- * If it is {@code null} the content-type based rules are used. - *
- * - * @return the default encoding to use. - */ - public String getDefaultEncoding() { - return defaultEncoding; - } - - /** - * Gets the charset encoding of the XmlStreamReader. - * - * @return charset encoding. - */ - public String getEncoding() { - return encoding; - } - - /** - * Process the raw stream. - * - * @param bomInput BOMInputStream to detect byte order marks - * @param piInput BOMInputStream to guess XML encoding - * @param lenient indicates if the charset encoding detection should be relaxed. - * @return the encoding to be used - * @throws IOException thrown if there is a problem reading the stream. - */ - private String processHttpStream(final BOMInputStream bomInput, final BOMInputStream piInput, final boolean lenient) throws IOException { - final String bomEnc = bomInput.getBOMCharsetName(); - final String xmlGuessEnc = piInput.getBOMCharsetName(); - final String xmlEnc = getXmlProlog(piInput, xmlGuessEnc); - try { - return calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc); - } catch (final XmlStreamReaderException ex) { - if (lenient) { - return doLenientDetection(null, ex); - } - throw ex; - } - } - - /** - * Processes an HTTP stream. - * - * @param bomInput BOMInputStream to detect byte order marks - * @param piInput BOMInputStream to guess XML encoding - * @param lenient indicates if the charset encoding detection should be relaxed. - * @param httpContentType The HTTP content type - * @return the encoding to be used - * @throws IOException thrown if there is a problem reading the stream. - */ - private String processHttpStream(final BOMInputStream bomInput, final BOMInputStream piInput, final boolean lenient, final String httpContentType) - throws IOException { - final String bomEnc = bomInput.getBOMCharsetName(); - final String xmlGuessEnc = piInput.getBOMCharsetName(); - final String xmlEnc = getXmlProlog(piInput, xmlGuessEnc); - try { - return calculateHttpEncoding(bomEnc, xmlGuessEnc, xmlEnc, lenient, httpContentType); - } catch (final XmlStreamReaderException ex) { - if (lenient) { - return doLenientDetection(httpContentType, ex); - } - throw ex; - } - } - - /** - * Reads the underlying reader's {@code read(char[], int, int)} method. - * - * @param buf the buffer to read the characters into - * @param offset The start offset - * @param len The number of bytes to read - * @return the number of characters read or -1 if the end of stream - * @throws IOException if an I/O error occurs. - */ - @Override - public int read(final char[] buf, final int offset, final int len) throws IOException { - return reader.read(buf, offset, len); - } - } diff --git a/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.java b/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.java index b92163478d0..cea865ae066 100644 --- a/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.java +++ b/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.java @@ -104,8 +104,8 @@ protected void fillBuffer() throws IOException { /** * Fills the buffer from the input stream until the given number of bytes have been added to the buffer. * - * @param count number of byte to fill into the buffer - * @return true if the buffer has bytes + * @param count number of byte to fill into the buffer. + * @return true if the buffer has bytes. * @throws IOException in case of an error while reading from the input stream. */ protected boolean haveBytes(final int count) throws IOException { diff --git a/src/main/java/org/apache/commons/io/input/buffer/CircularByteBuffer.java b/src/main/java/org/apache/commons/io/input/buffer/CircularByteBuffer.java index 43c8e71bd4a..64780b7c709 100644 --- a/src/main/java/org/apache/commons/io/input/buffer/CircularByteBuffer.java +++ b/src/main/java/org/apache/commons/io/input/buffer/CircularByteBuffer.java @@ -46,7 +46,7 @@ public CircularByteBuffer() { /** * Constructs a new instance with the given buffer size. * - * @param size the size of buffer to create + * @param size the size of buffer to create. */ public CircularByteBuffer(final int size) { buffer = IOUtils.byteArray(size); @@ -79,9 +79,9 @@ public void add(final byte value) { * for the bytes at offsets {@code offset+0}, {@code offset+1}, ..., * {@code offset+length-1} of byte array {@code targetBuffer}. * - * @param targetBuffer the buffer to copy - * @param offset start offset - * @param length length to copy + * @param targetBuffer the buffer to copy. + * @param offset start offset. + * @param length length to copy. * @throws IllegalStateException The buffer doesn't have sufficient space. Use * {@link #getSpace()} to prevent this exception. * @throws IllegalArgumentException Either of {@code offset}, or {@code length} is negative. @@ -119,7 +119,7 @@ public void clear() { /** * Gets the number of bytes, that are currently present in the buffer. * - * @return the number of bytes + * @return the number of bytes. */ public int getCurrentNumberOfBytes() { return currentNumberOfBytes; @@ -128,7 +128,7 @@ public int getCurrentNumberOfBytes() { /** * Gets the number of bytes, that can currently be added to the buffer. * - * @return the number of bytes that can be added + * @return the number of bytes that can be added. */ public int getSpace() { return buffer.length - currentNumberOfBytes; @@ -158,7 +158,7 @@ public boolean hasSpace() { /** * Tests whether there is currently room for the given number of bytes in the buffer. * - * @param count the byte count + * @param count the byte count. * @return true whether there is currently room for the given number of bytes in the buffer. * @see #hasSpace() * @see #getSpace() @@ -173,9 +173,9 @@ public boolean hasSpace(final int count) { * removed from the buffer. If the result is true, then the following invocations * of {@link #read()} are guaranteed to return exactly those bytes. * - * @param sourceBuffer the buffer to compare against - * @param offset start offset - * @param length length to compare + * @param sourceBuffer the buffer to compare against. + * @param offset start offset. + * @param length length to compare. * @return True, if the next invocations of {@link #read()} will return the * bytes at offsets {@code sourceBuffer}+0, {@code offset}+1, ..., * {@code offset}+{@code length}-1 of byte array {@code sourceBuffer}. diff --git a/src/main/java/org/apache/commons/io/input/buffer/PeekableInputStream.java b/src/main/java/org/apache/commons/io/input/buffer/PeekableInputStream.java index ec96054fc43..8bb0f7c7158 100644 --- a/src/main/java/org/apache/commons/io/input/buffer/PeekableInputStream.java +++ b/src/main/java/org/apache/commons/io/input/buffer/PeekableInputStream.java @@ -53,8 +53,8 @@ public PeekableInputStream(final InputStream inputStream, final int bufferSize) * Returns whether the next bytes in the buffer are as given by {@code sourceBuffer}. This is equivalent to * {@link #peek(byte[], int, int)} with {@code offset} == 0, and {@code length} == {@code sourceBuffer.length} * - * @param sourceBuffer the buffer to compare against - * @return true if the next bytes are as given + * @param sourceBuffer the buffer to compare against. + * @return true if the next bytes are as given. * @throws IOException Refilling the buffer failed. */ public boolean peek(final byte[] sourceBuffer) throws IOException { @@ -66,11 +66,11 @@ public boolean peek(final byte[] sourceBuffer) throws IOException { * Returns whether the next bytes in the buffer are as given by {@code sourceBuffer}, {code offset}, and * {@code length}. * - * @param sourceBuffer the buffer to compare against - * @param offset the start offset - * @param length the length to compare - * @return true if the next bytes in the buffer are as given - * @throws IOException if there is a problem calling fillBuffer() + * @param sourceBuffer the buffer to compare against. + * @param offset the start offset. + * @param length the length to compare. + * @return true if the next bytes in the buffer are as given. + * @throws IOException if there is a problem calling fillBuffer(). */ public boolean peek(final byte[] sourceBuffer, final int offset, final int length) throws IOException { Objects.requireNonNull(sourceBuffer, "sourceBuffer"); diff --git a/src/main/java/org/apache/commons/io/monitor/FileAlterationListener.java b/src/main/java/org/apache/commons/io/monitor/FileAlterationListener.java index ce64c8d4ed4..b7bf2a0cdb4 100644 --- a/src/main/java/org/apache/commons/io/monitor/FileAlterationListener.java +++ b/src/main/java/org/apache/commons/io/monitor/FileAlterationListener.java @@ -31,56 +31,56 @@ public interface FileAlterationListener { /** * Directory changed Event. * - * @param directory The directory changed + * @param directory The directory changed. */ void onDirectoryChange(File directory); /** * Directory created Event. * - * @param directory The directory created + * @param directory The directory created. */ void onDirectoryCreate(File directory); /** * Directory deleted Event. * - * @param directory The directory deleted + * @param directory The directory deleted. */ void onDirectoryDelete(File directory); /** * File changed Event. * - * @param file The file changed + * @param file The file changed. */ void onFileChange(File file); /** * File created Event. * - * @param file The file created + * @param file The file created. */ void onFileCreate(File file); /** * File deleted Event. * - * @param file The file deleted + * @param file The file deleted. */ void onFileDelete(File file); /** * File system observer started checking event. * - * @param observer The file system observer + * @param observer The file system observer. */ void onStart(FileAlterationObserver observer); /** * File system observer finished checking event. * - * @param observer The file system observer + * @param observer The file system observer. */ void onStop(FileAlterationObserver observer); } diff --git a/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.java b/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.java index 0b54bbd6723..c676470fa31 100644 --- a/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.java +++ b/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.java @@ -36,7 +36,7 @@ public FileAlterationListenerAdaptor() { /** * Directory changed Event. * - * @param directory The directory changed (ignored) + * @param directory The directory changed (ignored). */ @Override public void onDirectoryChange(final File directory) { @@ -46,7 +46,7 @@ public void onDirectoryChange(final File directory) { /** * Directory created Event. * - * @param directory The directory created (ignored) + * @param directory The directory created (ignored). */ @Override public void onDirectoryCreate(final File directory) { @@ -56,7 +56,7 @@ public void onDirectoryCreate(final File directory) { /** * Directory deleted Event. * - * @param directory The directory deleted (ignored) + * @param directory The directory deleted (ignored). */ @Override public void onDirectoryDelete(final File directory) { @@ -66,7 +66,7 @@ public void onDirectoryDelete(final File directory) { /** * File changed Event. * - * @param file The file changed (ignored) + * @param file The file changed (ignored). */ @Override public void onFileChange(final File file) { @@ -76,7 +76,7 @@ public void onFileChange(final File file) { /** * File created Event. * - * @param file The file created (ignored) + * @param file The file created (ignored). */ @Override public void onFileCreate(final File file) { @@ -86,7 +86,7 @@ public void onFileCreate(final File file) { /** * File deleted Event. * - * @param file The file deleted (ignored) + * @param file The file deleted (ignored). */ @Override public void onFileDelete(final File file) { @@ -96,7 +96,7 @@ public void onFileDelete(final File file) { /** * File system observer started checking event. * - * @param observer The file system observer (ignored) + * @param observer The file system observer (ignored). */ @Override public void onStart(final FileAlterationObserver observer) { @@ -106,7 +106,7 @@ public void onStart(final FileAlterationObserver observer) { /** * File system observer finished checking event. * - * @param observer The file system observer (ignored) + * @param observer The file system observer (ignored). */ @Override public void onStop(final FileAlterationObserver observer) { diff --git a/src/main/java/org/apache/commons/io/monitor/FileAlterationMonitor.java b/src/main/java/org/apache/commons/io/monitor/FileAlterationMonitor.java index 394e7aca661..ab3a65b9416 100644 --- a/src/main/java/org/apache/commons/io/monitor/FileAlterationMonitor.java +++ b/src/main/java/org/apache/commons/io/monitor/FileAlterationMonitor.java @@ -98,7 +98,7 @@ public FileAlterationMonitor(final long interval, final FileAlterationObserver.. /** * Adds a file system observer to this monitor. * - * @param observer The file system observer to add + * @param observer The file system observer to add. */ public void addObserver(final FileAlterationObserver observer) { if (observer != null) { @@ -109,7 +109,7 @@ public void addObserver(final FileAlterationObserver observer) { /** * Returns the interval. * - * @return the interval + * @return the interval. */ public long getInterval() { return intervalMillis; @@ -128,7 +128,7 @@ public Iterable* Serialization is deprecated and will be removed in 3.0. *
+ * * @see FileAlterationObserver * @since 2.0 */ @@ -84,7 +85,7 @@ public class FileEntry implements Serializable { /** * Constructs a new monitor for a specified {@link File}. * - * @param file The file being monitored + * @param file The file being monitored. */ public FileEntry(final File file) { this(null, file); @@ -107,7 +108,7 @@ public FileEntry(final FileEntry parent, final File file) { * * @return This directory's files or an empty * array if the file is not a directory or the - * directory is empty + * directory is empty. */ public FileEntry[] getChildren() { return children != null ? children : EMPTY_FILE_ENTRY_ARRAY; @@ -116,7 +117,7 @@ public FileEntry[] getChildren() { /** * Gets the file being monitored. * - * @return the file being monitored + * @return the file being monitored. */ public File getFile() { return file; @@ -145,7 +146,7 @@ public FileTime getLastModifiedFileTime() { /** * Gets the length. * - * @return the length + * @return the length. */ public long getLength() { return length; @@ -154,7 +155,7 @@ public long getLength() { /** * Gets the level * - * @return the level + * @return the level. */ public int getLevel() { return parent == null ? 0 : parent.getLevel() + 1; @@ -163,7 +164,7 @@ public int getLevel() { /** * Gets the file name. * - * @return the file name + * @return the file name. */ public String getName() { return name; @@ -172,7 +173,7 @@ public String getName() { /** * Gets the parent entry. * - * @return the parent entry + * @return the parent entry. */ public FileEntry getParent() { return parent; @@ -181,7 +182,7 @@ public FileEntry getParent() { /** * Tests whether the file is a directory or not. * - * @return whether the file is a directory or not + * @return whether the file is a directory or not. */ public boolean isDirectory() { return directory; @@ -191,7 +192,7 @@ public boolean isDirectory() { * Tests whether the file existed the last time it * was checked. * - * @return whether the file existed + * @return whether the file existed. */ public boolean isExists() { return exists; @@ -204,8 +205,8 @@ public boolean isExists() { * a new instance of the appropriate type. * * - * @param file The child file - * @return a new child instance + * @param file The child file. + * @return a new child instance. */ public FileEntry newChildInstance(final File file) { return new FileEntry(this, file); @@ -224,8 +225,8 @@ public FileEntry newChildInstance(final File file) { * and {@code length} properties are compared for changes * * - * @param file the file instance to compare to - * @return {@code true} if the file has changed, otherwise {@code false} + * @param file the file instance to compare to. + * @return {@code true} if the file has changed, otherwise {@code false}. */ public boolean refresh(final File file) { // cache original values @@ -253,7 +254,7 @@ public boolean refresh(final File file) { /** * Sets the directory's files. * - * @param children This directory's files, may be null + * @param children This directory's files, may be null. */ public void setChildren(final FileEntry... children) { this.children = children; @@ -262,7 +263,7 @@ public void setChildren(final FileEntry... children) { /** * Sets whether the file is a directory or not. * - * @param directory whether the file is a directory or not + * @param directory whether the file is a directory or not. */ public void setDirectory(final boolean directory) { this.directory = directory; @@ -272,7 +273,7 @@ public void setDirectory(final boolean directory) { * Sets whether the file existed the last time it * was checked. * - * @param exists whether the file exists or not + * @param exists whether the file exists or not. */ public void setExists(final boolean exists) { this.exists = exists; @@ -305,7 +306,7 @@ void setLastModified(final SerializableFileTime lastModified) { /** * Sets the length. * - * @param length the length + * @param length the length. */ public void setLength(final long length) { this.length = length; @@ -314,7 +315,7 @@ public void setLength(final long length) { /** * Sets the file name. * - * @param name the file name + * @param name the file name. */ public void setName(final String name) { this.name = name; diff --git a/src/main/java/org/apache/commons/io/output/AbstractByteArrayOutputStream.java b/src/main/java/org/apache/commons/io/output/AbstractByteArrayOutputStream.java index 6b095474fb2..90b65d28801 100644 --- a/src/main/java/org/apache/commons/io/output/AbstractByteArrayOutputStream.java +++ b/src/main/java/org/apache/commons/io/output/AbstractByteArrayOutputStream.java @@ -56,7 +56,7 @@ * ignored. * * - * @param