aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-04 03:04:02 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-04 03:04:02 +0000
commit9b6d0b5639882de2aa5624f174e87cb28717d9e7 (patch)
treeb9d08e0241a6b4395446f0d76f19c07f37874827
parent8305e91863d11c7ccec698de0cbc0078e5199927 (diff)
parent0c4d7b72e49a04598d65c566f44504b95342d75a (diff)
downloadapache-commons-io-android14-qpr2-release.tar.gz
Change-Id: I714f4fd5addf48715cac4ccd95aee0668d6a2507
-rw-r--r--.github/workflows/codeql-analysis.yml8
-rw-r--r--.github/workflows/coverage.yml4
-rw-r--r--.github/workflows/maven.yml12
-rw-r--r--.github/workflows/scorecards-analysis.yml6
-rw-r--r--METADATA6
-rw-r--r--README.md78
-rw-r--r--RELEASE-NOTES.txt79
-rw-r--r--pom.xml57
-rw-r--r--src/changes/changes.xml101
-rw-r--r--src/conf/checkstyle.xml6
-rw-r--r--src/main/java/org/apache/commons/io/ByteOrderMark.java7
-rw-r--r--src/main/java/org/apache/commons/io/CopyUtils.java2
-rw-r--r--src/main/java/org/apache/commons/io/EndianUtils.java2
-rw-r--r--src/main/java/org/apache/commons/io/FileUtils.java119
-rw-r--r--src/main/java/org/apache/commons/io/FilenameUtils.java4
-rw-r--r--src/main/java/org/apache/commons/io/HexDump.java2
-rw-r--r--src/main/java/org/apache/commons/io/IOIndexedException.java3
-rw-r--r--src/main/java/org/apache/commons/io/IOUtils.java22
-rw-r--r--src/main/java/org/apache/commons/io/RandomAccessFileMode.java3
-rw-r--r--src/main/java/org/apache/commons/io/RandomAccessFiles.java55
-rw-r--r--src/main/java/org/apache/commons/io/StreamIterator.java48
-rw-r--r--src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java5
-rw-r--r--src/main/java/org/apache/commons/io/channels/FileChannels.java87
-rw-r--r--src/main/java/org/apache/commons/io/channels/package-info.java23
-rw-r--r--src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java7
-rw-r--r--src/main/java/org/apache/commons/io/file/FilesUncheck.java60
-rw-r--r--src/main/java/org/apache/commons/io/file/PathUtils.java65
-rw-r--r--src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java18
-rw-r--r--src/main/java/org/apache/commons/io/filefilter/package-info.java2
-rw-r--r--src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java4
-rw-r--r--src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java3
-rw-r--r--src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java29
-rw-r--r--src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java193
-rw-r--r--src/main/java/org/apache/commons/io/input/ObservableInputStream.java2
-rw-r--r--src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java3
-rw-r--r--src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java2
-rw-r--r--src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.java30
-rw-r--r--src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java12
-rw-r--r--src/main/java/org/apache/commons/io/input/XmlStreamReader.java20
-rw-r--r--src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java47
-rw-r--r--src/main/java/org/apache/commons/io/output/LockableFileWriter.java3
-rw-r--r--src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java14
-rw-r--r--src/main/java/org/apache/commons/io/output/WriterOutputStream.java3
-rw-r--r--src/main/java/org/apache/commons/io/output/XmlStreamWriter.java3
-rw-r--r--src/main/java/org/apache/commons/io/package-info.java2
-rw-r--r--src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java52
-rw-r--r--src/site/xdoc/download_io.xml26
-rw-r--r--src/site/xdoc/index.xml13
-rw-r--r--src/site/xdoc/mail-lists.xml38
-rw-r--r--src/test/java/org/apache/commons/io/CharsetsTest.java15
-rw-r--r--src/test/java/org/apache/commons/io/DemuxInputStreamTest.java10
-rw-r--r--src/test/java/org/apache/commons/io/DirectoryWalkerTest.java8
-rw-r--r--src/test/java/org/apache/commons/io/DirectoryWalkerTestCaseJava4.java6
-rw-r--r--src/test/java/org/apache/commons/io/EndianUtilsTest.java2
-rw-r--r--src/test/java/org/apache/commons/io/FileUtilsDirectoryContainsTest.java6
-rw-r--r--src/test/java/org/apache/commons/io/FileUtilsListFilesTest.java113
-rw-r--r--src/test/java/org/apache/commons/io/FileUtilsTest.java89
-rw-r--r--src/test/java/org/apache/commons/io/IOUtilsMultithreadedSkipTest.java2
-rw-r--r--src/test/java/org/apache/commons/io/IOUtilsTest.java11
-rw-r--r--src/test/java/org/apache/commons/io/RandomAccessFilesTest.java90
-rw-r--r--src/test/java/org/apache/commons/io/StreamIteratorTest.java60
-rw-r--r--src/test/java/org/apache/commons/io/file/AbstractTempDirTest.java5
-rw-r--r--src/test/java/org/apache/commons/io/file/FilesUncheckTest.java25
-rw-r--r--src/test/java/org/apache/commons/io/filefilter/AbstractConditionalFileFilterTest.java12
-rw-r--r--src/test/java/org/apache/commons/io/function/IOBaseStreamTest.java4
-rw-r--r--src/test/java/org/apache/commons/io/function/IOBinaryOperatorStreamTest.java21
-rw-r--r--src/test/java/org/apache/commons/io/function/IOConsumerTest.java8
-rw-r--r--src/test/java/org/apache/commons/io/function/IOFunctionTest.java4
-rw-r--r--src/test/java/org/apache/commons/io/function/IOLongSupplierTest.java2
-rw-r--r--src/test/java/org/apache/commons/io/function/IOStreamTest.java15
-rw-r--r--src/test/java/org/apache/commons/io/function/TestConstants.java8
-rw-r--r--src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java4
-rw-r--r--src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java39
-rw-r--r--src/test/java/org/apache/commons/io/input/ClassLoaderObjectInputStreamTest.java2
-rw-r--r--src/test/java/org/apache/commons/io/input/MarkShieldInputStreamTest.java2
-rw-r--r--src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.java47
-rw-r--r--src/test/java/org/apache/commons/io/input/MessageDigestInputStreamTest.java65
-rw-r--r--src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java15
-rw-r--r--src/test/java/org/apache/commons/io/input/ProxyReaderTest.java4
-rw-r--r--src/test/java/org/apache/commons/io/input/TailerTest.java24
-rw-r--r--src/test/java/org/apache/commons/io/input/TimestampedObserverTest.java4
-rw-r--r--src/test/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStreamTest.java139
-rw-r--r--src/test/java/org/apache/commons/io/input/XmlStreamReaderTest.java32
-rw-r--r--src/test/java/org/apache/commons/io/input/XmlStreamReaderUtilitiesTest.java2
-rw-r--r--src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderUtilitiesCompatibilityTest.java2
-rw-r--r--src/test/java/org/apache/commons/io/jmh/PathUtilsContentEqualsBenchmark.java119
-rw-r--r--src/test/java/org/apache/commons/io/output/ByteArrayOutputStreamTest.java4
-rw-r--r--src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java8
-rw-r--r--src/test/java/org/apache/commons/io/test/TestUtils.java8
-rw-r--r--src/test/resources/org/apache/commons/io/test-file-empty2.bin0
90 files changed, 1760 insertions, 666 deletions
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 14204217..120d34f3 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -45,7 +45,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
@@ -57,7 +57,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@04daf014b50eaf774287bf3f0f1869d4b4c4b913 # v2.21.7
+ uses: github/codeql-action/init@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -68,7 +68,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@04daf014b50eaf774287bf3f0f1869d4b4c4b913 # v2.21.7
+ uses: github/codeql-action/autobuild@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
# ℹī¸ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -82,4 +82,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@04daf014b50eaf774287bf3f0f1869d4b4c4b913 # v2.21.7
+ uses: github/codeql-action/analyze@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
index f100bf3f..5c778d55 100644
--- a/.github/workflows/coverage.yml
+++ b/.github/workflows/coverage.yml
@@ -29,7 +29,7 @@ jobs:
java: [ 8 ]
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
@@ -44,7 +44,7 @@ jobs:
distribution: 'temurin'
java-version: ${{ matrix.java }}
- name: Build with Maven
- run: mvn -V test jacoco:report --file pom.xml --no-transfer-progress
+ run: mvn --show-version --batch-mode --no-transfer-progress test jacoco:report
- name: Upload coverage to Codecov
uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 6bd303e9..3ed497d6 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -28,22 +28,22 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
- java: [ 8, 11, 17 ]
+ java: [ 8, 11, 17, 21 ]
experimental: [false]
# include:
-# - java: 18-ea
+# - java: 22-ea
# os: ubuntu-latest
# experimental: true
-# - java: 18-ea
+# - java: 22-ea
# os: windows-latest
# experimental: true
-# - java: 18-ea
+# - java: 22-ea
# os: macos-latest
# experimental: true
fail-fast: false
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
@@ -58,4 +58,4 @@ jobs:
distribution: 'temurin'
java-version: ${{ matrix.java }}
- name: Build with Maven
- run: mvn -V --file pom.xml --no-transfer-progress -DtrimStackTrace=false
+ run: mvn --show-version --batch-mode --no-transfer-progress -DtrimStackTrace=false
diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml
index 3f533c0e..890f0498 100644
--- a/.github/workflows/scorecards-analysis.yml
+++ b/.github/workflows/scorecards-analysis.yml
@@ -40,12 +40,12 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- name: "Run analysis"
- uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # 2.2.0
+ uses: ossf/scorecard-action@483ef80eb98fb506c348f7d62e28055e49fe2398 # 2.3.0
with:
results_file: results.sarif
results_format: sarif
@@ -64,6 +64,6 @@ jobs:
retention-days: 5
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@04daf014b50eaf774287bf3f0f1869d4b4c4b913 # 2.21.7
+ uses: github/codeql-action/upload-sarif@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # 2.22.3
with:
sarif_file: results.sarif
diff --git a/METADATA b/METADATA
index b462024b..3833c5d0 100644
--- a/METADATA
+++ b/METADATA
@@ -13,11 +13,11 @@ third_party {
type: GIT
value: "https://github.com/apache/commons-io.git"
}
- version: "rel/commons-io-2.14.0"
+ version: "rel/commons-io-2.15.0"
license_type: NOTICE
last_upgrade_date {
year: 2023
- month: 10
- day: 11
+ month: 11
+ day: 1
}
}
diff --git a/README.md b/README.md
index 25c792e9..48bf0123 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ Apache Commons IO
[![GitHub Actions Status](https://github.com/apache/commons-io/workflows/Java%20CI/badge.svg)](https://github.com/apache/commons-io/actions)
[![Coverage Status](https://codecov.io/gh/apache/commons-io/branch/master/graph/badge.svg)](https://app.codecov.io/gh/apache/commons-io)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/commons-io/commons-io/badge.svg?gav=true)](https://maven-badges.herokuapp.com/maven-central/commons-io/commons-io/?gav=true)
-[![Javadocs](https://javadoc.io/badge/commons-io/commons-io/2.14.0.svg)](https://javadoc.io/doc/commons-io/commons-io/2.14.0)
+[![Javadocs](https://javadoc.io/badge/commons-io/commons-io/2.15.0.svg)](https://javadoc.io/doc/commons-io/commons-io/2.15.0)
[![CodeQL](https://github.com/apache/commons-io/workflows/CodeQL/badge.svg)](https://github.com/apache/commons-io/actions/workflows/codeql-analysis.yml?query=workflow%3ACodeQL)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/commons-io/badge)](https://api.securityscorecards.dev/projects/github.com/apache/commons-io)
@@ -60,8 +60,8 @@ More information can be found on the [Apache Commons IO homepage](https://common
The [Javadoc](https://commons.apache.org/proper/commons-io/apidocs) can be browsed.
Questions related to the usage of Apache Commons IO should be posted to the [user mailing list][ml].
-Where can I get the latest release?
------------------------------------
+Getting the latest release
+--------------------------
You can download source and binaries from our [download page](https://commons.apache.org/proper/commons-io/download_io.cgi).
Alternatively, you can pull it from the central Maven repositories:
@@ -70,17 +70,25 @@ Alternatively, you can pull it from the central Maven repositories:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- <version>2.14.0</version>
+ <version>2.15.0</version>
</dependency>
```
+Building
+--------
+
+Building requires a Java JDK and [Apache Maven](https://maven.apache.org/).
+The required Java version is found in the `pom.xml` as the `maven.compiler.source` property.
+
+From a command shell, run `mvn` without arguments to invoke the default Maven goal to run all tests and checks.
+
Contributing
------------
We accept Pull Requests via GitHub. The [developer mailing list](https://commons.apache.org/mail-lists.html) is the main channel of communication for contributors.
There are some guidelines which will make applying PRs easier for us:
+ No tabs! Please use spaces for indentation.
-+ Respect the code style.
++ Respect the existing code style for each file.
+ 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.
+ Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running ```mvn```.
@@ -89,13 +97,13 @@ You can learn more about contributing via GitHub in our [contribution guidelines
License
-------
-This code is under the [Apache License v2](https://www.apache.org/licenses/LICENSE-2.0).
+This code is licensed under the [Apache License v2](https://www.apache.org/licenses/LICENSE-2.0).
See the `NOTICE.txt` file for required notices and attributions.
-Donations
----------
-You like Apache Commons IO? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support the development.
+Donating
+--------
+You like Apache Commons IO? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support development.
Additional Resources
--------------------
@@ -109,54 +117,4 @@ Additional Resources
Apache Commons Components
-------------------------
-| Component | GitHub Repository | Apache Homepage |
-| --------- | ----------------- | ----------------|
-| Apache Commons BCEL | [commons-bcel](https://github.com/apache/commons-bcel) | [commons-bcel](https://commons.apache.org/proper/commons-bcel) |
-| Apache Commons Beanutils | [commons-beanutils](https://github.com/apache/commons-beanutils) | [commons-beanutils](https://commons.apache.org/proper/commons-beanutils) |
-| Apache Commons BSF | [commons-bsf](https://github.com/apache/commons-bsf) | [commons-bsf](https://commons.apache.org/proper/commons-bsf) |
-| Apache Commons Build-plugin | [commons-build-plugin](https://github.com/apache/commons-build-plugin) | [commons-build-plugin](https://commons.apache.org/proper/commons-build-plugin) |
-| Apache Commons Chain | [commons-chain](https://github.com/apache/commons-chain) | [commons-chain](https://commons.apache.org/proper/commons-chain) |
-| Apache Commons CLI | [commons-cli](https://github.com/apache/commons-cli) | [commons-cli](https://commons.apache.org/proper/commons-cli) |
-| Apache Commons Codec | [commons-codec](https://github.com/apache/commons-codec) | [commons-codec](https://commons.apache.org/proper/commons-codec) |
-| Apache Commons Collections | [commons-collections](https://github.com/apache/commons-collections) | [commons-collections](https://commons.apache.org/proper/commons-collections) |
-| Apache Commons Compress | [commons-compress](https://github.com/apache/commons-compress) | [commons-compress](https://commons.apache.org/proper/commons-compress) |
-| Apache Commons Configuration | [commons-configuration](https://github.com/apache/commons-configuration) | [commons-configuration](https://commons.apache.org/proper/commons-configuration) |
-| Apache Commons Crypto | [commons-crypto](https://github.com/apache/commons-crypto) | [commons-crypto](https://commons.apache.org/proper/commons-crypto) |
-| Apache Commons CSV | [commons-csv](https://github.com/apache/commons-csv) | [commons-csv](https://commons.apache.org/proper/commons-csv) |
-| Apache Commons Daemon | [commons-daemon](https://github.com/apache/commons-daemon) | [commons-daemon](https://commons.apache.org/proper/commons-daemon) |
-| Apache Commons DBCP | [commons-dbcp](https://github.com/apache/commons-dbcp) | [commons-dbcp](https://commons.apache.org/proper/commons-dbcp) |
-| Apache Commons Dbutils | [commons-dbutils](https://github.com/apache/commons-dbutils) | [commons-dbutils](https://commons.apache.org/proper/commons-dbutils) |
-| Apache Commons Digester | [commons-digester](https://github.com/apache/commons-digester) | [commons-digester](https://commons.apache.org/proper/commons-digester) |
-| Apache Commons Email | [commons-email](https://github.com/apache/commons-email) | [commons-email](https://commons.apache.org/proper/commons-email) |
-| Apache Commons Exec | [commons-exec](https://github.com/apache/commons-exec) | [commons-exec](https://commons.apache.org/proper/commons-exec) |
-| Apache Commons Fileupload | [commons-fileupload](https://github.com/apache/commons-fileupload) | [commons-fileupload](https://commons.apache.org/proper/commons-fileupload) |
-| Apache Commons Functor | [commons-functor](https://github.com/apache/commons-functor) | [commons-functor](https://commons.apache.org/proper/commons-functor) |
-| Apache Commons Geometry | [commons-geometry](https://github.com/apache/commons-geometry) | [commons-geometry](https://commons.apache.org/proper/commons-geometry) |
-| Apache Commons Graph | [commons-graph](https://github.com/apache/commons-graph) | [commons-graph](https://commons.apache.org/proper/commons-graph) |
-| Apache Commons Imaging | [commons-imaging](https://github.com/apache/commons-imaging) | [commons-imaging](https://commons.apache.org/proper/commons-imaging) |
-| Apache Commons IO | [commons-io](https://github.com/apache/commons-io) | [commons-io](https://commons.apache.org/proper/commons-io) |
-| Apache Commons JCI | [commons-jci](https://github.com/apache/commons-jci) | [commons-jci](https://commons.apache.org/proper/commons-jci) |
-| Apache Commons JCS | [commons-jcs](https://github.com/apache/commons-jcs) | [commons-jcs](https://commons.apache.org/proper/commons-jcs) |
-| Apache Commons Jelly | [commons-jelly](https://github.com/apache/commons-jelly) | [commons-jelly](https://commons.apache.org/proper/commons-jelly) |
-| Apache Commons Jexl | [commons-jexl](https://github.com/apache/commons-jexl) | [commons-jexl](https://commons.apache.org/proper/commons-jexl) |
-| Apache Commons Jxpath | [commons-jxpath](https://github.com/apache/commons-jxpath) | [commons-jxpath](https://commons.apache.org/proper/commons-jxpath) |
-| Apache Commons Lang | [commons-lang](https://github.com/apache/commons-lang) | [commons-lang](https://commons.apache.org/proper/commons-lang) |
-| Apache Commons Logging | [commons-logging](https://github.com/apache/commons-logging) | [commons-logging](https://commons.apache.org/proper/commons-logging) |
-| Apache Commons Math | [commons-math](https://github.com/apache/commons-math) | [commons-math](https://commons.apache.org/proper/commons-math) |
-| Apache Commons Net | [commons-net](https://github.com/apache/commons-net) | [commons-net](https://commons.apache.org/proper/commons-net) |
-| Apache Commons Numbers | [commons-numbers](https://github.com/apache/commons-numbers) | [commons-numbers](https://commons.apache.org/proper/commons-numbers) |
-| Apache Commons Parent | [commons-parent](https://github.com/apache/commons-parent) | [commons-parent](https://commons.apache.org/proper/commons-parent) |
-| Apache Commons Pool | [commons-pool](https://github.com/apache/commons-pool) | [commons-pool](https://commons.apache.org/proper/commons-pool) |
-| Apache Commons Proxy | [commons-proxy](https://github.com/apache/commons-proxy) | [commons-proxy](https://commons.apache.org/proper/commons-proxy) |
-| Apache Commons RDF | [commons-rdf](https://github.com/apache/commons-rdf) | [commons-rdf](https://commons.apache.org/proper/commons-rdf) |
-| Apache Commons Release-plugin | [commons-release-plugin](https://github.com/apache/commons-release-plugin) | [commons-release-plugin](https://commons.apache.org/proper/commons-release-plugin) |
-| Apache Commons Rng | [commons-rng](https://github.com/apache/commons-rng) | [commons-rng](https://commons.apache.org/proper/commons-rng) |
-| Apache Commons Scxml | [commons-scxml](https://github.com/apache/commons-scxml) | [commons-scxml](https://commons.apache.org/proper/commons-scxml) |
-| Apache Commons Signing | [commons-signing](https://github.com/apache/commons-signing) | [commons-signing](https://commons.apache.org/proper/commons-signing) |
-| Apache Commons Skin | [commons-skin](https://github.com/apache/commons-skin) | [commons-skin](https://commons.apache.org/proper/commons-skin) |
-| Apache Commons Statistics | [commons-statistics](https://github.com/apache/commons-statistics) | [commons-statistics](https://commons.apache.org/proper/commons-statistics) |
-| Apache Commons Testing | [commons-testing](https://github.com/apache/commons-testing) | [commons-testing](https://commons.apache.org/proper/commons-testing) |
-| Apache Commons Text | [commons-text](https://github.com/apache/commons-text) | [commons-text](https://commons.apache.org/proper/commons-text) |
-| Apache Commons Validator | [commons-validator](https://github.com/apache/commons-validator) | [commons-validator](https://commons.apache.org/proper/commons-validator) |
-| Apache Commons VFS | [commons-vfs](https://github.com/apache/commons-vfs) | [commons-vfs](https://commons.apache.org/proper/commons-vfs) |
-| Apache Commons Weaver | [commons-weaver](https://github.com/apache/commons-weaver) | [commons-weaver](https://commons.apache.org/proper/commons-weaver) |
+Please see the [list of components](https://commons.apache.org/components.html)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 8300ad4f..7eb52960 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -1,3 +1,82 @@
+Apache Commons IO
+Version 2.15.0
+Release Notes
+
+INTRODUCTION:
+
+Commons IO is a package of Java utility classes like java.io.
+Classes in this package are considered to be so standard and of such high
+reuse as to justify existence in java.io.
+
+The Apache Commons IO library contains utility classes, stream implementations, file filters,
+file comparators, endian transformation classes, and much more.
+
+Java 8 is required.
+
+Changes in this version include:
+
+New features:
+o Add org.apache.commons.io.channels.FileChannels. Thanks to Gary Gregory.
+o Add RandomAccessFiles#contentEquals(RandomAccessFile, RandomAccessFile). Thanks to Gary Gregory.
+o Add RandomAccessFiles#reset(RandomAccessFile). Thanks to Gary Gregory.
+o Add PathUtilsContentEqualsBenchmark. Thanks to Gary Gregory.
+o Add org.apache.commons.io.StreamIterator. Thanks to Gary Gregory.
+o Add MessageDigestInputStream and deprecate MessageDigestCalculatingInputStream. Thanks to Gary Gregory.
+
+Fixed Bugs:
+o IO-810: XmlStreamReader encoding match RE is too strict. Thanks to Laurence Gonsalves.
+o IO-810: Javadoc in FileUtils does not reflect code for thrown exceptions. Thanks to Gregor Dschung, Gary Gregory.
+o IO-812: Javadoc should mention closing Streams based on file resources. Thanks to Adam Rauch, Gary Gregory.
+o IO-811: In tests, Files.walk() direct and indirect callers fail to close the returned Stream. Thanks to Adam Rauch, Gary Gregory.
+o IO-811: FileUtils.listFiles(File, String[], boolean) fails to close its internal Stream. Thanks to Adam Rauch, Gary Gregory.
+o IO-811: FileUtils.iterateFiles(File, String[], boolean) fails to close its internal Stream. Thanks to Adam Rauch, Gary Gregory.
+o IO-811: StreamIterator fails to close its internal Stream. Thanks to Adam Rauch, Gary Gregory.
+o IO-814: Don't throw UncheckedIOException #491. Thanks to Elliotte Rusty Harold, Gary Gregory.
+o IO-414: Don't write a BOM on every (or any) line #492. Thanks to Elliotte Rusty Harold, Gary Gregory.
+o IO-814: RandomAccessFileMode.create(Path) provides a better NullPointerException message. Thanks to Gary Gregory.
+o Improve performance of PathUtils.fileContentEquals(Path, Path, LinkOption[], OpenOption[]) by about 60%, see PathUtilsContentEqualsBenchmark. Thanks to Gary Gregory.
+o Improve performance of PathUtils.fileContentEquals(Path, Path) by about 60%, see PathUtilsContentEqualsBenchmark. Thanks to Gary Gregory.
+o Improve performance of FileUtils.contentEquals(File, File) by about 60%, see PathUtilsContentEqualsBenchmark. Thanks to Gary Gregory.
+o Remove unused test code #494. Thanks to Elliotte Rusty Harold.
+o [Javadoc] IOUtils#contentEquals does not throw NullPointerException #496. Thanks to sebbASF.
+o Fix CodeQL warnings in UnsynchronizedBufferedInputStream: Implicit narrowing conversion in compound assignment. Thanks to Gary Gregory.
+o MessageDigestCalculatingInputStream.MessageDigestMaintainingObserver.MessageDigestMaintainingObserver(MessageDigest) now throws a NullPointerException
+ if the MessageDigest is null. Thanks to Gary Gregory.
+o MessageDigestCalculatingInputStream.MessageDigestCalculatingInputStream(InputStream, MessageDigest) now throws a NullPointerException
+ if the MessageDigest is null. Thanks to Gary Gregory.
+o IO-816: UnsynchronizedBufferedInputStream.read(byte[], int, int) does not use buffer. Thanks to Andreas Loth, Gary Gregory.
+
+Changes:
+o Bump org.apache.commons:commons-parent from 62 to 64. Thanks to Gary Gregory.
+
+Compatibility with 2.6:
+Binary compatible: Yes.
+Source compatible: Yes.
+Semantic compatible: Yes.
+
+Commons IO 2.9.0 requires Java 8.
+Commons IO 2.8.0 requires Java 8.
+Commons IO 2.7 requires Java 8.
+Commons IO 2.6 requires Java 7.
+Commons IO 2.5 requires Java 6.
+Commons IO 2.4 requires Java 6.
+Commons IO 2.3 requires Java 6.
+Commons IO 2.2 requires Java 5.
+Commons IO 1.4 requires Java 1.3.
+
+Historical list of changes: https://commons.apache.org/proper/commons-io/changes-report.html
+
+For complete information on Apache Commons IO, including instructions on how to submit bug reports,
+patches, or suggestions for improvement, see the Apache Commons IO website:
+
+https://commons.apache.org/proper/commons-io/
+
+Download page: https://commons.apache.org/proper/commons-io/download_io.cgi
+
+Have fun!
+-Apache Commons Team
+
+==============================================================================
Apache Commons IO
Version 2.14.0
diff --git a/pom.xml b/pom.xml
index 18c11d96..bad8c9ba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@@ -19,12 +19,12 @@
<parent>
<groupId>org.apache.commons</groupId>
<artifactId>commons-parent</artifactId>
- <version>62</version>
+ <version>64</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- <version>2.14.0</version>
+ <version>2.15.0</version>
<name>Apache Commons IO</name>
<inceptionYear>2002</inceptionYear>
@@ -52,7 +52,7 @@ file comparators, endian transformation classes, and much more.
<connection>scm:git:https://gitbox.apache.org/repos/asf/commons-io.git</connection>
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/commons-io.git</developerConnection>
<url>https://gitbox.apache.org/repos/asf?p=commons-io.git</url>
- <tag>rel/commons-io-2.13.0</tag>
+ <tag>rel/commons-io-2.15.0</tag>
</scm>
<developers>
@@ -257,6 +257,20 @@ file comparators, endian transformation classes, and much more.
<scope>test</scope>
</dependency>
<dependency>
+ <!-- Java 21 support, revisit for Mockito 5 -->
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy</artifactId>
+ <version>${commons.bytebuddy.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <!-- Java 21 support, revisit for Mockito 5 -->
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy-agent</artifactId>
+ <version>${commons.bytebuddy.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>4.11.0</version>
@@ -275,6 +289,12 @@ file comparators, endian transformation classes, and much more.
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.16.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh.version}</version>
@@ -294,8 +314,9 @@ file comparators, endian transformation classes, and much more.
<commons.componentid>io</commons.componentid>
<commons.module.name>org.apache.commons.io</commons.module.name>
<commons.rc.version>RC1</commons.rc.version>
- <commons.bc.version>2.13.0</commons.bc.version>
- <commons.release.version>2.14.0</commons.release.version>
+ <commons.bc.version>2.14.0</commons.bc.version>
+ <commons.release.version>2.15.0</commons.release.version>
+ <commons.release.next>2.15.1</commons.release.next>
<commons.release.desc>(requires Java 8)</commons.release.desc>
<commons.jira.id>IO</commons.jira.id>
<commons.jira.pid>12310477</commons.jira.pid>
@@ -325,11 +346,10 @@ file comparators, endian transformation classes, and much more.
<commons.javadoc.java.link>${commons.javadoc8.java.link}</commons.javadoc.java.link>
<commons.moditect.version>1.0.0.Final</commons.moditect.version>
<jmh.version>1.37</jmh.version>
+ <commons.bytebuddy.version>1.14.9</commons.bytebuddy.version>
<japicmp.skip>false</japicmp.skip>
<jacoco.skip>${env.JACOCO_SKIP}</jacoco.skip>
<commons.release.isDistModule>true</commons.release.isDistModule>
- <commons.releaseManagerName>Gary Gregory</commons.releaseManagerName>
- <commons.releaseManagerKey>86fdc7e2a11262cb</commons.releaseManagerKey>
</properties>
<build>
@@ -389,7 +409,8 @@ file comparators, endian transformation classes, and much more.
</classpathDependencyExcludes>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
- <!-- limit memory size see IO-161 -->
+ <!-- Limit memory size see IO-161 -->
+ <!-- Mockito inline may need -XX:+EnableDynamicAgentLoading -->
<argLine>${argLine} -Xmx25M</argLine>
<includes>
<!-- Only include test classes, not test data -->
@@ -436,6 +457,14 @@ file comparators, endian transformation classes, and much more.
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
+ <configuration>
+ <parameter>
+ <excludes>
+ <!-- False positive: https://github.com/siom79/japicmp/issues/365 -->
+ <exclude>org.apache.commons.io.StreamIterator</exclude>
+ </excludes>
+ </parameter>
+ </configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -465,7 +494,15 @@ file comparators, endian transformation classes, and much more.
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
- </plugin>
+ <configuration>
+ <parameter>
+ <excludes>
+ <!-- False positive: https://github.com/siom79/japicmp/issues/365 -->
+ <exclude>org.apache.commons.io.StreamIterator</exclude>
+ </excludes>
+ </parameter>
+ </configuration>
+ </plugin>
</plugins>
</reporting>
<profiles>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 28efbb7d..d8665e8f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -47,7 +47,92 @@ The <action> type attribute can be add,update,fix,remove.
</properties>
<body>
- <release version="2.14.0" date="2023-09-24" description="Java 8 required.">
+ <release version="2.15.0" date="2023-10-21" description="Java 8 is required.">
+ <!-- FIX -->
+ <action dev="sebb" type="fix" issue="IO-810" due-to="Laurence Gonsalves">
+ XmlStreamReader encoding match RE is too strict.
+ </action>
+ <action dev="ggregory" type="fix" issue="IO-810" due-to="Gregor Dschung, Gary Gregory">
+ Javadoc in FileUtils does not reflect code for thrown exceptions.
+ </action>
+ <action dev="ggregory" type="fix" issue="IO-812" due-to="Adam Rauch, Gary Gregory">
+ Javadoc should mention closing Streams based on file resources.
+ </action>
+ <action dev="ggregory" type="fix" issue="IO-811" due-to="Adam Rauch, Gary Gregory">
+ In tests, Files.walk() direct and indirect callers fail to close the returned Stream.
+ </action>
+ <action dev="ggregory" type="fix" issue="IO-811" due-to="Adam Rauch, Gary Gregory">
+ FileUtils.listFiles(File, String[], boolean) fails to close its internal Stream.
+ </action>
+ <action dev="ggregory" type="fix" issue="IO-811" due-to="Adam Rauch, Gary Gregory">
+ FileUtils.iterateFiles(File, String[], boolean) fails to close its internal Stream.
+ </action>
+ <action dev="ggregory" type="fix" issue="IO-811" due-to="Adam Rauch, Gary Gregory">
+ StreamIterator fails to close its internal Stream.
+ </action>
+ <action dev="ggregory" type="fix" issue="IO-814" due-to="Elliotte Rusty Harold, Gary Gregory">
+ Don't throw UncheckedIOException #491.
+ </action>
+ <action dev="ggregory" type="fix" issue="IO-414" due-to="Elliotte Rusty Harold, Gary Gregory">
+ Don't write a BOM on every (or any) line #492.
+ </action>
+ <action dev="ggregory" type="fix" issue="IO-814" due-to="Gary Gregory">
+ RandomAccessFileMode.create(Path) provides a better NullPointerException message.
+ </action>
+ <action dev="ggregory" type="fix" due-to="Gary Gregory">
+ Improve performance of PathUtils.fileContentEquals(Path, Path, LinkOption[], OpenOption[]) by about 60%, see PathUtilsContentEqualsBenchmark.
+ </action>
+ <action dev="ggregory" type="fix" due-to="Gary Gregory">
+ Improve performance of PathUtils.fileContentEquals(Path, Path) by about 60%, see PathUtilsContentEqualsBenchmark.
+ </action>
+ <action dev="ggregory" type="fix" due-to="Gary Gregory">
+ Improve performance of FileUtils.contentEquals(File, File) by about 60%, see PathUtilsContentEqualsBenchmark.
+ </action>
+ <action dev="ggregory" type="fix" due-to="Elliotte Rusty Harold">
+ Remove unused test code #494.
+ </action>
+ <action dev="ggregory" type="fix" due-to="sebbASF">
+ [Javadoc] IOUtils#contentEquals does not throw NullPointerException #496.
+ </action>
+ <action dev="ggregory" type="fix" due-to="Gary Gregory">
+ Fix CodeQL warnings in UnsynchronizedBufferedInputStream: Implicit narrowing conversion in compound assignment.
+ </action>
+ <action dev="ggregory" type="fix" due-to="Gary Gregory">
+ MessageDigestCalculatingInputStream.MessageDigestMaintainingObserver.MessageDigestMaintainingObserver(MessageDigest) now throws a NullPointerException
+ if the MessageDigest is null.
+ </action>
+ <action dev="ggregory" type="fix" due-to="Gary Gregory">
+ MessageDigestCalculatingInputStream.MessageDigestCalculatingInputStream(InputStream, MessageDigest) now throws a NullPointerException
+ if the MessageDigest is null.
+ </action>
+ <action issue="IO-816" dev="ggregory" type="fix" due-to="Andreas Loth, Gary Gregory">
+ UnsynchronizedBufferedInputStream.read(byte[], int, int) does not use buffer.
+ </action>
+ <!-- ADD -->
+ <action dev="ggregory" type="add" due-to="Gary Gregory">
+ Add org.apache.commons.io.channels.FileChannels.
+ </action>
+ <action dev="ggregory" type="add" due-to="Gary Gregory">
+ Add RandomAccessFiles#contentEquals(RandomAccessFile, RandomAccessFile).
+ </action>
+ <action dev="ggregory" type="add" due-to="Gary Gregory">
+ Add RandomAccessFiles#reset(RandomAccessFile).
+ </action>
+ <action dev="ggregory" type="add" due-to="Gary Gregory">
+ Add PathUtilsContentEqualsBenchmark.
+ </action>
+ <action dev="ggregory" type="add" due-to="Gary Gregory">
+ Add org.apache.commons.io.StreamIterator.
+ </action>
+ <action dev="ggregory" type="add" due-to="Gary Gregory">
+ Add MessageDigestInputStream and deprecate MessageDigestCalculatingInputStream.
+ </action>
+ <!-- UPDATE -->
+ <action dev="ggregory" type="update" due-to="Gary Gregory">
+ Bump org.apache.commons:commons-parent from 62 to 64.
+ </action>
+ </release>
+ <release version="2.14.0" date="2023-09-24" description="Java 8 is required.">
<!-- FIX -->
<action dev="ggregory" type="fix" issue="IO-799" due-to="Jeroen van der Vegt, Gary Gregory">
ReaderInputStream.read() throws an exception instead of returning -1 when called again after returning -1.
@@ -133,7 +218,7 @@ The <action> type attribute can be add,update,fix,remove.
Bump commons-lang3 from 3.12 to 3.13.0.
</action>
</release>
- <release version="2.13.0" date="2023-06-03" description="Java 8 required.">
+ <release version="2.13.0" date="2023-06-03" description="Java 8 is required.">
<!-- FIX -->
<action issue="IO-791" dev="ggregory" type="fix" due-to="Chad Wilson, Gary Gregory">
Regression in FileUtils.touch() - no longer creates parent directories.
@@ -204,7 +289,7 @@ The <action> type attribute can be add,update,fix,remove.
Bump commons-parent from 57 to 58.
</action>
</release>
- <release version="2.12.0" date="2023-05-13" description="Java 8 required.">
+ <release version="2.12.0" date="2023-05-13" description="Java 8 is required.">
<!-- FIX -->
<action issue="IO-697" dev="kinow" type="fix" due-to="otter606">
IOUtils.toByteArray size validation does not match documentation.
@@ -741,7 +826,7 @@ The <action> type attribute can be add,update,fix,remove.
Bump default buffer size for WriterOutputStream to IOUtils#DEFAULT_BUFFER_SIZE.
</action>
</release>
- <release version="2.11.0" date="2021-07-09" description="Java 8 required.">
+ <release version="2.11.0" date="2021-07-09" description="Java 8 is required.">
<!-- FIX -->
<action issue="IO-741" dev="ggregory" type="fix" due-to="Zach Sherman">
FileUtils.listFiles does not list matching files if File parameter is a symbolic link.
@@ -793,7 +878,7 @@ The <action> type attribute can be add,update,fix,remove.
</action>
</release>
<!-- The release date is the date RC is cut -->
- <release version="2.10.0" date="2021-06-10" description="Java 8 required.">
+ <release version="2.10.0" date="2021-06-10" description="Java 8 is required.">
<!-- FIX -->
<action issue="IO-733" dev="ggregory" type="fix" due-to="Jim Sellers, Gary Gregory">
RegexFileFilter uses the path and file name instead of just the file name.
@@ -828,7 +913,7 @@ The <action> type attribute can be add,update,fix,remove.
Bump mockito-inline from 3.10.0 to 3.11.0 #242.
</action>
</release>
- <release version="2.9.0" date="2021-05-22" description="Java 8 required.">
+ <release version="2.9.0" date="2021-05-22" description="Java 8 is required.">
<!-- FIX -->
<action issue="IO-686" dev="ggregory" type="fix" due-to="Alan Moffat, Gary Gregory">
IOUtils.toByteArray(InputStream) Javadoc does not match code.
@@ -1073,7 +1158,7 @@ The <action> type attribute can be add,update,fix,remove.
</action>
</release>
<!-- The release date is the date RC is cut -->
- <release version="2.8.0" date="2020-09-05" description="Java 8 required.">
+ <release version="2.8.0" date="2020-09-05" description="Java 8 is required.">
<action dev="ggregory" type="add" due-to="Gary Gregory">
Add org.apache.commons.io.input.CircularInputStream.
</action>
@@ -1199,7 +1284,7 @@ The <action> type attribute can be add,update,fix,remove.
</action>
</release>
<!-- The release date is the date RC is cut -->
- <release version="2.7" date="2020-05-24" description="Java 8 required.">
+ <release version="2.7" date="2020-05-24" description="Java 8 is required.">
<action issue="IO-589" dev="sebb" type="fix">
Some tests fail if the base path contains a space.
</action>
diff --git a/src/conf/checkstyle.xml b/src/conf/checkstyle.xml
index d2fc3923..4ff52333 100644
--- a/src/conf/checkstyle.xml
+++ b/src/conf/checkstyle.xml
@@ -34,6 +34,12 @@ limitations under the License.
<module name="AvoidStarImport" />
<module name="RedundantImport" />
<module name="UnusedImports" />
+ <module name="ImportOrder">
+ <property name="option" value="top"/>
+ <property name="groups" value="java,javax,org"/>
+ <property name="ordered" value="true"/>
+ <property name="separated" value="true"/>
+ </module>
<module name="NeedBraces" />
<module name="LeftCurly" />
<module name="JavadocMethod" />
diff --git a/src/main/java/org/apache/commons/io/ByteOrderMark.java b/src/main/java/org/apache/commons/io/ByteOrderMark.java
index 2e4f0305..c5ab57b1 100644
--- a/src/main/java/org/apache/commons/io/ByteOrderMark.java
+++ b/src/main/java/org/apache/commons/io/ByteOrderMark.java
@@ -115,7 +115,14 @@ public class ByteOrderMark implements Serializable {
*/
public static final char UTF_BOM = '\uFEFF';
+ /**
+ * Charset name.
+ */
private final String charsetName;
+
+ /**
+ * Bytes.
+ */
private final int[] bytes;
/**
diff --git a/src/main/java/org/apache/commons/io/CopyUtils.java b/src/main/java/org/apache/commons/io/CopyUtils.java
index b7e7829e..da01a987 100644
--- a/src/main/java/org/apache/commons/io/CopyUtils.java
+++ b/src/main/java/org/apache/commons/io/CopyUtils.java
@@ -103,7 +103,7 @@ import java.nio.charset.Charset;
* method variants to specify the encoding, each row may
* correspond to up to 2 methods.
* <p>
- * Origin of code: Excalibur.
+ * Provenance: Excalibur.
*
* @deprecated Use IOUtils. Will be removed in 3.0.
* Methods renamed to IOUtils.write() or IOUtils.copy().
diff --git a/src/main/java/org/apache/commons/io/EndianUtils.java b/src/main/java/org/apache/commons/io/EndianUtils.java
index acc95319..83c2ce25 100644
--- a/src/main/java/org/apache/commons/io/EndianUtils.java
+++ b/src/main/java/org/apache/commons/io/EndianUtils.java
@@ -34,7 +34,7 @@ import java.io.OutputStream;
* This class helps you solve this incompatibility.
* </p>
* <p>
- * Origin of code: Excalibur
+ * Provenance: Excalibur
* </p>
*
* @see org.apache.commons.io.input.SwappedDataInputStream
diff --git a/src/main/java/org/apache/commons/io/FileUtils.java b/src/main/java/org/apache/commons/io/FileUtils.java
index 807dc37c..80d100f1 100644
--- a/src/main/java/org/apache/commons/io/FileUtils.java
+++ b/src/main/java/org/apache/commons/io/FileUtils.java
@@ -36,6 +36,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.CopyOption;
+import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
@@ -108,7 +109,7 @@ import org.apache.commons.io.function.Uncheck;
* {@link SecurityException} are not documented in the Javadoc.
* </p>
* <p>
- * Origin of code: Excalibur, Alexandria, Commons-Utils
+ * Provenance: Excalibur, Alexandria, Commons-Utils
* </p>
*/
public class FileUtils {
@@ -352,16 +353,13 @@ public class FileUtils {
* This method checks to see if the two files are different lengths or if they point to the same file, before
* resorting to byte-by-byte comparison of the contents.
* </p>
- * <p>
- * Code origin: Avalon
- * </p>
*
* @param file1 the first file
* @param file2 the second file
* @return true if the content of the files are equal or they both don't exist, false otherwise
* @throws IllegalArgumentException when an input is not a file.
* @throws IOException If an I/O error occurs.
- * @see org.apache.commons.io.file.PathUtils#fileContentEquals(Path,Path,java.nio.file.LinkOption[],java.nio.file.OpenOption...)
+ * @see PathUtils#fileContentEquals(Path,Path)
*/
public static boolean contentEquals(final File file1, final File file2) throws IOException {
if (file1 == null && file2 == null) {
@@ -393,9 +391,7 @@ public class FileUtils {
return true;
}
- try (InputStream input1 = Files.newInputStream(file1.toPath()); InputStream input2 = Files.newInputStream(file2.toPath())) {
- return IOUtils.contentEquals(input1, input2);
- }
+ return PathUtils.fileContentEquals(file1.toPath(), file2.toPath());
}
/**
@@ -451,12 +447,12 @@ public class FileUtils {
}
/**
- * Converts a Collection containing java.io.File instances into array
+ * Converts a Collection containing {@link File} instances into array
* representation. This is to account for the difference between
* File.listFiles() and FileUtils.listFiles().
*
- * @param files a Collection containing java.io.File instances
- * @return an array of java.io.File
+ * @param files a Collection containing {@link File} instances
+ * @return an array of {@link File}
*/
public static File[] convertFileCollectionToFileArray(final Collection<File> files) {
return files.toArray(EMPTY_FILE_ARRAY);
@@ -1449,7 +1445,7 @@ public class FileUtils {
/**
* Returns a {@link File} representing the system temporary directory.
*
- * @return the system temporary directory.
+ * @return the system temporary directory as a File
* @since 2.0
*/
public static File getTempDirectory() {
@@ -1459,7 +1455,12 @@ public class FileUtils {
/**
* Returns the path to the system temporary directory.
*
- * @return the path to the system temporary directory.
+ * WARNING: this method relies on the Java system property 'java.io.tmpdir'
+ * which may or may not have a trailing file separator.
+ * This can affect code that uses String processing to manipulate pathnames rather
+ * than the standard libary methods in classes such as {@link java.io.File}
+ *
+ * @return the path to the system temporary directory as a String
* @since 2.0
*/
public static String getTempDirectoryPath() {
@@ -1971,7 +1972,7 @@ public class FileUtils {
* @param dirFilter optional filter to apply when finding subdirectories.
* If this parameter is {@code null}, subdirectories will not be included in the
* search. Use TrueFileFilter.INSTANCE to match all directories.
- * @return an iterator of java.io.File for the matching files
+ * @return an iterator of {@link File} for the matching files
* @see org.apache.commons.io.filefilter.FileFilterUtils
* @see org.apache.commons.io.filefilter.NameFileFilter
* @since 1.2
@@ -1988,14 +1989,14 @@ public class FileUtils {
* </p>
*
* @param directory the directory to search in
- * @param extensions an array of extensions, ex. {"java","xml"}. If this
+ * @param extensions an array of extensions, for example, {"java","xml"}. If this
* parameter is {@code null}, all files are returned.
* @param recursive if true all subdirectories are searched as well
- * @return an iterator of java.io.File with the matching files
+ * @return an iterator of {@link File} with the matching files
* @since 1.2
*/
public static Iterator<File> iterateFiles(final File directory, final String[] extensions, final boolean recursive) {
- return Uncheck.apply(d -> streamFiles(d, recursive, extensions).iterator(), directory);
+ return StreamIterator.iterator(Uncheck.get(() -> streamFiles(directory, recursive, extensions)));
}
/**
@@ -2016,7 +2017,7 @@ public class FileUtils {
* @param dirFilter optional filter to apply when finding subdirectories.
* If this parameter is {@code null}, subdirectories will not be included in the
* search. Use TrueFileFilter.INSTANCE to match all directories.
- * @return an iterator of java.io.File for the matching files
+ * @return an iterator of {@link File} for the matching files
* @see org.apache.commons.io.filefilter.FileFilterUtils
* @see org.apache.commons.io.filefilter.NameFileFilter
* @since 2.2
@@ -2216,28 +2217,30 @@ public class FileUtils {
* @param dirFilter optional filter to apply when finding subdirectories.
* If this parameter is {@code null}, subdirectories will not be included in the
* search. Use {@link TrueFileFilter#INSTANCE} to match all directories.
- * @return a collection of java.io.File with the matching files
+ * @return a collection of {@link File} with the matching files
* @see org.apache.commons.io.filefilter.FileFilterUtils
* @see org.apache.commons.io.filefilter.NameFileFilter
*/
public static Collection<File> listFiles(final File directory, final IOFileFilter fileFilter, final IOFileFilter dirFilter) {
final AccumulatorPathVisitor visitor = Uncheck
.apply(d -> listAccumulate(d, FileFileFilter.INSTANCE.and(fileFilter), dirFilter, FileVisitOption.FOLLOW_LINKS), directory);
- return visitor.getFileList().stream().map(Path::toFile).collect(Collectors.toList());
+ return toList(visitor.getFileList().stream().map(Path::toFile));
}
/**
- * Finds files within a given directory (and optionally its subdirectories)
+ * Lists files within a given directory (and optionally its subdirectories)
* which match an array of extensions.
*
* @param directory the directory to search in
- * @param extensions an array of extensions, ex. {"java","xml"}. If this
+ * @param extensions an array of extensions, for example, {"java","xml"}. If this
* parameter is {@code null}, all files are returned.
* @param recursive if true all subdirectories are searched as well
- * @return a collection of java.io.File with the matching files
+ * @return a collection of {@link File} with the matching files
*/
public static Collection<File> listFiles(final File directory, final String[] extensions, final boolean recursive) {
- return Uncheck.apply(d -> toList(streamFiles(d, recursive, extensions)), directory);
+ try (Stream<File> fileStream = Uncheck.get(() -> streamFiles(directory, recursive, extensions))) {
+ return toList(fileStream);
+ }
}
/**
@@ -2253,7 +2256,7 @@ public class FileUtils {
* @param dirFilter optional filter to apply when finding subdirectories.
* If this parameter is {@code null}, subdirectories will not be included in the
* search. Use TrueFileFilter.INSTANCE to match all directories.
- * @return a collection of java.io.File with the matching files
+ * @return a collection of {@link File} with the matching files
* @see org.apache.commons.io.FileUtils#listFiles
* @see org.apache.commons.io.filefilter.FileFilterUtils
* @see org.apache.commons.io.filefilter.NameFileFilter
@@ -2264,7 +2267,7 @@ public class FileUtils {
directory);
final List<Path> list = visitor.getFileList();
list.addAll(visitor.getDirList());
- return list.stream().map(Path::toFile).collect(Collectors.toList());
+ return toList(list.stream().map(Path::toFile));
}
/**
@@ -2570,9 +2573,8 @@ public class FileUtils {
* @param file the file to read, must not be {@code null}
* @return the file contents, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @since 1.1
*/
public static byte[] readFileToByteArray(final File file) throws IOException {
@@ -2587,9 +2589,8 @@ public class FileUtils {
* @param file the file to read, must not be {@code null}
* @return the file contents, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @since 1.3.1
* @deprecated 2.5 use {@link #readFileToString(File, Charset)} instead (and specify the appropriate encoding)
*/
@@ -2606,9 +2607,8 @@ public class FileUtils {
* @param charsetName the name of the requested charset, {@code null} means platform default
* @return the file contents, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @since 2.3
*/
public static String readFileToString(final File file, final Charset charsetName) throws IOException {
@@ -2622,9 +2622,8 @@ public class FileUtils {
* @param charsetName the name of the requested charset, {@code null} means platform default
* @return the file contents, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io
* .UnsupportedEncodingException} in version 2.2 if the named charset is unavailable.
* @since 2.3
@@ -2640,9 +2639,8 @@ public class FileUtils {
* @param file the file to read, must not be {@code null}
* @return the list of Strings representing each line in the file, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @since 1.3
* @deprecated 2.5 use {@link #readLines(File, Charset)} instead (and specify the appropriate encoding)
*/
@@ -2659,9 +2657,8 @@ public class FileUtils {
* @param charset the charset to use, {@code null} means platform default
* @return the list of Strings representing each line in the file, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @since 2.3
*/
public static List<String> readLines(final File file, final Charset charset) throws IOException {
@@ -2675,9 +2672,8 @@ public class FileUtils {
* @param charsetName the name of the requested charset, {@code null} means platform default
* @return the list of Strings representing each line in the file, never {@code null}
* @throws NullPointerException if file is {@code null}.
- * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
- * other reason cannot be opened for reading.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, including when the file does not exist, is a directory rather than a
+ * regular file, or for some other reason why the file cannot be opened for reading.
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io
* .UnsupportedEncodingException} in version 2.2 if the named charset is unavailable.
* @since 1.1
@@ -2861,9 +2857,8 @@ public class FileUtils {
* {@code false} otherwise
* @throws NullPointerException if sourceFile is {@code null}.
* @throws NullPointerException if targetFile is {@code null}.
- * @throws IOException if setting the last-modified time failed.
*/
- private static boolean setTimes(final File sourceFile, final File targetFile) throws IOException {
+ private static boolean setTimes(final File sourceFile, final File targetFile) {
Objects.requireNonNull(sourceFile, "sourceFile");
Objects.requireNonNull(targetFile, "targetFile");
try {
@@ -2967,14 +2962,17 @@ public class FileUtils {
}
/**
- * Streams over the files in a given directory (and optionally
- * its subdirectories) which match an array of extensions.
+ * Streams over the files in a given directory (and optionally its subdirectories) which match an array of extensions.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a
+ * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
* @param directory the directory to search in
* @param recursive if true all subdirectories are searched as well
- * @param extensions an array of extensions, ex. {"java","xml"}. If this
- * parameter is {@code null}, all files are returned.
- * @return an iterator of java.io.File with the matching files
+ * @param extensions an array of extensions, for example, {"java","xml"}. If this parameter is {@code null}, all files are returned.
+ * @return a Stream of {@link File} for matching files.
* @throws IOException if an I/O error is thrown when accessing the starting file.
* @since 2.9.0
*/
@@ -3006,8 +3004,8 @@ public class FileUtils {
if (url == null || !"file".equalsIgnoreCase(url.getProtocol())) {
return null;
}
- final String filename = url.getFile().replace('/', File.separatorChar);
- return new File(decodeUrl(filename));
+ final String fileName = url.getFile().replace('/', File.separatorChar);
+ return new File(decodeUrl(fileName));
}
/**
@@ -3048,6 +3046,15 @@ public class FileUtils {
return files;
}
+ /**
+ * Consumes all of the given stream.
+ * <p>
+ * When called from a FileTreeWalker, the walker <em>closes</em> the stream because {@link FileTreeWalker#next()} calls {@code top.stream().close()}.
+ * </p>
+ *
+ * @param stream The stream to consume.
+ * @return a new List.
+ */
private static List<File> toList(final Stream<File> stream) {
return stream.collect(Collectors.toList());
}
diff --git a/src/main/java/org/apache/commons/io/FilenameUtils.java b/src/main/java/org/apache/commons/io/FilenameUtils.java
index 09c62f71..049c3a71 100644
--- a/src/main/java/org/apache/commons/io/FilenameUtils.java
+++ b/src/main/java/org/apache/commons/io/FilenameUtils.java
@@ -90,7 +90,7 @@ import java.util.stream.Stream;
* currently running on.
* </p>
* <p>
- * Origin of code: Excalibur, Alexandria, Tomcat, Commons-Utils.
+ * Provenance: Excalibur, Alexandria, Tomcat, Commons-Utils.
* </p>
*
* @since 1.1
@@ -846,7 +846,7 @@ public class FilenameUtils {
* ~user --&gt; 6 --&gt; named user (slash added)
* //server/a/b/c.txt --&gt; 9
* ///a/b/c.txt --&gt; -1 --&gt; error
- * C: --&gt; 0 --&gt; valid filename as only null character and / are reserved characters
+ * C: --&gt; 0 --&gt; valid file name as only null character and / are reserved characters
* </pre>
* <p>
* The output will be the same irrespective of the machine that the code is running on.
diff --git a/src/main/java/org/apache/commons/io/HexDump.java b/src/main/java/org/apache/commons/io/HexDump.java
index d7e5abdc..0a53e3d6 100644
--- a/src/main/java/org/apache/commons/io/HexDump.java
+++ b/src/main/java/org/apache/commons/io/HexDump.java
@@ -31,7 +31,7 @@ import org.apache.commons.io.output.CloseShieldOutputStream;
* in hexadecimal form.
* </p>
* <p>
- * Origin of code: POI.
+ * Provenance: POI.
* </p>
*/
public class HexDump {
diff --git a/src/main/java/org/apache/commons/io/IOIndexedException.java b/src/main/java/org/apache/commons/io/IOIndexedException.java
index 9a85328e..1893509f 100644
--- a/src/main/java/org/apache/commons/io/IOIndexedException.java
+++ b/src/main/java/org/apache/commons/io/IOIndexedException.java
@@ -42,6 +42,9 @@ public class IOIndexedException extends IOException {
return String.format("%s #%,d: %s", name, index, msg);
}
+ /**
+ * Index.
+ */
private final int index;
/**
diff --git a/src/main/java/org/apache/commons/io/IOUtils.java b/src/main/java/org/apache/commons/io/IOUtils.java
index b6b6f137..dfb4c19e 100644
--- a/src/main/java/org/apache/commons/io/IOUtils.java
+++ b/src/main/java/org/apache/commons/io/IOUtils.java
@@ -45,6 +45,7 @@ import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.Selector;
import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Collection;
@@ -118,7 +119,7 @@ import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
* closing streams after use.
* </p>
* <p>
- * Origin of code: Excalibur.
+ * Provenance: Excalibur.
* </p>
*/
public class IOUtils {
@@ -893,7 +894,6 @@ public class IOUtils {
* @param input2 the second stream
* @return true if the content of the streams are equal or they both don't
* exist, false otherwise
- * @throws NullPointerException if either input is null
* @throws IOException if an I/O error occurs
*/
public static boolean contentEquals(final InputStream input1, final InputStream input2) throws IOException {
@@ -3827,28 +3827,36 @@ public class IOUtils {
* Writes the {@link #toString()} value of each item in a collection to
* an {@link OutputStream} line by line, using the specified character
* encoding and the specified line ending.
+ * <p>
+ * UTF-16 is written big-endian with no byte order mark.
+ * For little endian, use UTF-16LE. For a BOM, write it to the stream
+ * before calling this method.
+ * </p>
*
* @param lines the lines to write, null entries produce blank lines
* @param lineEnding the line separator to use, null is system default
* @param output the {@link OutputStream} to write to, not null, not closed
* @param charset the charset to use, null means platform default
- * @throws NullPointerException if the output is null
+ * @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static void writeLines(final Collection<?> lines, String lineEnding, final OutputStream output,
- final Charset charset) throws IOException {
+ Charset charset) throws IOException {
if (lines == null) {
return;
}
if (lineEnding == null) {
lineEnding = System.lineSeparator();
}
- final Charset cs = Charsets.toCharset(charset);
- final byte[] eolBytes = lineEnding.getBytes(cs);
+ if (StandardCharsets.UTF_16.equals(charset)) {
+ // don't write a BOM
+ charset = StandardCharsets.UTF_16BE;
+ }
+ final byte[] eolBytes = lineEnding.getBytes(charset);
for (final Object line : lines) {
if (line != null) {
- write(line.toString(), output, cs);
+ write(line.toString(), output, charset);
}
output.write(eolBytes);
}
diff --git a/src/main/java/org/apache/commons/io/RandomAccessFileMode.java b/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
index 54061588..8b51e439 100644
--- a/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
+++ b/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
@@ -20,6 +20,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.nio.file.Path;
+import java.util.Objects;
/**
* Access modes and factory methods for {@link RandomAccessFile}.
@@ -77,7 +78,7 @@ public enum RandomAccessFileMode {
* @throws FileNotFoundException See {@link RandomAccessFile#RandomAccessFile(File, String)}.
*/
public RandomAccessFile create(final Path file) throws FileNotFoundException {
- return create(file.toFile());
+ return create(Objects.requireNonNull(file.toFile(), "file"));
}
/**
diff --git a/src/main/java/org/apache/commons/io/RandomAccessFiles.java b/src/main/java/org/apache/commons/io/RandomAccessFiles.java
index 2fc071fc..0e0140b6 100644
--- a/src/main/java/org/apache/commons/io/RandomAccessFiles.java
+++ b/src/main/java/org/apache/commons/io/RandomAccessFiles.java
@@ -19,15 +19,55 @@ package org.apache.commons.io;
import java.io.IOException;
import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.util.Objects;
+
+import org.apache.commons.io.channels.FileChannels;
/**
- * Works on RandomAccessFile.
+ * Works with {@link RandomAccessFile}.
*
* @since 2.13.0
*/
public class RandomAccessFiles {
/**
+ * Tests if two RandomAccessFile contents are equal.
+ *
+ * @param raf1 A RandomAccessFile.
+ * @param raf2 Another RandomAccessFile.
+ * @return true if the contents of both RandomAccessFiles are equal, false otherwise.
+ * @throws IOException if an I/O error occurs.
+ * @since 2.15.0
+ */
+ @SuppressWarnings("resource") // See comments
+ public static boolean contentEquals(final RandomAccessFile raf1, final RandomAccessFile raf2) throws IOException {
+ // Short-circuit test
+ if (Objects.equals(raf1, raf2)) {
+ return true;
+ }
+ // Short-circuit test
+ final long length1 = length(raf1);
+ final long length2 = length(raf2);
+ if (length1 != length2) {
+ return false;
+ }
+ if (length1 == 0 && length2 == 0) {
+ return true;
+ }
+ // Dig in and to the work
+ // We do not close FileChannels because that closes the owning RandomAccessFile.
+ // Instead, the caller is assumed to manage the given RandomAccessFile objects.
+ final FileChannel channel1 = raf1.getChannel();
+ final FileChannel channel2 = raf2.getChannel();
+ return FileChannels.contentEquals(channel1, channel2, IOUtils.DEFAULT_BUFFER_SIZE);
+ }
+
+ private static long length(final RandomAccessFile raf) throws IOException {
+ return raf != null ? raf.length() : 0;
+ }
+
+ /**
* Reads a byte array starting at "position" for "length" bytes.
*
* @param input The source RandomAccessFile.
@@ -42,4 +82,17 @@ public class RandomAccessFiles {
return IOUtils.toByteArray(input::read, length);
}
+ /**
+ * Resets the given file to position 0.
+ *
+ * @param raf The RandomAccessFile to reset.
+ * @return The given RandomAccessFile.
+ * @throws IOException If {@code pos} is less than {@code 0} or if an I/O error occurs.
+ * @since 2.15.0
+ */
+ public static RandomAccessFile reset(final RandomAccessFile raf) throws IOException {
+ raf.seek(0);
+ return raf;
+ }
+
}
diff --git a/src/main/java/org/apache/commons/io/StreamIterator.java b/src/main/java/org/apache/commons/io/StreamIterator.java
index 3a321681..23465657 100644
--- a/src/main/java/org/apache/commons/io/StreamIterator.java
+++ b/src/main/java/org/apache/commons/io/StreamIterator.java
@@ -17,42 +17,55 @@
package org.apache.commons.io;
-import java.io.Closeable;
import java.util.Iterator;
import java.util.Objects;
import java.util.stream.Stream;
/**
- * Wraps and presents a stream as a closable iterator resource that automatically closes itself when reaching the end
- * of stream.
+ * Wraps and presents a {@link Stream} as a {@link AutoCloseable} {@link Iterator} resource that automatically closes itself when reaching the end of stream.
*
- * @param <E> The stream and iterator type.
- * @since 2.9.0
+ * <h2>Warning</h2>
+ * <p>
+ * In order to close the stream, the call site MUST either close the stream it allocated OR call this iterator until the end.
+ * </p>
+ *
+ * @param <E> The {@link Stream} and {@link Iterator} type.
+ * @since 2.15.0
*/
-final class StreamIterator<E> implements Iterator<E>, Closeable {
+public final class StreamIterator<E> implements Iterator<E>, AutoCloseable {
/**
- * Wraps and presents a stream as a closable resource that automatically closes itself when reaching the end of
- * stream.
- * <h2>Warning</h2>
+ * Wraps and presents a stream as a closable resource that automatically closes itself when reaching the end of stream.
+ * <p>
+ * <b>Warning</b>
+ * </p>
* <p>
- * In order to close the stream, the call site MUST either close the stream it allocated OR call the iterator until
- * the end.
+ * In order to close the stream, the call site MUST either close the stream it allocated OR call this iterator until the end.
* </p>
*
- * @param <T> The stream and iterator type.
+ * @param <T> The stream and iterator type.
* @param stream The stream iterate.
* @return A new iterator.
*/
- @SuppressWarnings("resource") // Caller MUST close or iterate to the end.
- public static <T> Iterator<T> iterator(final Stream<T> stream) {
- return new StreamIterator<>(stream).iterator;
+ public static <T> StreamIterator<T> iterator(final Stream<T> stream) {
+ return new StreamIterator<>(stream);
}
+ /**
+ * The given stream's Iterator.
+ */
private final Iterator<E> iterator;
+ /**
+ * The given stream.
+ */
private final Stream<E> stream;
+ /**
+ * Whether {@link #close()} has been called.
+ */
+ private boolean closed;
+
private StreamIterator(final Stream<E> stream) {
this.stream = Objects.requireNonNull(stream, "stream");
this.iterator = stream.iterator();
@@ -63,11 +76,16 @@ final class StreamIterator<E> implements Iterator<E>, Closeable {
*/
@Override
public void close() {
+ closed = true;
stream.close();
}
@Override
public boolean hasNext() {
+ if (closed) {
+ // Calling Iterator#hasNext() on a closed java.nio.file.FileTreeIterator causes an IllegalStateException.
+ return false;
+ }
final boolean hasNext = iterator.hasNext();
if (!hasNext) {
close();
diff --git a/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java b/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
index d94638ac..e0f9ba66 100644
--- a/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
+++ b/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
@@ -154,6 +154,11 @@ public abstract class AbstractStreamBuilder<T, B extends AbstractStreamBuilder<T
return checkOrigin().getInputStream(getOpenOptions());
}
+ /**
+ * Gets the OpenOption.
+ *
+ * @return the OpenOption.
+ */
protected OpenOption[] getOpenOptions() {
return openOptions;
}
diff --git a/src/main/java/org/apache/commons/io/channels/FileChannels.java b/src/main/java/org/apache/commons/io/channels/FileChannels.java
new file mode 100644
index 00000000..468c85b4
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FileChannels.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.io.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.Objects;
+
+import org.apache.commons.io.IOUtils;
+
+/**
+ * Works with {@link FileChannel}.
+ *
+ * @since 2.15.0
+ */
+public final class FileChannels {
+
+ /**
+ * Tests if two RandomAccessFiles contents are equal.
+ *
+ * @param channel1 A FileChannel.
+ * @param channel2 Another FileChannel.
+ * @param byteBufferSize The two internal buffer capacities, in bytes.
+ * @return true if the contents of both RandomAccessFiles are equal, false otherwise.
+ * @throws IOException if an I/O error occurs.
+ */
+ public static boolean contentEquals(final FileChannel channel1, final FileChannel channel2, final int byteBufferSize) throws IOException {
+ // Short-circuit test
+ if (Objects.equals(channel1, channel2)) {
+ return true;
+ }
+ // Short-circuit test
+ final long size1 = size(channel1);
+ final long size2 = size(channel2);
+ if (size1 != size2) {
+ return false;
+ }
+ if (size1 == 0 && size2 == 0) {
+ return true;
+ }
+ // Dig in and do the work
+ final ByteBuffer byteBuffer1 = ByteBuffer.allocateDirect(byteBufferSize);
+ final ByteBuffer byteBuffer2 = ByteBuffer.allocateDirect(byteBufferSize);
+ while (true) {
+ final int read1 = channel1.read(byteBuffer1);
+ final int read2 = channel2.read(byteBuffer2);
+ if (read1 == IOUtils.EOF && read2 == IOUtils.EOF) {
+ return byteBuffer1.equals(byteBuffer2);
+ }
+ if (read1 != read2) {
+ return false;
+ }
+ if (!byteBuffer1.equals(byteBuffer2)) {
+ return false;
+ }
+ byteBuffer1.clear();
+ byteBuffer2.clear();
+ }
+ }
+
+ private static long size(final FileChannel channel) throws IOException {
+ return channel != null ? channel.size() : 0;
+ }
+
+ /**
+ * Don't instantiate.
+ */
+ private FileChannels() {
+ // no-op
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/channels/package-info.java b/src/main/java/org/apache/commons/io/channels/package-info.java
new file mode 100644
index 00000000..51a7ca28
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides classes to work with {@link java.nio.channels}.
+ *
+ * @since 2.15.0
+ */
+package org.apache.commons.io.channels;
diff --git a/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java b/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
index 0f57a833..d50f3252 100644
--- a/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
@@ -19,6 +19,7 @@ package org.apache.commons.io.comparator;
import java.io.File;
import java.io.Serializable;
import java.util.Comparator;
+import java.util.function.IntFunction;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@@ -48,6 +49,9 @@ public class CompositeFileComparator extends AbstractFileComparator implements S
private static final Comparator<?>[] EMPTY_COMPARATOR_ARRAY = {};
private static final long serialVersionUID = -2224170307287243428L;
+ /**
+ * Delegates.
+ */
private final Comparator<File>[] delegates;
/**
@@ -65,7 +69,8 @@ public class CompositeFileComparator extends AbstractFileComparator implements S
* @param delegates The delegate file comparators
*/
public CompositeFileComparator(final Iterable<Comparator<File>> delegates) {
- this.delegates = delegates == null ? emptyArray() : StreamSupport.stream(delegates.spliterator(), false).toArray(Comparator[]::new);
+ this.delegates = delegates == null ? emptyArray()
+ : StreamSupport.stream(delegates.spliterator(), false).toArray((IntFunction<Comparator<File>[]>) Comparator[]::new);
}
/**
diff --git a/src/main/java/org/apache/commons/io/file/FilesUncheck.java b/src/main/java/org/apache/commons/io/file/FilesUncheck.java
index 02a1febb..02688cac 100644
--- a/src/main/java/org/apache/commons/io/file/FilesUncheck.java
+++ b/src/main/java/org/apache/commons/io/file/FilesUncheck.java
@@ -22,6 +22,7 @@ import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.Reader;
import java.io.UncheckedIOException;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.Charset;
@@ -244,6 +245,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#find(Path, int, BiPredicate, FileVisitOption...)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link DirectoryStream}. When you require timely disposal of file system resources, use a {@code try}-with-resources
+ * block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed.
+ * </p>
*
* @param start See delegate.
* @param maxDepth See delegate.
@@ -348,6 +353,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#lines(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link Reader}. When you require timely disposal of file system resources, use a {@code try}-with-resources block to
+ * ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed.
+ * </p>
*
* @param path See delegate.
* @return See delegate.
@@ -359,6 +368,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#lines(Path, Charset)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link Reader}. When you require timely disposal of file system resources, use a {@code try}-with-resources block to
+ * ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed.
+ * </p>
*
* @param path See delegate.
* @param cs See delegate.
@@ -371,6 +384,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#list(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link DirectoryStream}. When you require timely disposal of file system resources, use a {@code try}-with-resources
+ * block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed.
+ * </p>
*
* @param dir See delegate.
* @return See delegate.
@@ -474,8 +491,11 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#newDirectoryStream(Path)} throwing {@link UncheckedIOException} instead of
- * {@link IOException}.
+ * Delegates to {@link Files#newDirectoryStream(Path)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * If you don't use the try-with-resources construct, then you must call the stream's {@link Stream#close()} method after iteration is complete to free any
+ * resources held for the open directory.
+ * </p>
*
* @param dir See delegate.
* @return See delegate.
@@ -485,10 +505,14 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#newDirectoryStream(Path, java.nio.file.DirectoryStream.Filter)} throwing
- * {@link UncheckedIOException} instead of {@link IOException}.
+ * Delegates to {@link Files#newDirectoryStream(Path, java.nio.file.DirectoryStream.Filter)} throwing {@link UncheckedIOException} instead of
+ * {@link IOException}.
+ * <p>
+ * If you don't use the try-with-resources construct, then you must call the stream's {@link Stream#close()} method after iteration is complete to free any
+ * resources held for the open directory.
+ * </p>
*
- * @param dir See delegate.
+ * @param dir See delegate.
* @param filter See delegate.
* @return See delegate.
*/
@@ -499,6 +523,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#newDirectoryStream(Path, String)} throwing {@link UncheckedIOException} instead of
* {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link DirectoryStream}. When you require timely disposal of file system resources, use a {@code try}-with-resources
+ * block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed.
+ * </p>
*
* @param dir See delegate.
* @param glob See delegate.
@@ -674,10 +702,14 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#walk(Path, FileVisitOption...)} throwing {@link UncheckedIOException} instead of
- * {@link IOException}.
+ * Delegates to {@link Files#walk(Path, FileVisitOption...)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a
+ * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
- * @param start See delegate.
+ * @param start See delegate.
* @param options See delegate.
* @return See delegate.
*/
@@ -686,12 +718,16 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#walk(Path, int, FileVisitOption...)} throwing {@link UncheckedIOException} instead of
- * {@link IOException}.
+ * Delegates to {@link Files#walk(Path, int, FileVisitOption...)} throwing {@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a
+ * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
- * @param start See delegate.
+ * @param start See delegate.
* @param maxDepth See delegate.
- * @param options See delegate.
+ * @param options See delegate.
* @return See delegate.
*/
public static Stream<Path> walk(final Path start, final int maxDepth, final FileVisitOption... options) {
diff --git a/src/main/java/org/apache/commons/io/file/PathUtils.java b/src/main/java/org/apache/commons/io/file/PathUtils.java
index 56b2a05c..d85fdb67 100644
--- a/src/main/java/org/apache/commons/io/file/PathUtils.java
+++ b/src/main/java/org/apache/commons/io/file/PathUtils.java
@@ -21,7 +21,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.UncheckedIOException;
+import java.io.RandomAccessFile;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
@@ -70,14 +70,14 @@ import java.util.stream.Stream;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.RandomAccessFileMode;
+import org.apache.commons.io.RandomAccessFiles;
import org.apache.commons.io.ThreadUtils;
import org.apache.commons.io.file.Counters.PathCounters;
import org.apache.commons.io.file.attribute.FileTimes;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.function.IOFunction;
import org.apache.commons.io.function.IOSupplier;
-import org.apache.commons.io.function.Uncheck;
/**
* NIO Path utilities.
@@ -90,7 +90,7 @@ public final class PathUtils {
* Private worker/holder that computes and tracks relative path names and their equality. We reuse the sorted relative
* lists when comparing directories.
*/
- private static class RelativeSortedPaths {
+ private static final class RelativeSortedPaths {
final boolean equals;
// final List<Path> relativeDirList1; // might need later?
@@ -365,7 +365,7 @@ public final class PathUtils {
* Creates the parent directories for the given {@code path}.
* <p>
* If the parent directory already exists, then return it.
- * <p>
+ * </p>
*
* @param path The path to a file (or directory).
* @param attrs An optional list of file attributes to set atomically when creating the directories.
@@ -381,7 +381,7 @@ public final class PathUtils {
* Creates the parent directories for the given {@code path}.
* <p>
* If the parent directory already exists, then return it.
- * <p>
+ * </p>
*
* @param path The path to a file (or directory).
* @param linkOption A {@link LinkOption} or null.
@@ -719,20 +719,20 @@ public final class PathUtils {
/**
* Compares the file contents of two Paths to determine if they are equal or not.
* <p>
- * File content is accessed through {@link Files#newInputStream(Path,OpenOption...)}.
+ * File content is accessed through {@link RandomAccessFileMode#create(Path)}.
* </p>
*
* @param path1 the first stream.
* @param path2 the second stream.
* @param linkOptions options specifying how files are followed.
- * @param openOptions options specifying how files are opened.
+ * @param openOptions ignored.
* @return true if the content of the streams are equal or they both don't exist, false otherwise.
* @throws NullPointerException if openOptions is null.
* @throws IOException if an I/O error occurs.
* @see org.apache.commons.io.FileUtils#contentEquals(java.io.File, java.io.File)
*/
public static boolean fileContentEquals(final Path path1, final Path path2, final LinkOption[] linkOptions, final OpenOption[] openOptions)
- throws IOException {
+ throws IOException {
if (path1 == null && path2 == null) {
return true;
}
@@ -766,9 +766,9 @@ public final class PathUtils {
// same file
return true;
}
- try (InputStream inputStream1 = Files.newInputStream(nPath1, openOptions);
- InputStream inputStream2 = Files.newInputStream(nPath2, openOptions)) {
- return IOUtils.contentEquals(inputStream1, inputStream2);
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(path1.toRealPath(linkOptions));
+ RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(path2.toRealPath(linkOptions))) {
+ return RandomAccessFiles.contentEquals(raf1, raf2);
}
}
@@ -1182,8 +1182,12 @@ public final class PathUtils {
/**
* Creates a new DirectoryStream for Paths rooted at the given directory.
+ * <p>
+ * If you don't use the try-with-resources construct, then you must call the stream's {@link Stream#close()} method after iteration is complete to free any
+ * resources held for the open directory.
+ * </p>
*
- * @param dir the path to the directory to stream.
+ * @param dir the path to the directory to stream.
* @param pathFilter the directory stream filter.
* @return a new instance.
* @throws IOException if an I/O error occurs.
@@ -1243,21 +1247,20 @@ public final class PathUtils {
}
/**
- * Reads the BasicFileAttributes from the given path. Returns null instead of throwing
- * {@link UnsupportedOperationException}. Throws {@link Uncheck} instead of {@link IOException}.
+ * Reads the BasicFileAttributes from the given path. Returns null if the attributes can't be read.
*
* @param <A> The {@link BasicFileAttributes} type
* @param path The Path to test.
* @param type the {@link Class} of the file attributes required to read.
* @param options options indicating how to handle symbolic links.
- * @return the file attributes.
+ * @return the file attributes or null if the attributes can't be read.
* @see Files#readAttributes(Path, Class, LinkOption...)
* @since 2.12.0
*/
public static <A extends BasicFileAttributes> A readAttributes(final Path path, final Class<A> type, final LinkOption... options) {
try {
- return path == null ? null : Uncheck.apply(Files::readAttributes, path, type, options);
- } catch (final UnsupportedOperationException e) {
+ return path == null ? null : Files.readAttributes(path, type, options);
+ } catch (final UnsupportedOperationException | IOException e) {
// For example, on Windows.
return null;
}
@@ -1270,16 +1273,14 @@ public final class PathUtils {
* @return the path attributes.
* @throws IOException if an I/O error occurs.
* @since 2.9.0
- * @deprecated Will be removed in 3.0.0 in favor of {@link #readBasicFileAttributes(Path, LinkOption...)}.
*/
- @Deprecated
public static BasicFileAttributes readBasicFileAttributes(final Path path) throws IOException {
return Files.readAttributes(path, BasicFileAttributes.class);
}
/**
- * Reads the BasicFileAttributes from the given path. Returns null instead of throwing
- * {@link UnsupportedOperationException}.
+ * Reads the BasicFileAttributes from the given path. Returns null if the attributes
+ * can't be read.
*
* @param path the path to read.
* @param options options indicating how to handle symbolic links.
@@ -1291,12 +1292,11 @@ public final class PathUtils {
}
/**
- * Reads the BasicFileAttributes from the given path. Returns null instead of throwing
- * {@link UnsupportedOperationException}.
+ * Reads the BasicFileAttributes from the given path. Returns null if the attributes
+ * can't be read.
*
* @param path the path to read.
* @return the path attributes.
- * @throws UncheckedIOException if an I/O error occurs
* @since 2.9.0
* @deprecated Use {@link #readBasicFileAttributes(Path, LinkOption...)}.
*/
@@ -1306,8 +1306,8 @@ public final class PathUtils {
}
/**
- * Reads the DosFileAttributes from the given path. Returns null instead of throwing
- * {@link UnsupportedOperationException}.
+ * Reads the DosFileAttributes from the given path. Returns null if the attributes
+ * can't be read.
*
* @param path the path to read.
* @param options options indicating how to handle symbolic links.
@@ -1323,8 +1323,8 @@ public final class PathUtils {
}
/**
- * Reads the PosixFileAttributes or DosFileAttributes from the given path. Returns null instead of throwing
- * {@link UnsupportedOperationException}.
+ * Reads the PosixFileAttributes or DosFileAttributes from the given path. Returns null if the attributes
+ * can't be read.
*
* @param path The Path to read.
* @param options options indicating how to handle symbolic links.
@@ -1751,6 +1751,11 @@ public final class PathUtils {
/**
* Returns a stream of filtered paths.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link DirectoryStream}s. When you require timely disposal of file system resources, use a
+ * {@code try}-with-resources block to ensure invocation of the stream's {@link Stream#close()} method after the stream operations are completed. Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
* @param start the start path
* @param pathFilter the path filter
@@ -1801,7 +1806,7 @@ public final class PathUtils {
}
/**
- * Does allow to instantiate.
+ * Prevents instantiation.
*/
private PathUtils() {
// do not instantiate.
diff --git a/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java
index 14c99566..ee2bb02b 100644
--- a/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java
@@ -39,7 +39,7 @@ public class DelegateFileFilter extends AbstractFileFilter implements Serializab
/** The File filter */
private final FileFilter fileFilter;
/** The Filename filter */
- private final FilenameFilter filenameFilter;
+ private final FilenameFilter fileNameFilter;
/**
* Constructs a delegate file filter around an existing FileFilter.
@@ -49,17 +49,17 @@ public class DelegateFileFilter extends AbstractFileFilter implements Serializab
public DelegateFileFilter(final FileFilter fileFilter) {
Objects.requireNonNull(fileFilter, "filter");
this.fileFilter = fileFilter;
- this.filenameFilter = null;
+ this.fileNameFilter = null;
}
/**
* Constructs a delegate file filter around an existing FilenameFilter.
*
- * @param filenameFilter the filter to decorate
+ * @param fileNameFilter the filter to decorate
*/
- public DelegateFileFilter(final FilenameFilter filenameFilter) {
- Objects.requireNonNull(filenameFilter, "filter");
- this.filenameFilter = filenameFilter;
+ public DelegateFileFilter(final FilenameFilter fileNameFilter) {
+ Objects.requireNonNull(fileNameFilter, "filter");
+ this.fileNameFilter = fileNameFilter;
this.fileFilter = null;
}
@@ -86,8 +86,8 @@ public class DelegateFileFilter extends AbstractFileFilter implements Serializab
*/
@Override
public boolean accept(final File dir, final String name) {
- if (filenameFilter != null) {
- return filenameFilter.accept(dir, name);
+ if (fileNameFilter != null) {
+ return fileNameFilter.accept(dir, name);
}
return super.accept(dir, name);
}
@@ -99,7 +99,7 @@ public class DelegateFileFilter extends AbstractFileFilter implements Serializab
*/
@Override
public String toString() {
- final String delegate = fileFilter != null ? fileFilter.toString() : filenameFilter.toString();
+ final String delegate = fileFilter != null ? fileFilter.toString() : fileNameFilter.toString();
return super.toString() + "(" + delegate + ")";
}
diff --git a/src/main/java/org/apache/commons/io/filefilter/package-info.java b/src/main/java/org/apache/commons/io/filefilter/package-info.java
index a374fb0d..3bf71238 100644
--- a/src/main/java/org/apache/commons/io/filefilter/package-info.java
+++ b/src/main/java/org/apache/commons/io/filefilter/package-info.java
@@ -40,7 +40,7 @@
* </tr>
* <tr>
* <td><a href="NameFileFilter.html">NameFileFilter</a></td>
- * <td>Filter based on a filename</td>
+ * <td>Filter based on a file name</td>
* </tr>
* <tr>
* <td><a href="WildcardFileFilter.html">WildcardFileFilter</a></td>
diff --git a/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java b/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
index fc334e96..72b1b1e8 100644
--- a/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
+++ b/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
@@ -38,7 +38,7 @@ class ByteBufferCleaner {
void clean(ByteBuffer buffer) throws ReflectiveOperationException;
}
- private static class Java8Cleaner implements Cleaner {
+ private static final class Java8Cleaner implements Cleaner {
private final Method cleanerMethod;
private final Method cleanMethod;
@@ -57,7 +57,7 @@ class ByteBufferCleaner {
}
}
- private static class Java9Cleaner implements Cleaner {
+ private static final class Java9Cleaner implements Cleaner {
private final Object theUnsafe;
private final Method invokeCleaner;
diff --git a/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java b/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
index 89114be9..3d03f8ce 100644
--- a/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
@@ -87,6 +87,9 @@ public final class MemoryMappedFileInputStream extends InputStream {
*/
public static class Builder extends AbstractStreamBuilder<MemoryMappedFileInputStream, Builder> {
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
setBufferSizeDefault(DEFAULT_BUFFER_SIZE);
setBufferSize(DEFAULT_BUFFER_SIZE);
diff --git a/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java b/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
index 7aed4185..97d7ff59 100644
--- a/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
@@ -21,12 +21,13 @@ import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
+import java.util.Objects;
import org.apache.commons.io.build.AbstractStreamBuilder;
/**
* This class is an example for using an {@link ObservableInputStream}. It creates its own {@link org.apache.commons.io.input.ObservableInputStream.Observer},
- * which calculates a checksum using a MessageDigest, for example an MD5 sum.
+ * which calculates a checksum using a {@link MessageDigest}, for example, a SHA-512 sum.
* <p>
* To build an instance, see {@link Builder}.
* </p>
@@ -35,12 +36,11 @@ import org.apache.commons.io.build.AbstractStreamBuilder;
* Cryptography Architecture Standard Algorithm Name Documentation</a> for information about standard algorithm names.
* </p>
* <p>
- * <em>Note</em>: Neither {@link ObservableInputStream}, nor {@link MessageDigest}, are thread safe. So is {@link MessageDigestCalculatingInputStream}.
- * </p>
- * <p>
- * TODO Rename to MessageDigestInputStream in 3.0.
+ * <em>Note</em>: Neither {@link ObservableInputStream}, nor {@link MessageDigest}, are thread safe, so is {@link MessageDigestCalculatingInputStream}.
* </p>
+ * @deprecated Use {@link MessageDigestInputStream}.
*/
+@Deprecated
public class MessageDigestCalculatingInputStream extends ObservableInputStream {
/**
@@ -61,6 +61,9 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
private MessageDigest messageDigest;
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
try {
this.messageDigest = getDefaultMessageDigest();
@@ -92,6 +95,9 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
/**
* Sets the message digest.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
*
* @param messageDigest the message digest.
*/
@@ -101,6 +107,9 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
/**
* Sets the name of the name of the message digest algorithm.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
*
* @param algorithm the name of the algorithm. See the MessageDigest section in the
* <a href= "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> Java Cryptography
@@ -123,9 +132,10 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
* Constructs an MessageDigestMaintainingObserver for the given MessageDigest.
*
* @param messageDigest the message digest to use
+ * @throws NullPointerException if messageDigest is null.
*/
public MessageDigestMaintainingObserver(final MessageDigest messageDigest) {
- this.messageDigest = messageDigest;
+ this.messageDigest = Objects.requireNonNull(messageDigest, "messageDigest");
}
@Override
@@ -187,9 +197,13 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
/**
* Constructs a new instance, which calculates a signature on the given stream, using the given {@link MessageDigest}.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
*
* @param inputStream the stream to calculate the message digest for
* @param messageDigest the message digest to use
+ * @throws NullPointerException if messageDigest is null.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
@@ -200,6 +214,9 @@ public class MessageDigestCalculatingInputStream extends ObservableInputStream {
/**
* Constructs a new instance, which calculates a signature on the given stream, using a {@link MessageDigest} with the given algorithm.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
*
* @param inputStream the stream to calculate the message digest for
* @param algorithm the name of the algorithm requested. See the MessageDigest section in the
diff --git a/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java b/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java
new file mode 100644
index 00000000..d822256b
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
+
+import org.apache.commons.io.build.AbstractStreamBuilder;
+
+/**
+ * This class is an example for using an {@link ObservableInputStream}. It creates its own {@link org.apache.commons.io.input.ObservableInputStream.Observer},
+ * which calculates a checksum using a {@link MessageDigest}, for example, a SHA-512 sum.
+ * <p>
+ * To build an instance, see {@link Builder}.
+ * </p>
+ * <p>
+ * See the MessageDigest section in the <a href= "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> Java
+ * Cryptography Architecture Standard Algorithm Name Documentation</a> for information about standard algorithm names.
+ * </p>
+ * <p>
+ * You must specify a message digest algorithm name or instance.
+ * </p>
+ * <p>
+ * <em>Note</em>: Neither {@link ObservableInputStream}, nor {@link MessageDigest}, are thread safe, so is {@link MessageDigestInputStream}.
+ * </p>
+ *
+ * @since 2.15.0
+ */
+public final class MessageDigestInputStream extends ObservableInputStream {
+
+ /**
+ * Builds new {@link MessageDigestInputStream} instances.
+ * <p>
+ * For example:
+ * </p>
+ * <pre>{@code
+ * MessageDigestInputStream s = MessageDigestInputStream.builder()
+ * .setPath(path)
+ * .setMessageDigest("SHA-512")
+ * .get();}
+ * </pre>
+ * <p>
+ * You must specify a message digest algorithm name or instance.
+ * </p>
+ */
+ public static class Builder extends AbstractStreamBuilder<MessageDigestInputStream, Builder> {
+
+ private MessageDigest messageDigest;
+
+ /**
+ * Constructs a new Builder.
+ */
+ public Builder() {
+ // empty
+ }
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspects InputStream, OpenOption[], and MessageDigest.
+ * </p>
+ * <p>
+ * You must provide an origin that can be converted to an InputStream by this builder, otherwise, this call will throw an
+ * {@link UnsupportedOperationException}.
+ * </p>
+ *
+ * @return a new instance.
+ * @throws UnsupportedOperationException if the origin cannot provide an InputStream.
+ * @see #getInputStream()
+ */
+ @SuppressWarnings("resource")
+ @Override
+ public MessageDigestInputStream get() throws IOException {
+ return new MessageDigestInputStream(getInputStream(), messageDigest);
+ }
+
+ /**
+ * Sets the message digest.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
+ *
+ * @param messageDigest the message digest.
+ * @return this
+ */
+ public Builder setMessageDigest(final MessageDigest messageDigest) {
+ this.messageDigest = messageDigest;
+ return this;
+ }
+
+ /**
+ * Sets the name of the name of the message digest algorithm.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
+ *
+ * @param algorithm the name of the algorithm. See the MessageDigest section in the
+ * <a href= "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"> Java Cryptography
+ * Architecture Standard Algorithm Name Documentation</a> for information about standard algorithm names.
+ * @return this
+ * @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation for the specified algorithm.
+ */
+ public Builder setMessageDigest(final String algorithm) throws NoSuchAlgorithmException {
+ this.messageDigest = MessageDigest.getInstance(algorithm);
+ return this;
+ }
+
+ }
+
+ /**
+ * Maintains the message digest.
+ */
+ public static class MessageDigestMaintainingObserver extends Observer {
+
+ private final MessageDigest messageDigest;
+
+ /**
+ * Constructs an MessageDigestMaintainingObserver for the given MessageDigest.
+ *
+ * @param messageDigest the message digest to use
+ * @throws NullPointerException if messageDigest is null.
+ */
+ public MessageDigestMaintainingObserver(final MessageDigest messageDigest) {
+ this.messageDigest = Objects.requireNonNull(messageDigest, "messageDigest");
+ }
+
+ @Override
+ public void data(final byte[] input, final int offset, final int length) throws IOException {
+ messageDigest.update(input, offset, length);
+ }
+
+ @Override
+ public void data(final int input) throws IOException {
+ messageDigest.update((byte) input);
+ }
+ }
+
+ /**
+ * Constructs a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ private final MessageDigest messageDigest;
+
+ /**
+ * Constructs a new instance, which calculates a signature on the given stream, using the given {@link MessageDigest}.
+ * <p>
+ * The MD5 cryptographic algorithm is weak and should not be used.
+ * </p>
+ *
+ * @param inputStream the stream to calculate the message digest for
+ * @param messageDigest the message digest to use
+ * @throws NullPointerException if messageDigest is null.
+ */
+ private MessageDigestInputStream(final InputStream inputStream, final MessageDigest messageDigest) {
+ super(inputStream, new MessageDigestMaintainingObserver(messageDigest));
+ this.messageDigest = messageDigest;
+ }
+
+ /**
+ * Gets the {@link MessageDigest}, which is being used for generating the checksum.
+ * <p>
+ * <em>Note</em>: The checksum will only reflect the data, which has been read so far. This is probably not, what you expect. Make sure, that the complete
+ * data has been read, if that is what you want. The easiest way to do so is by invoking {@link #consume()}.
+ * </p>
+ *
+ * @return the message digest used
+ */
+ public MessageDigest getMessageDigest() {
+ return messageDigest;
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/input/ObservableInputStream.java b/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
index ee080f06..a97702fb 100644
--- a/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
@@ -39,7 +39,7 @@ import org.apache.commons.io.function.IOConsumer;
* be used.
* </p>
*
- * @see MessageDigestCalculatingInputStream
+ * @see MessageDigestInputStream
*/
public class ObservableInputStream extends ProxyInputStream {
diff --git a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
index 04c9cf91..7ef620fe 100644
--- a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
+++ b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
@@ -66,6 +66,9 @@ public class ReversedLinesFileReader implements Closeable {
*/
public static class Builder extends AbstractStreamBuilder<ReversedLinesFileReader, Builder> {
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
setBufferSizeDefault(DEFAULT_BLOCK_SIZE);
setBufferSize(DEFAULT_BLOCK_SIZE);
diff --git a/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java b/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java
index 31600f58..9239b520 100644
--- a/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java
@@ -29,7 +29,7 @@ import org.apache.commons.io.EndianUtils;
* DataInput for systems relying on little endian data formats. When read, values will be changed from little endian to
* big endian formats for internal usage.
* <p>
- * <b>Origin of code: </b>Avalon Excalibur (IO)
+ * Provenance: Avalon Excalibur (IO)
* </p>
*/
public class SwappedDataInputStream extends ProxyInputStream implements DataInput {
diff --git a/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.java b/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.java
index ffd456df..b33a1187 100644
--- a/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStream.java
@@ -105,7 +105,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
protected volatile byte[] buffer;
/**
- * The total number of bytes inside the byte array {@code buf}.
+ * The total number of bytes inside the byte array {@code buffer}.
*/
protected int count;
@@ -120,7 +120,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
protected int markPos = IOUtils.EOF;
/**
- * The current position within the byte array {@code buf}.
+ * The current position within the byte array {@code buffer}.
*/
protected int pos;
@@ -190,8 +190,8 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
}
final byte[] newbuf = new byte[newLength];
System.arraycopy(localBuf, 0, newbuf, 0, localBuf.length);
- // Reassign buf, which will invalidate any local references
- // FIXME: what if buf was null?
+ // Reassign buffer, which will invalidate any local references
+ // FIXME: what if buffer was null?
localBuf = buffer = newbuf;
} else if (markPos > 0) {
System.arraycopy(localBuf, markPos, localBuf, 0, localBuf.length - markPos);
@@ -276,7 +276,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
* set and the requested number of bytes is larger than the receiver's buffer size, this implementation bypasses the buffer and simply places the results
* directly into {@code buffer}.
*
- * @param buffer the byte array in which to store the bytes read.
+ * @param dest the byte array in which to store the bytes read.
* @param offset the initial position in {@code buffer} to store the bytes read from this stream.
* @param length the maximum number of bytes to store in {@code buffer}.
* @return the number of bytes actually read or -1 if end of stream.
@@ -284,7 +284,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
* @throws IOException if the stream is already closed or another IOException occurs.
*/
@Override
- public int read(final byte[] buffer, int offset, final int length) throws IOException {
+ public int read(final byte[] dest, int offset, final int length) throws IOException {
// Use local ref since buf may be invalidated by an unsynchronized
// close()
byte[] localBuf = buffer;
@@ -292,7 +292,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
throw new IOException("Stream is closed");
}
// avoid int overflow
- if (offset > buffer.length - length || offset < 0 || length < 0) {
+ if (offset > dest.length - length || offset < 0 || length < 0) {
throw new IndexOutOfBoundsException();
}
if (length == 0) {
@@ -307,7 +307,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
if (pos < count) {
/* There are bytes available in the buffer. */
final int copylength = count - pos >= length ? length : count - pos;
- System.arraycopy(localBuf, pos, buffer, offset, copylength);
+ System.arraycopy(localBuf, pos, dest, offset, copylength);
pos += copylength;
if (copylength == length || localIn.available() == 0) {
return copylength;
@@ -324,7 +324,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
* If we're not marked and the required size is greater than the buffer, simply read the bytes directly bypassing the buffer.
*/
if (markPos == IOUtils.EOF && required >= localBuf.length) {
- read = localIn.read(buffer, offset, required);
+ read = localIn.read(dest, offset, required);
if (read == IOUtils.EOF) {
return required == length ? IOUtils.EOF : length - required;
}
@@ -341,7 +341,7 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
}
read = count - pos >= required ? required : count - pos;
- System.arraycopy(localBuf, pos, buffer, offset, read);
+ System.arraycopy(localBuf, pos, dest, offset, read);
pos += read;
}
required -= read;
@@ -397,10 +397,12 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
}
if (count - pos >= amount) {
- pos += amount;
+ // (int count - int pos) here is always an int so amount is also in the int range if the above test is true.
+ // We can safely cast to int and avoid static analysis warnings.
+ pos += (int) amount;
return amount;
}
- long read = count - pos;
+ int read = count - pos;
pos = count;
if (markPos != IOUtils.EOF && amount <= markLimit) {
@@ -408,7 +410,9 @@ public final class UnsynchronizedBufferedInputStream extends UnsynchronizedFilte
return read;
}
if (count - pos >= amount - read) {
- pos += amount - read;
+ // (int count - int pos) here is always an int so (amount - read) is also in the int range if the above test is true.
+ // We can safely cast to int and avoid static analysis warnings.
+ pos += (int) amount - read;
return amount;
}
// Couldn't get all the bytes, skip what we read
diff --git a/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java b/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java
index a4fc696c..f10c1120 100644
--- a/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.java
@@ -106,6 +106,12 @@ public class UnsynchronizedByteArrayInputStream extends InputStream {
return super.setByteArray(origin);
}
+ /**
+ * Sets the length.
+ *
+ * @param length Must be greater or equal to 0.
+ * @return this.
+ */
public Builder setLength(final int length) {
if (length < 0) {
throw new IllegalArgumentException("length cannot be negative");
@@ -114,6 +120,12 @@ public class UnsynchronizedByteArrayInputStream extends InputStream {
return this;
}
+ /**
+ * Sets the offset.
+ *
+ * @param offset Must be greater or equal to 0.
+ * @return this.
+ */
public Builder setOffset(final int offset) {
if (offset < 0) {
throw new IllegalArgumentException("offset cannot be negative");
diff --git a/src/main/java/org/apache/commons/io/input/XmlStreamReader.java b/src/main/java/org/apache/commons/io/input/XmlStreamReader.java
index a38ef807..290e5360 100644
--- a/src/main/java/org/apache/commons/io/input/XmlStreamReader.java
+++ b/src/main/java/org/apache/commons/io/input/XmlStreamReader.java
@@ -157,11 +157,23 @@ public class XmlStreamReader extends Reader {
return super.setCharset(Charsets.toCharset(charset, getCharsetDefault()));
}
+ /**
+ * Sets the HTTP content type.
+ *
+ * @param httpContentType the HTTP content type.
+ * @return this.
+ */
public Builder setHttpContentType(final String httpContentType) {
this.httpContentType = httpContentType;
return this;
}
+ /**
+ * Sets the lenient toggle.
+ *
+ * @param lenient the lenient toggle.
+ * @return this.
+ */
public Builder setLenient(final boolean lenient) {
this.lenient = lenient;
return this;
@@ -209,8 +221,14 @@ public class XmlStreamReader extends Reader {
// @formatter:off
"^<\\?xml\\s+"
+ "version\\s*=\\s*(?:(?:\"1\\.[0-9]+\")|(?:'1.[0-9]+'))\\s+"
- + "encoding\\s*=\\s*((?:\"[A-Za-z]([A-Za-z0-9\\._]|-)*\")|(?:'[A-Za-z]([A-Za-z0-9\\\\._]|-)*'))",
+ + "encoding\\s*=\\s*"
+ + "((?:\"[A-Za-z0-9][A-Za-z0-9._+:-]*\")" // double-quoted
+ + "|(?:'[A-Za-z0-9][A-Za-z0-9._+:-]*'))", // single-quoted
Pattern.MULTILINE);
+ // N.B. the documented pattern is
+ // EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+ // However this does not match all the aliases that are supported by Java.
+ // e.g. '437', 'ISO_8859-1:1987' and 'ebcdic-de-273+euro'
// @formatter:on
private static final String RAW_EX_1 = "Illegal encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] encoding mismatch";
diff --git a/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java b/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
index d4dc19e9..3382bdcd 100644
--- a/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
@@ -70,6 +70,9 @@ public class DeferredFileOutputStream extends ThresholdingOutputStream {
private String suffix;
private Path directory;
+ /**
+ * Constructs a new builder.
+ */
public Builder() {
setBufferSizeDefault(AbstractByteArrayOutputStream.DEFAULT_SIZE);
setBufferSize(AbstractByteArrayOutputStream.DEFAULT_SIZE);
@@ -265,28 +268,6 @@ public class DeferredFileOutputStream extends ThresholdingOutputStream {
}
/**
- * Constructs an instance of this class which will trigger an event at the specified threshold, and save data either to a file beyond that point.
- *
- * @param threshold The number of bytes at which to trigger an event.
- * @param outputFile The file to which data is saved beyond the threshold.
- * @param prefix Prefix to use for the temporary file.
- * @param suffix Suffix to use for the temporary file.
- * @param directory Temporary file directory.
- * @param initialBufferSize The initial size of the in memory buffer.
- * @throws IllegalArgumentException if initialBufferSize &lt; 0.
- */
- private DeferredFileOutputStream(final int threshold, final Path outputFile, final String prefix, final String suffix, final Path directory,
- final int initialBufferSize) {
- super(threshold);
- this.outputPath = toPath(outputFile, null);
- this.prefix = prefix;
- this.suffix = suffix;
- this.directory = toPath(directory, PathUtils::getTempDirectory);
- this.memoryOutputStream = new ByteArrayOutputStream(checkBufferSize(initialBufferSize));
- this.currentOutputStream = memoryOutputStream;
- }
-
- /**
* Constructs an instance of this class which will trigger an event at the specified threshold, and save data to a file beyond that point.
*
* @param threshold The number of bytes at which to trigger an event.
@@ -317,6 +298,28 @@ public class DeferredFileOutputStream extends ThresholdingOutputStream {
}
/**
+ * Constructs an instance of this class which will trigger an event at the specified threshold, and save data either to a file beyond that point.
+ *
+ * @param threshold The number of bytes at which to trigger an event.
+ * @param outputFile The file to which data is saved beyond the threshold.
+ * @param prefix Prefix to use for the temporary file.
+ * @param suffix Suffix to use for the temporary file.
+ * @param directory Temporary file directory.
+ * @param initialBufferSize The initial size of the in memory buffer.
+ * @throws IllegalArgumentException if initialBufferSize &lt; 0.
+ */
+ private DeferredFileOutputStream(final int threshold, final Path outputFile, final String prefix, final String suffix, final Path directory,
+ final int initialBufferSize) {
+ super(threshold);
+ this.outputPath = toPath(outputFile, null);
+ this.prefix = prefix;
+ this.suffix = suffix;
+ this.directory = toPath(directory, PathUtils::getTempDirectory);
+ this.memoryOutputStream = new ByteArrayOutputStream(checkBufferSize(initialBufferSize));
+ this.currentOutputStream = memoryOutputStream;
+ }
+
+ /**
* Constructs an instance of this class which will trigger an event at the specified threshold, and save data to a temporary file beyond that point. The
* initial buffer size will default to 32 bytes which is ByteArrayOutputStream's default buffer size.
*
diff --git a/src/main/java/org/apache/commons/io/output/LockableFileWriter.java b/src/main/java/org/apache/commons/io/output/LockableFileWriter.java
index 064de220..b33abc81 100644
--- a/src/main/java/org/apache/commons/io/output/LockableFileWriter.java
+++ b/src/main/java/org/apache/commons/io/output/LockableFileWriter.java
@@ -70,6 +70,9 @@ public class LockableFileWriter extends Writer {
private boolean append;
private AbstractOrigin<?, ?> lockDirectory = AbstractOriginSupplier.newFileOrigin(FileUtils.getTempDirectoryPath());
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
setBufferSizeDefault(AbstractByteArrayOutputStream.DEFAULT_SIZE);
setBufferSize(AbstractByteArrayOutputStream.DEFAULT_SIZE);
diff --git a/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java b/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
index 1d8a3a03..8102eb58 100644
--- a/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
@@ -149,11 +149,10 @@ public class ThresholdingOutputStream extends OutputStream {
*
* @return The underlying output stream.
* @throws IOException if an error occurs.
- * @deprecated Use {@link #getOutputStream()}.
+ * @since 2.14.0
*/
- @Deprecated
- protected OutputStream getStream() throws IOException {
- return getOutputStream();
+ protected OutputStream getOutputStream() throws IOException {
+ return outputStreamGetter.apply(this);
}
/**
@@ -162,10 +161,11 @@ public class ThresholdingOutputStream extends OutputStream {
*
* @return The underlying output stream.
* @throws IOException if an error occurs.
- * @since 2.14.0
+ * @deprecated Use {@link #getOutputStream()}.
*/
- protected OutputStream getOutputStream() throws IOException {
- return outputStreamGetter.apply(this);
+ @Deprecated
+ protected OutputStream getStream() throws IOException {
+ return getOutputStream();
}
/**
diff --git a/src/main/java/org/apache/commons/io/output/WriterOutputStream.java b/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
index dc4cd6fd..bc2c5c21 100644
--- a/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
@@ -99,6 +99,9 @@ public class WriterOutputStream extends OutputStream {
private CharsetDecoder charsetDecoder;
private boolean writeImmediately;
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
this.charsetDecoder = getCharset().newDecoder();
}
diff --git a/src/main/java/org/apache/commons/io/output/XmlStreamWriter.java b/src/main/java/org/apache/commons/io/output/XmlStreamWriter.java
index b40a2aca..6f732a72 100644
--- a/src/main/java/org/apache/commons/io/output/XmlStreamWriter.java
+++ b/src/main/java/org/apache/commons/io/output/XmlStreamWriter.java
@@ -62,6 +62,9 @@ public class XmlStreamWriter extends Writer {
*/
public static class Builder extends AbstractStreamBuilder<XmlStreamWriter, Builder> {
+ /**
+ * Constructs a new Builder.
+ */
public Builder() {
setCharsetDefault(StandardCharsets.UTF_8);
setCharset(StandardCharsets.UTF_8);
diff --git a/src/main/java/org/apache/commons/io/package-info.java b/src/main/java/org/apache/commons/io/package-info.java
index 29464fe9..6633c106 100644
--- a/src/main/java/org/apache/commons/io/package-info.java
+++ b/src/main/java/org/apache/commons/io/package-info.java
@@ -24,7 +24,7 @@
* <b>FileUtils</b> provides operations based around the JDK File class. These include reading, writing, copying, comparing and deleting.
* </p>
* <p>
- * <b>FilenameUtils</b> provides utilities based on filenames. This utility class manipulates filenames without using File objects. It aims to simplify the
+ * <b>FilenameUtils</b> provides utilities based on filenames. This utility class manipulates file names without using File objects. It aims to simplify the
* transition between Windows and Unix. Before using this class however, you should consider whether you should be using File objects.
* </p>
* <p>
diff --git a/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java b/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java
index bde163c7..6e60f32e 100644
--- a/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java
+++ b/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java
@@ -110,6 +110,32 @@ public class ValidatingObjectInputStream extends ObjectInputStream {
}
/**
+ * Checks that the class name conforms to requirements.
+ *
+ * @param name The class name
+ * @throws InvalidClassException when a non-accepted class is encountered
+ */
+ private void checkClassName(final String name) throws InvalidClassException {
+ // Reject has precedence over accept
+ for (final ClassNameMatcher m : rejectMatchers) {
+ if (m.matches(name)) {
+ invalidClassNameFound(name);
+ }
+ }
+
+ boolean ok = false;
+ for (final ClassNameMatcher m : acceptMatchers) {
+ if (m.matches(name)) {
+ ok = true;
+ break;
+ }
+ }
+ if (!ok) {
+ invalidClassNameFound(name);
+ }
+ }
+
+ /**
* Called to throw {@link InvalidClassException} if an invalid
* class name is found during deserialization. Can be overridden, for example
* to log those class names.
@@ -172,31 +198,7 @@ public class ValidatingObjectInputStream extends ObjectInputStream {
@Override
protected Class<?> resolveClass(final ObjectStreamClass osc) throws IOException, ClassNotFoundException {
- validateClassName(osc.getName());
+ checkClassName(osc.getName());
return super.resolveClass(osc);
}
-
- /** Check that the classname conforms to requirements.
- * @param name The class name
- * @throws InvalidClassException when a non-accepted class is encountered
- */
- private void validateClassName(final String name) throws InvalidClassException {
- // Reject has precedence over accept
- for (final ClassNameMatcher m : rejectMatchers) {
- if (m.matches(name)) {
- invalidClassNameFound(name);
- }
- }
-
- boolean ok = false;
- for (final ClassNameMatcher m : acceptMatchers) {
- if (m.matches(name)) {
- ok = true;
- break;
- }
- }
- if (!ok) {
- invalidClassNameFound(name);
- }
- }
} \ No newline at end of file
diff --git a/src/site/xdoc/download_io.xml b/src/site/xdoc/download_io.xml
index 1d7ef8ec..02445fe0 100644
--- a/src/site/xdoc/download_io.xml
+++ b/src/site/xdoc/download_io.xml
@@ -113,32 +113,32 @@ limitations under the License.
</p>
</subsection>
</section>
- <section name="Apache Commons IO 2.14.0 (requires Java 8)">
+ <section name="Apache Commons IO 2.15.0 (requires Java 8)">
<subsection name="Binaries">
<table>
<tr>
- <td><a href="[preferred]/commons/io/binaries/commons-io-2.14.0-bin.tar.gz">commons-io-2.14.0-bin.tar.gz</a></td>
- <td><a href="https://downloads.apache.org/commons/io/binaries/commons-io-2.14.0-bin.tar.gz.sha512">sha512</a></td>
- <td><a href="https://downloads.apache.org/commons/io/binaries/commons-io-2.14.0-bin.tar.gz.asc">pgp</a></td>
+ <td><a href="[preferred]/commons/io/binaries/commons-io-2.15.0-bin.tar.gz">commons-io-2.15.0-bin.tar.gz</a></td>
+ <td><a href="https://downloads.apache.org/commons/io/binaries/commons-io-2.15.0-bin.tar.gz.sha512">sha512</a></td>
+ <td><a href="https://downloads.apache.org/commons/io/binaries/commons-io-2.15.0-bin.tar.gz.asc">pgp</a></td>
</tr>
<tr>
- <td><a href="[preferred]/commons/io/binaries/commons-io-2.14.0-bin.zip">commons-io-2.14.0-bin.zip</a></td>
- <td><a href="https://downloads.apache.org/commons/io/binaries/commons-io-2.14.0-bin.zip.sha512">sha512</a></td>
- <td><a href="https://downloads.apache.org/commons/io/binaries/commons-io-2.14.0-bin.zip.asc">pgp</a></td>
+ <td><a href="[preferred]/commons/io/binaries/commons-io-2.15.0-bin.zip">commons-io-2.15.0-bin.zip</a></td>
+ <td><a href="https://downloads.apache.org/commons/io/binaries/commons-io-2.15.0-bin.zip.sha512">sha512</a></td>
+ <td><a href="https://downloads.apache.org/commons/io/binaries/commons-io-2.15.0-bin.zip.asc">pgp</a></td>
</tr>
</table>
</subsection>
<subsection name="Source">
<table>
<tr>
- <td><a href="[preferred]/commons/io/source/commons-io-2.14.0-src.tar.gz">commons-io-2.14.0-src.tar.gz</a></td>
- <td><a href="https://downloads.apache.org/commons/io/source/commons-io-2.14.0-src.tar.gz.sha512">sha512</a></td>
- <td><a href="https://downloads.apache.org/commons/io/source/commons-io-2.14.0-src.tar.gz.asc">pgp</a></td>
+ <td><a href="[preferred]/commons/io/source/commons-io-2.15.0-src.tar.gz">commons-io-2.15.0-src.tar.gz</a></td>
+ <td><a href="https://downloads.apache.org/commons/io/source/commons-io-2.15.0-src.tar.gz.sha512">sha512</a></td>
+ <td><a href="https://downloads.apache.org/commons/io/source/commons-io-2.15.0-src.tar.gz.asc">pgp</a></td>
</tr>
<tr>
- <td><a href="[preferred]/commons/io/source/commons-io-2.14.0-src.zip">commons-io-2.14.0-src.zip</a></td>
- <td><a href="https://downloads.apache.org/commons/io/source/commons-io-2.14.0-src.zip.sha512">sha512</a></td>
- <td><a href="https://downloads.apache.org/commons/io/source/commons-io-2.14.0-src.zip.asc">pgp</a></td>
+ <td><a href="[preferred]/commons/io/source/commons-io-2.15.0-src.zip">commons-io-2.15.0-src.zip</a></td>
+ <td><a href="https://downloads.apache.org/commons/io/source/commons-io-2.15.0-src.zip.sha512">sha512</a></td>
+ <td><a href="https://downloads.apache.org/commons/io/source/commons-io-2.15.0-src.zip.asc">pgp</a></td>
</tr>
</table>
</subsection>
diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml
index 1723036e..faecfc29 100644
--- a/src/site/xdoc/index.xml
+++ b/src/site/xdoc/index.xml
@@ -118,18 +118,9 @@ limitations under the License.
The Java platform requirements are:
</p>
<ul>
- <li>Version 2.14.0 requires Java 8.</li>
- <li>Version 2.13.0 requires Java 8.</li>
- <li>Version 2.12.0 requires Java 8.</li>
- <li>Version 2.11.0 requires Java 8.</li>
- <li>Version 2.10.0 requires Java 8.</li>
- <li>Version 2.9.0 requires Java 8.</li>
- <li>Version 2.8.0 requires Java 8.</li>
- <li>Version 2.7 requires Java 8.</li>
+ <li>Version 2.7 and up requires Java 8.</li>
<li>Version 2.6 requires Java 7.</li>
- <li>Version 2.5 requires Java 6.</li>
- <li>Version 2.4 requires Java 6.</li>
- <li>Version 2.3 requires Java 6.</li>
+ <li>Version 2.3 through 2.5 requires Java 6.</li>
<li>Version 2.2 requires Java 5.</li>
</ul>
</subsection>
diff --git a/src/site/xdoc/mail-lists.xml b/src/site/xdoc/mail-lists.xml
index 36189d55..bb94ded2 100644
--- a/src/site/xdoc/mail-lists.xml
+++ b/src/site/xdoc/mail-lists.xml
@@ -59,9 +59,9 @@ limitations under the License.
</p>
<p>
Questions related to the usage of Apache Commons IO should be posted to the
- <a href="https://mail-archives.apache.org/mod_mbox/commons-user/">User List</a>.
+ <a href="https://lists.apache.org/list.html?user@commons.apache.org">User List</a>.
<br />
- The <a href="https://mail-archives.apache.org/mod_mbox/commons-dev/">Developer List</a>
+ The <a href="https://lists.apache.org/list.html?dev@commons.apache.org">Developer List</a>
is for questions and discussion related to the development of Apache Commons IO.
<br />
Please do not cross-post; developers are also subscribed to the user list.
@@ -70,8 +70,10 @@ limitations under the License.
to subscribe.
</p>
<p>
- <strong>Note:</strong> please don't send patches or attachments to any of the mailing lists.
+ <strong>Note:</strong> please don't send patches or attachments to any of the mailing lists;
+ most of the lists are set up to drop attachments.
Patches are best handled via the <a href="issue-tracking.html">Issue Tracking</a> system.
+ If you have a GitHub account, most components also accept PRs (pull requests).
Otherwise, please upload the file to a public server and include the URL in the mail.
</p>
</section>
@@ -105,12 +107,11 @@ limitations under the License.
<td><a href="mailto:user-subscribe@commons.apache.org">Subscribe</a></td>
<td><a href="mailto:user-unsubscribe@commons.apache.org">Unsubscribe</a></td>
<td><a href="mailto:user@commons.apache.org?subject=[io]">Post</a></td>
- <td><a href="https://mail-archives.apache.org/mod_mbox/commons-user/">mail-archives.apache.org</a><br />
+ <td>
<a href="https://lists.apache.org/list.html?user@commons.apache.org">lists.apache.org</a>
</td>
- <td><a href="https://markmail.org/list/org.apache.commons.users/">markmail.org</a><br />
- <a href="https://www.mail-archive.com/user@commons.apache.org/">www.mail-archive.com</a><br />
- <a href="https://news.gmane.org/gmane.comp.jakarta.commons.devel">news.gmane.org</a>
+ <td>
+ <a href="https://www.mail-archive.com/user@commons.apache.org/">www.mail-archive.com</a>
</td>
</tr>
@@ -125,12 +126,11 @@ limitations under the License.
<td><a href="mailto:dev-subscribe@commons.apache.org">Subscribe</a></td>
<td><a href="mailto:dev-unsubscribe@commons.apache.org">Unsubscribe</a></td>
<td><a href="mailto:dev@commons.apache.org?subject=[io]">Post</a></td>
- <td><a href="https://mail-archives.apache.org/mod_mbox/commons-dev/">mail-archives.apache.org</a><br />
+ <td>
<a href="https://lists.apache.org/list.html?dev@commons.apache.org">lists.apache.org</a>
</td>
- <td><a href="https://markmail.org/list/org.apache.commons.dev/">markmail.org</a><br />
- <a href="https://www.mail-archive.com/dev@commons.apache.org/">www.mail-archive.com</a><br />
- <a href="https://news.gmane.org/gmane.comp.jakarta.commons.devel">news.gmane.org</a>
+ <td>
+ <a href="https://www.mail-archive.com/dev@commons.apache.org/">www.mail-archive.com</a>
</td>
</tr>
@@ -145,10 +145,10 @@ limitations under the License.
<td><a href="mailto:issues-subscribe@commons.apache.org">Subscribe</a></td>
<td><a href="mailto:issues-unsubscribe@commons.apache.org">Unsubscribe</a></td>
<td><i>read only</i></td>
- <td><a href="https://mail-archives.apache.org/mod_mbox/commons-issues/">mail-archives.apache.org</a><br />
+ <td>
<a href="https://lists.apache.org/list.html?issues@commons.apache.org">lists.apache.org</a>
</td>
- <td><a href="https://markmail.org/list/org.apache.commons.issues/">markmail.org</a><br />
+ <td>
<a href="https://www.mail-archive.com/issues@commons.apache.org/">www.mail-archive.com</a>
</td>
</tr>
@@ -164,10 +164,10 @@ limitations under the License.
<td><a href="mailto:commits-subscribe@commons.apache.org">Subscribe</a></td>
<td><a href="mailto:commits-unsubscribe@commons.apache.org">Unsubscribe</a></td>
<td><i>read only</i></td>
- <td><a href="https://mail-archives.apache.org/mod_mbox/commons-commits/">mail-archives.apache.org</a><br />
+ <td>
<a href="https://lists.apache.org/list.html?commits@commons.apache.org">lists.apache.org</a>
</td>
- <td><a href="https://markmail.org/list/org.apache.commons.commits/">markmail.org</a><br />
+ <td>
<a href="https://www.mail-archive.com/commits@commons.apache.org/">www.mail-archive.com</a>
</td>
</tr>
@@ -199,13 +199,11 @@ limitations under the License.
<td><a class="externalLink" href="mailto:announce-subscribe@apache.org">Subscribe</a></td>
<td><a class="externalLink" href="mailto:announce-unsubscribe@apache.org">Unsubscribe</a></td>
<td><i>read only</i></td>
- <td><a class="externalLink" href="https://mail-archives.apache.org/mod_mbox/www-announce/">mail-archives.apache.org</a><br />
+ <td>
<a class="externalLink" href="https://lists.apache.org/list.html?announce@apache.org">lists.apache.org</a>
</td>
- <td><a class="externalLink" href="https://markmail.org/list/org.apache.announce/">markmail.org</a><br />
- <a class="externalLink" href="https://old.nabble.com/Apache-News-and-Announce-f109.html">old.nabble.com</a><br />
- <a class="externalLink" href="https://www.mail-archive.com/announce@apache.org/">www.mail-archive.com</a><br />
- <a class="externalLink" href="https://news.gmane.org/gmane.comp.apache.announce">news.gmane.org</a>
+ <td>
+ <a class="externalLink" href="https://www.mail-archive.com/announce@apache.org/">www.mail-archive.com</a>
</td>
</tr>
</table>
diff --git a/src/test/java/org/apache/commons/io/CharsetsTest.java b/src/test/java/org/apache/commons/io/CharsetsTest.java
index b68b90b6..7c988978 100644
--- a/src/test/java/org/apache/commons/io/CharsetsTest.java
+++ b/src/test/java/org/apache/commons/io/CharsetsTest.java
@@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.util.Set;
import java.util.SortedMap;
import org.junit.jupiter.api.Test;
@@ -31,6 +32,20 @@ import org.junit.jupiter.api.Test;
@SuppressWarnings("deprecation") // testing deprecated code
public class CharsetsTest {
+ /**
+ * For parameterized tests.
+ */
+ public static final String AVAIL_CHARSETS = "org.apache.commons.io.CharsetsTest#availableCharsetsKeySet";
+
+ /**
+ * For parameterized tests.
+ *
+ * @return {@code Charset.availableCharsets().keySet()}.
+ */
+ public static Set<String> availableCharsetsKeySet() {
+ return Charset.availableCharsets().keySet();
+ }
+
@Test
public void testIso8859_1() {
assertEquals("ISO-8859-1", Charsets.ISO_8859_1.name());
diff --git a/src/test/java/org/apache/commons/io/DemuxInputStreamTest.java b/src/test/java/org/apache/commons/io/DemuxInputStreamTest.java
index 6872bc54..6b1a63b2 100644
--- a/src/test/java/org/apache/commons/io/DemuxInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/DemuxInputStreamTest.java
@@ -37,7 +37,7 @@ import org.junit.jupiter.api.Test;
*/
public class DemuxInputStreamTest {
- private static class ReaderThread extends Thread {
+ private static final class ReaderThread extends Thread {
private final DemuxInputStream demuxInputStream;
private final InputStream inputStream;
private final StringBuffer stringBuffer = new StringBuffer();
@@ -62,7 +62,7 @@ public class DemuxInputStreamTest {
// System.out.println( "Reading: " + (char)ch );
stringBuffer.append((char) ch);
- final int sleepMillis = Math.abs(c_random.nextInt() % 10);
+ final int sleepMillis = Math.abs(RANDOM.nextInt() % 10);
TestUtils.sleep(sleepMillis);
ch = demuxInputStream.read();
}
@@ -72,7 +72,7 @@ public class DemuxInputStreamTest {
}
}
- private static class WriterThread extends Thread {
+ private static final class WriterThread extends Thread {
private final byte[] byteArray;
private final DemuxOutputStream demuxOutputStream;
private final OutputStream outputStream;
@@ -91,7 +91,7 @@ public class DemuxInputStreamTest {
try {
// System.out.println( "Writing: " + (char)byteArray[ i ] );
demuxOutputStream.write(element);
- final int sleepMillis = Math.abs(c_random.nextInt() % 10);
+ final int sleepMillis = Math.abs(RANDOM.nextInt() % 10);
TestUtils.sleep(sleepMillis);
} catch (final Exception e) {
e.printStackTrace();
@@ -100,7 +100,7 @@ public class DemuxInputStreamTest {
}
}
- private static final Random c_random = new Random();
+ private static final Random RANDOM = new Random();
private static final String DATA1 = "Data for thread1";
private static final String DATA2 = "Data for thread2";
diff --git a/src/test/java/org/apache/commons/io/DirectoryWalkerTest.java b/src/test/java/org/apache/commons/io/DirectoryWalkerTest.java
index 5ac3aa9c..ccb5c110 100644
--- a/src/test/java/org/apache/commons/io/DirectoryWalkerTest.java
+++ b/src/test/java/org/apache/commons/io/DirectoryWalkerTest.java
@@ -90,7 +90,7 @@ public class DirectoryWalkerTest {
* Test DirectoryWalker implementation that always returns false
* from handleDirectoryStart()
*/
- private static class TestFalseFileFinder extends TestFileFinder {
+ private static final class TestFalseFileFinder extends TestFileFinder {
protected TestFalseFileFinder(final FileFilter filter, final int depthLimit) {
super(filter, depthLimit);
@@ -143,7 +143,7 @@ public class DirectoryWalkerTest {
* Test DirectoryWalker implementation that finds files in a directory hierarchy
* applying a file filter.
*/
- private static class TestFileFinderString extends DirectoryWalker<String> {
+ private static final class TestFileFinderString extends DirectoryWalker<String> {
protected TestFileFinderString(final FileFilter filter, final int depthLimit) {
super(filter, depthLimit);
@@ -234,12 +234,12 @@ public class DirectoryWalkerTest {
private static final File outputDir = new File(ioDir, "output");
private static final File[] dirs = {orgDir, apacheDir, commonsDir, ioDir, outputDir};
// Files
- private static final File filenameUtils = new File(ioDir, "FilenameUtils.java");
+ private static final File fileNameUtils = new File(ioDir, "FilenameUtils.java");
private static final File ioUtils = new File(ioDir, "IOUtils.java");
private static final File proxyWriter = new File(outputDir, "ProxyWriter.java");
private static final File nullStream = new File(outputDir, "NullOutputStream.java");
- private static final File[] ioFiles = {filenameUtils, ioUtils};
+ private static final File[] ioFiles = {fileNameUtils, ioUtils};
private static final File[] outputFiles = {proxyWriter, nullStream};
// Filters
diff --git a/src/test/java/org/apache/commons/io/DirectoryWalkerTestCaseJava4.java b/src/test/java/org/apache/commons/io/DirectoryWalkerTestCaseJava4.java
index f55699ad..ad7337dd 100644
--- a/src/test/java/org/apache/commons/io/DirectoryWalkerTestCaseJava4.java
+++ b/src/test/java/org/apache/commons/io/DirectoryWalkerTestCaseJava4.java
@@ -102,7 +102,7 @@ public class DirectoryWalkerTestCaseJava4 {
* Test DirectoryWalker implementation that always returns false
* from handleDirectoryStart()
*/
- private static class TestFalseFileFinder extends TestFileFinder {
+ private static final class TestFalseFileFinder extends TestFileFinder {
protected TestFalseFileFinder(final FileFilter filter, final int depthLimit) {
super(filter, depthLimit);
@@ -237,12 +237,12 @@ public class DirectoryWalkerTestCaseJava4 {
private static final File outputDir = new File(ioDir, "output");
private static final File[] dirs = {orgDir, apacheDir, commonsDir, ioDir, outputDir};
// Files
- private static final File filenameUtils = new File(ioDir, "FilenameUtils.java");
+ private static final File fileNameUtils = new File(ioDir, "FilenameUtils.java");
private static final File ioUtils = new File(ioDir, "IOUtils.java");
private static final File proxyWriter = new File(outputDir, "ProxyWriter.java");
private static final File nullStream = new File(outputDir, "NullOutputStream.java");
- private static final File[] ioFiles = {filenameUtils, ioUtils};
+ private static final File[] ioFiles = {fileNameUtils, ioUtils};
private static final File[] outputFiles = {proxyWriter, nullStream};
// Filters
private static final IOFileFilter dirsFilter = createNameFilter(dirs);
diff --git a/src/test/java/org/apache/commons/io/EndianUtilsTest.java b/src/test/java/org/apache/commons/io/EndianUtilsTest.java
index 79df0c66..4247644d 100644
--- a/src/test/java/org/apache/commons/io/EndianUtilsTest.java
+++ b/src/test/java/org/apache/commons/io/EndianUtilsTest.java
@@ -38,7 +38,7 @@ public class EndianUtilsTest {
}
@Test
- public void testEOFException() throws IOException {
+ public void testEOFException() {
final ByteArrayInputStream input = new ByteArrayInputStream(new byte[] {});
assertThrows(EOFException.class, () -> EndianUtils.readSwappedDouble(input));
}
diff --git a/src/test/java/org/apache/commons/io/FileUtilsDirectoryContainsTest.java b/src/test/java/org/apache/commons/io/FileUtilsDirectoryContainsTest.java
index bba9f098..3e92fef6 100644
--- a/src/test/java/org/apache/commons/io/FileUtilsDirectoryContainsTest.java
+++ b/src/test/java/org/apache/commons/io/FileUtilsDirectoryContainsTest.java
@@ -112,7 +112,7 @@ public class FileUtilsDirectoryContainsTest {
}
@Test
- public void testDirectoryDoesNotExist() throws IOException {
+ public void testDirectoryDoesNotExist() {
final File dir = new File("DOESNOTEXIST");
assertFalse(dir.exists());
assertThrows(IllegalArgumentException.class, () -> FileUtils.directoryContains(dir, file1));
@@ -158,12 +158,12 @@ public class FileUtilsDirectoryContainsTest {
}
@Test
- public void testSameFile() throws IOException {
+ public void testSameFile() {
assertThrows(IllegalArgumentException.class, () -> FileUtils.directoryContains(file1, file1));
}
@Test
- public void testUnrealizedContainment() throws IOException {
+ public void testUnrealizedContainment() {
final File dir = new File("DOESNOTEXIST");
final File file = new File(dir, "DOESNOTEXIST2");
assertFalse(dir.exists());
diff --git a/src/test/java/org/apache/commons/io/FileUtilsListFilesTest.java b/src/test/java/org/apache/commons/io/FileUtilsListFilesTest.java
index 27a81c98..e65bc8de 100644
--- a/src/test/java/org/apache/commons/io/FileUtilsListFilesTest.java
+++ b/src/test/java/org/apache/commons/io/FileUtilsListFilesTest.java
@@ -29,6 +29,7 @@ import java.util.stream.Collectors;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.lang3.function.Consumers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
@@ -45,8 +46,15 @@ public class FileUtilsListFilesTest {
return files.stream().map(File::getName).collect(Collectors.toList());
}
+ /**
+ * Consumes and closes the underlying stream.
+ *
+ * @param files The iterator to consume.
+ * @return a new collection.
+ */
private Collection<String> filesToFilenames(final Iterator<File> files) {
final Collection<String> fileNames = new ArrayList<>();
+ // Iterator.forEachRemaining() closes the underlying stream.
files.forEachRemaining(f -> fileNames.add(f.getName()));
return fileNames;
}
@@ -88,68 +96,83 @@ public class FileUtilsListFilesTest {
final String[] extensions = { "xml", "txt" };
Iterator<File> files = FileUtils.iterateFiles(temporaryFolder, extensions, false);
- Collection<String> filenames = filesToFilenames(files);
- assertEquals(1, filenames.size());
- assertTrue(filenames.contains("dummy-build.xml"));
- assertFalse(filenames.contains("README"));
- assertFalse(filenames.contains("dummy-file.txt"));
-
- files = FileUtils.iterateFiles(temporaryFolder, extensions, true);
- filenames = filesToFilenames(files);
- assertEquals(4, filenames.size());
- assertTrue(filenames.contains("dummy-file.txt"));
- assertFalse(filenames.contains("dummy-index.html"));
+ try {
+ final Collection<String> fileNames = filesToFilenames(files);
+ assertEquals(1, fileNames.size());
+ assertTrue(fileNames.contains("dummy-build.xml"));
+ assertFalse(fileNames.contains("README"));
+ assertFalse(fileNames.contains("dummy-file.txt"));
+ } finally {
+ // Backstop in case filesToFilenames() failure.
+ files.forEachRemaining(Consumers.nop());
+ }
+
+ try {
+ files = FileUtils.iterateFiles(temporaryFolder, extensions, true);
+ final Collection<String> fileNames = filesToFilenames(files);
+ assertEquals(4, fileNames.size());
+ assertTrue(fileNames.contains("dummy-file.txt"));
+ assertFalse(fileNames.contains("dummy-index.html"));
+ } finally {
+ // Backstop in case filesToFilenames() failure.
+ files.forEachRemaining(Consumers.nop());
+ }
files = FileUtils.iterateFiles(temporaryFolder, null, false);
- filenames = filesToFilenames(files);
- assertEquals(2, filenames.size());
- assertTrue(filenames.contains("dummy-build.xml"));
- assertTrue(filenames.contains("README"));
- assertFalse(filenames.contains("dummy-file.txt"));
+ try {
+ final Collection<String> fileNames = filesToFilenames(files);
+ assertEquals(2, fileNames.size());
+ assertTrue(fileNames.contains("dummy-build.xml"));
+ assertTrue(fileNames.contains("README"));
+ assertFalse(fileNames.contains("dummy-file.txt"));
+ } finally {
+ // Backstop in case filesToFilenames() failure.
+ files.forEachRemaining(Consumers.nop());
+ }
}
@Test
public void testListFiles() {
Collection<File> files;
- Collection<String> filenames;
+ Collection<String> fileNames;
IOFileFilter fileFilter;
IOFileFilter dirFilter;
// First, find non-recursively
fileFilter = FileFilterUtils.trueFileFilter();
files = FileUtils.listFiles(temporaryFolder, fileFilter, null);
- filenames = filesToFilenames(files);
- assertTrue(filenames.contains("dummy-build.xml"), "'dummy-build.xml' is missing");
- assertFalse(filenames.contains("dummy-index.html"), "'dummy-index.html' shouldn't be found");
- assertFalse(filenames.contains("Entries"), "'Entries' shouldn't be found");
+ fileNames = filesToFilenames(files);
+ assertTrue(fileNames.contains("dummy-build.xml"), "'dummy-build.xml' is missing");
+ assertFalse(fileNames.contains("dummy-index.html"), "'dummy-index.html' shouldn't be found");
+ assertFalse(fileNames.contains("Entries"), "'Entries' shouldn't be found");
// Second, find recursively
fileFilter = FileFilterUtils.trueFileFilter();
dirFilter = FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("CVS"));
files = FileUtils.listFiles(temporaryFolder, fileFilter, dirFilter);
- filenames = filesToFilenames(files);
- assertTrue(filenames.contains("dummy-build.xml"), "'dummy-build.xml' is missing");
- assertTrue(filenames.contains("dummy-index.html"), "'dummy-index.html' is missing");
- assertFalse(filenames.contains("Entries"), "'Entries' shouldn't be found");
+ fileNames = filesToFilenames(files);
+ assertTrue(fileNames.contains("dummy-build.xml"), "'dummy-build.xml' is missing");
+ assertTrue(fileNames.contains("dummy-index.html"), "'dummy-index.html' is missing");
+ assertFalse(fileNames.contains("Entries"), "'Entries' shouldn't be found");
// Do the same as above but now with the filter coming from FileFilterUtils
fileFilter = FileFilterUtils.trueFileFilter();
dirFilter = FileFilterUtils.makeCVSAware(null);
files = FileUtils.listFiles(temporaryFolder, fileFilter, dirFilter);
- filenames = filesToFilenames(files);
- assertTrue(filenames.contains("dummy-build.xml"), "'dummy-build.xml' is missing");
- assertTrue(filenames.contains("dummy-index.html"), "'dummy-index.html' is missing");
- assertFalse(filenames.contains("Entries"), "'Entries' shouldn't be found");
+ fileNames = filesToFilenames(files);
+ assertTrue(fileNames.contains("dummy-build.xml"), "'dummy-build.xml' is missing");
+ assertTrue(fileNames.contains("dummy-index.html"), "'dummy-index.html' is missing");
+ assertFalse(fileNames.contains("Entries"), "'Entries' shouldn't be found");
// Again with the CVS filter but now with a non-null parameter
fileFilter = FileFilterUtils.trueFileFilter();
dirFilter = FileFilterUtils.prefixFileFilter("sub");
dirFilter = FileFilterUtils.makeCVSAware(dirFilter);
files = FileUtils.listFiles(temporaryFolder, fileFilter, dirFilter);
- filenames = filesToFilenames(files);
- assertTrue(filenames.contains("dummy-build.xml"), "'dummy-build.xml' is missing");
- assertTrue(filenames.contains("dummy-index.html"), "'dummy-index.html' is missing");
- assertFalse(filenames.contains("Entries"), "'Entries' shouldn't be found");
+ fileNames = filesToFilenames(files);
+ assertTrue(fileNames.contains("dummy-build.xml"), "'dummy-build.xml' is missing");
+ assertTrue(fileNames.contains("dummy-index.html"), "'dummy-index.html' is missing");
+ assertFalse(fileNames.contains("Entries"), "'Entries' shouldn't be found");
assertThrows(NullPointerException.class, () -> FileUtils.listFiles(temporaryFolder, null, null));
}
@@ -160,23 +183,23 @@ public class FileUtilsListFilesTest {
Collection<File> files = FileUtils.listFiles(temporaryFolder, extensions, false);
assertEquals(1, files.size());
- Collection<String> filenames = filesToFilenames(files);
- assertTrue(filenames.contains("dummy-build.xml"));
- assertFalse(filenames.contains("README"));
- assertFalse(filenames.contains("dummy-file.txt"));
+ Collection<String> fileNames = filesToFilenames(files);
+ assertTrue(fileNames.contains("dummy-build.xml"));
+ assertFalse(fileNames.contains("README"));
+ assertFalse(fileNames.contains("dummy-file.txt"));
files = FileUtils.listFiles(temporaryFolder, extensions, true);
- filenames = filesToFilenames(files);
- assertEquals(4, filenames.size());
- assertTrue(filenames.contains("dummy-file.txt"));
- assertFalse(filenames.contains("dummy-index.html"));
+ fileNames = filesToFilenames(files);
+ assertEquals(4, fileNames.size());
+ assertTrue(fileNames.contains("dummy-file.txt"));
+ assertFalse(fileNames.contains("dummy-index.html"));
files = FileUtils.listFiles(temporaryFolder, null, false);
assertEquals(2, files.size());
- filenames = filesToFilenames(files);
- assertTrue(filenames.contains("dummy-build.xml"));
- assertTrue(filenames.contains("README"));
- assertFalse(filenames.contains("dummy-file.txt"));
+ fileNames = filesToFilenames(files);
+ assertTrue(fileNames.contains("dummy-build.xml"));
+ assertTrue(fileNames.contains("README"));
+ assertFalse(fileNames.contains("dummy-file.txt"));
}
diff --git a/src/test/java/org/apache/commons/io/FileUtilsTest.java b/src/test/java/org/apache/commons/io/FileUtilsTest.java
index 4d976c4e..2c820c8d 100644
--- a/src/test/java/org/apache/commons/io/FileUtilsTest.java
+++ b/src/test/java/org/apache/commons/io/FileUtilsTest.java
@@ -40,6 +40,7 @@ import java.math.BigInteger;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -47,6 +48,7 @@ import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.AclFileAttributeView;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
@@ -86,6 +88,7 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -123,20 +126,6 @@ public class FileUtilsTest extends AbstractTempDirTest {
}
}
- // Test helper class to pretend a file is shorter than it is
- private static class ShorterFile extends File {
- private static final long serialVersionUID = 1L;
-
- public ShorterFile(final String pathname) {
- super(pathname);
- }
-
- @Override
- public long length() {
- return super.length() - 1;
- }
- }
-
private static final String UTF_8 = StandardCharsets.UTF_8.name();
/** Test data. */
@@ -168,11 +157,6 @@ public class FileUtilsTest extends AbstractTempDirTest {
*/
private static final ListDirectoryWalker LIST_WALKER = new ListDirectoryWalker();
- /**
- * Delay in milliseconds to make sure test for "last modified date" are accurate
- */
- //private static final int LAST_MODIFIED_DELAY = 600;
-
private File testFile1;
private File testFile2;
@@ -1452,7 +1436,7 @@ public class FileUtilsTest extends AbstractTempDirTest {
public void testFileUtils() throws Exception {
// Loads file from classpath
final File file1 = new File(tempDirFile, "test.txt");
- final String filename = file1.getAbsolutePath();
+ final String fileName = file1.getAbsolutePath();
//Create test file on-the-fly (used to be in CVS)
try (OutputStream out = Files.newOutputStream(file1.toPath())) {
@@ -1461,16 +1445,16 @@ public class FileUtilsTest extends AbstractTempDirTest {
final File file2 = new File(tempDirFile, "test2.txt");
- FileUtils.writeStringToFile(file2, filename, UTF_8);
+ FileUtils.writeStringToFile(file2, fileName, UTF_8);
assertTrue(file2.exists());
assertTrue(file2.length() > 0);
final String file2contents = FileUtils.readFileToString(file2, UTF_8);
- assertEquals(filename, file2contents, "Second file's contents correct");
+ assertEquals(fileName, file2contents, "Second file's contents correct");
assertTrue(file2.delete());
- final String contents = FileUtils.readFileToString(new File(filename), UTF_8);
+ final String contents = FileUtils.readFileToString(new File(fileName), UTF_8);
assertEquals("This is a test", contents, "FileUtils.fileRead()");
}
@@ -1645,8 +1629,8 @@ public class FileUtilsTest extends AbstractTempDirTest {
@Test
public void testIO575() throws IOException {
final Path sourceDir = Files.createTempDirectory("source-dir");
- final String filename = "some-file";
- final Path sourceFile = Files.createFile(sourceDir.resolve(filename));
+ final String fileName = "some-file";
+ final Path sourceFile = Files.createFile(sourceDir.resolve(fileName));
assertEquals(SystemUtils.IS_OS_WINDOWS, sourceFile.toFile().canExecute());
@@ -1658,7 +1642,7 @@ public class FileUtilsTest extends AbstractTempDirTest {
FileUtils.copyDirectory(sourceDir.toFile(), destDir.toFile());
- final Path destFile = destDir.resolve(filename);
+ final Path destFile = destDir.resolve(fileName);
assertTrue(destFile.toFile().exists());
assertTrue(destFile.toFile().canExecute());
@@ -2445,6 +2429,41 @@ public class FileUtilsTest extends AbstractTempDirTest {
}
@Test
+ public void testReadFileToByteArray_Errors() {
+ assertThrows(NullPointerException.class, () -> FileUtils.readFileToByteArray(null));
+ assertThrows(IOException.class, () -> FileUtils.readFileToByteArray(new File("non-exsistent")));
+ assertThrows(IOException.class, () -> FileUtils.readFileToByteArray(tempDirFile));
+ }
+
+ @Test
+ @EnabledIf("isPosixFilePermissionsSupported")
+ public void testReadFileToByteArray_IOExceptionOnPosixFileSystem() throws Exception {
+ final File file = TestUtils.newFile(tempDirFile, "cant-read.txt");
+ TestUtils.createFile(file, 100);
+ Files.setPosixFilePermissions(file.toPath(), PosixFilePermissions.fromString("---------"));
+
+ assertThrows(IOException.class, () -> FileUtils.readFileToByteArray(file));
+ }
+
+ @Test
+ public void testReadFileToString_Errors() {
+ assertThrows(NullPointerException.class, () -> FileUtils.readFileToString(null));
+ assertThrows(IOException.class, () -> FileUtils.readFileToString(new File("non-exsistent")));
+ assertThrows(IOException.class, () -> FileUtils.readFileToString(tempDirFile));
+ assertThrows(UnsupportedCharsetException.class, () -> FileUtils.readFileToString(tempDirFile, "unsupported-charset"));
+ }
+
+ @Test
+ @EnabledIf("isPosixFilePermissionsSupported")
+ public void testReadFileToString_IOExceptionOnPosixFileSystem() throws Exception {
+ final File file = TestUtils.newFile(tempDirFile, "cant-read.txt");
+ TestUtils.createFile(file, 100);
+ Files.setPosixFilePermissions(file.toPath(), PosixFilePermissions.fromString("---------"));
+
+ assertThrows(IOException.class, () -> FileUtils.readFileToString(file));
+ }
+
+ @Test
public void testReadFileToStringWithDefaultEncoding() throws Exception {
final File file = new File(tempDirFile, "read.obj");
final String fixture = "Hello /u1234";
@@ -2478,6 +2497,24 @@ public class FileUtilsTest extends AbstractTempDirTest {
}
@Test
+ public void testReadLines_Errors() {
+ assertThrows(NullPointerException.class, () -> FileUtils.readLines(null));
+ assertThrows(IOException.class, () -> FileUtils.readLines(new File("non-exsistent")));
+ assertThrows(IOException.class, () -> FileUtils.readLines(tempDirFile));
+ assertThrows(UnsupportedCharsetException.class, () -> FileUtils.readLines(tempDirFile, "unsupported-charset"));
+ }
+
+ @Test
+ @EnabledIf("isPosixFilePermissionsSupported")
+ public void testReadLines_IOExceptionOnPosixFileSystem() throws Exception {
+ final File file = TestUtils.newFile(tempDirFile, "cant-read.txt");
+ TestUtils.createFile(file, 100);
+ Files.setPosixFilePermissions(file.toPath(), PosixFilePermissions.fromString("---------"));
+
+ assertThrows(IOException.class, () -> FileUtils.readLines(file));
+ }
+
+ @Test
public void testSizeOf() throws Exception {
final File file = new File(tempDirFile, getName());
diff --git a/src/test/java/org/apache/commons/io/IOUtilsMultithreadedSkipTest.java b/src/test/java/org/apache/commons/io/IOUtilsMultithreadedSkipTest.java
index 9db0d67b..a492d397 100644
--- a/src/test/java/org/apache/commons/io/IOUtilsMultithreadedSkipTest.java
+++ b/src/test/java/org/apache/commons/io/IOUtilsMultithreadedSkipTest.java
@@ -87,7 +87,7 @@ public class IOUtilsMultithreadedSkipTest {
try (final InputStream inputStream = getClass().getResourceAsStream(FIXTURE)) {
bytes = IOUtils.toByteArray(inputStream);
}
- final int numSkips = (random.nextInt(bytes.length) / 100) + 1;
+ final int numSkips = random.nextInt(bytes.length) / 100 + 1;
final int[] skips = generateSkips(bytes, numSkips, random);
final int[] expected;
diff --git a/src/test/java/org/apache/commons/io/IOUtilsTest.java b/src/test/java/org/apache/commons/io/IOUtilsTest.java
index e361e885..c921abc1 100644
--- a/src/test/java/org/apache/commons/io/IOUtilsTest.java
+++ b/src/test/java/org/apache/commons/io/IOUtilsTest.java
@@ -1257,7 +1257,7 @@ public class IOUtilsTest {
assertThrows(NullPointerException.class, () -> IOUtils.resourceToURL(null, ClassLoader.getSystemClassLoader()));
}
- public void testSingleEOL(final String s1, final String s2, final boolean ifEquals) throws IOException {
+ public void testSingleEOL(final String s1, final String s2, final boolean ifEquals) {
assertEquals(ifEquals, IOUtils.contentEqualsIgnoreEOL(
new CharArrayReader(s1.toCharArray()),
new CharArrayReader(s2.toCharArray())
@@ -1750,6 +1750,15 @@ public class IOUtilsTest {
}
@Test
+ public void testWriteLines() throws IOException {
+ final String[] data = {"The", "quick"};
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ IOUtils.writeLines(Arrays.asList(data), "\n", out, "UTF-16");
+ final String result = new String(out.toByteArray(), StandardCharsets.UTF_16);
+ assertEquals("The\nquick\n", result);
+ }
+
+ @Test
public void testWriteLittleString() throws IOException {
final String data = "\uD83D";
// White-box test to check that not closing the internal channel is not a problem.
diff --git a/src/test/java/org/apache/commons/io/RandomAccessFilesTest.java b/src/test/java/org/apache/commons/io/RandomAccessFilesTest.java
index d3873599..ce7fa8fd 100644
--- a/src/test/java/org/apache/commons/io/RandomAccessFilesTest.java
+++ b/src/test/java/org/apache/commons/io/RandomAccessFilesTest.java
@@ -19,10 +19,15 @@ package org.apache.commons.io;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.io.RandomAccessFile;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
import org.junit.jupiter.api.Test;
@@ -31,32 +36,101 @@ import org.junit.jupiter.api.Test;
*/
public class RandomAccessFilesTest {
- protected static final String FILE_RES_RO = "/org/apache/commons/io/test-file-20byteslength.bin";
- protected static final String FILE_NAME_RO = "src/test/resources" + FILE_RES_RO;
+ private static final String FILE_NAME_RO_20 = "src/test/resources/org/apache/commons/io/test-file-20byteslength.bin";
+ private static final String FILE_NAME_RO_0 = "src/test/resources/org/apache/commons/io/test-file-empty.bin";
+ private static final String FILE_NAME_RO_0_BIS = "src/test/resources/org/apache/commons/io/test-file-empty2.bin";
+
+ @Test
+ public void testContentEquals() throws IOException {
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) {
+ assertEquals(raf1, raf1);
+ assertTrue(RandomAccessFiles.contentEquals(raf1, raf1));
+ }
+ // as above, to make sure resources are OK
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) {
+ assertEquals(raf1, raf1);
+ assertTrue(RandomAccessFiles.contentEquals(raf1, raf1));
+ }
+ // same 20 bytes
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20);
+ RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) {
+ assertTrue(RandomAccessFiles.contentEquals(raf1, raf2));
+ }
+ // same empty file
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_0);
+ RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_0)) {
+ assertTrue(RandomAccessFiles.contentEquals(raf1, raf2));
+ assertTrue(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf2), RandomAccessFiles.reset(raf1)));
+ }
+ // diff empty file
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_0);
+ RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_0_BIS)) {
+ assertTrue(RandomAccessFiles.contentEquals(raf1, raf2));
+ assertTrue(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf2), RandomAccessFiles.reset(raf1)));
+ }
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_0);
+ RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) {
+ assertFalse(RandomAccessFiles.contentEquals(raf1, raf2));
+ assertFalse(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf2), RandomAccessFiles.reset(raf1)));
+ }
+ //
+ final Path bigFile1 = Files.createTempFile(getClass().getSimpleName(), "-1.bin");
+ final Path bigFile2 = Files.createTempFile(getClass().getSimpleName(), "-2.bin");
+ final Path bigFile3 = Files.createTempFile(getClass().getSimpleName(), "-3.bin");
+ try {
+ final int newLength = 1_000_000;
+ final byte[] bytes1 = new byte[newLength];
+ final byte[] bytes2 = new byte[newLength];
+ Arrays.fill(bytes1, (byte) 1);
+ Arrays.fill(bytes2, (byte) 2);
+ Files.write(bigFile1, bytes1);
+ Files.write(bigFile2, bytes2);
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(bigFile1);
+ RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(bigFile2)) {
+ assertFalse(RandomAccessFiles.contentEquals(raf1, raf2));
+ assertFalse(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf2), RandomAccessFiles.reset(raf1)));
+ assertTrue(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf1), RandomAccessFiles.reset(raf1)));
+ }
+ // Make the last byte different
+ final byte[] bytes3 = bytes1.clone();
+ bytes3[bytes3.length - 1] = 9;
+ Files.write(bigFile3, bytes3);
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(bigFile1);
+ RandomAccessFile raf3 = RandomAccessFileMode.READ_ONLY.create(bigFile3)) {
+ assertFalse(RandomAccessFiles.contentEquals(raf1, raf3));
+ assertFalse(RandomAccessFiles.contentEquals(RandomAccessFiles.reset(raf3), RandomAccessFiles.reset(raf1)));
+ }
+ } finally {
+ // Delete ASAP
+ Files.deleteIfExists(bigFile1);
+ Files.deleteIfExists(bigFile2);
+ Files.deleteIfExists(bigFile3);
+ }
+ }
@Test
public void testRead() throws IOException {
- try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO)) {
+ try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) {
final byte[] buffer = RandomAccessFiles.read(raf, 0, 0);
assertArrayEquals(new byte[] {}, buffer);
}
- try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO)) {
+ try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) {
final byte[] buffer = RandomAccessFiles.read(raf, 1, 0);
assertArrayEquals(new byte[] {}, buffer);
}
- try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO)) {
+ try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) {
final byte[] buffer = RandomAccessFiles.read(raf, 0, 1);
assertArrayEquals(new byte[] { '1' }, buffer);
}
- try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO)) {
+ try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) {
final byte[] buffer = RandomAccessFiles.read(raf, 1, 1);
assertArrayEquals(new byte[] { '2' }, buffer);
}
- try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO)) {
+ try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) {
final byte[] buffer = RandomAccessFiles.read(raf, 0, 20);
assertEquals(20, buffer.length);
}
- try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO)) {
+ try (final RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(FILE_NAME_RO_20)) {
assertThrows(IOException.class, () -> RandomAccessFiles.read(raf, 0, 21));
}
}
diff --git a/src/test/java/org/apache/commons/io/StreamIteratorTest.java b/src/test/java/org/apache/commons/io/StreamIteratorTest.java
new file mode 100644
index 00000000..7cfa9afb
--- /dev/null
+++ b/src/test/java/org/apache/commons/io/StreamIteratorTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.io;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link StreamIterator}.
+ */
+public class StreamIteratorTest {
+
+ @Test
+ public void testForEachRemaining() {
+ final AtomicBoolean closed = new AtomicBoolean();
+ final Iterator<Integer> iter = StreamIterator.iterator(Stream.of(1, 2, 3).onClose(() -> closed.set(true)));
+ final AtomicInteger sum = new AtomicInteger();
+
+ iter.forEachRemaining(sum::addAndGet);
+
+ assertEquals(6, sum.get());
+ assertTrue(closed.get());
+ }
+
+ @Test
+ public void testHasNext() {
+ final AtomicBoolean closed = new AtomicBoolean();
+ final Iterator<Integer> iter = StreamIterator.iterator(Stream.of(1, 2, 3).onClose(() -> closed.set(true)));
+ int sum = 0;
+
+ while (iter.hasNext()) {
+ sum += iter.next();
+ }
+
+ assertEquals(6, sum);
+ assertTrue(closed.get());
+ }
+}
diff --git a/src/test/java/org/apache/commons/io/file/AbstractTempDirTest.java b/src/test/java/org/apache/commons/io/file/AbstractTempDirTest.java
index a5ed616f..16bd66cc 100644
--- a/src/test/java/org/apache/commons/io/file/AbstractTempDirTest.java
+++ b/src/test/java/org/apache/commons/io/file/AbstractTempDirTest.java
@@ -19,6 +19,7 @@ package org.apache.commons.io.file;
import java.io.File;
import java.io.IOException;
+import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -52,4 +53,8 @@ public abstract class AbstractTempDirTest {
tempDirFile = tempDirPath.toFile();
}
+
+ protected final boolean isPosixFilePermissionsSupported() {
+ return FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
+ }
}
diff --git a/src/test/java/org/apache/commons/io/file/FilesUncheckTest.java b/src/test/java/org/apache/commons/io/file/FilesUncheckTest.java
index 4fa73681..80f4d37b 100644
--- a/src/test/java/org/apache/commons/io/file/FilesUncheckTest.java
+++ b/src/test/java/org/apache/commons/io/file/FilesUncheckTest.java
@@ -50,6 +50,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
+import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.function.Uncheck;
@@ -166,7 +167,9 @@ public class FilesUncheckTest {
@Test
public void testFind() {
- assertNotNull(FilesUncheck.find(FILE_PATH_EMPTY, 0, (t, u) -> false));
+ try (Stream<Path> find = FilesUncheck.find(FILE_PATH_EMPTY, 0, (t, u) -> false)) {
+ assertNotNull(find);
+ }
}
@Test
@@ -207,17 +210,23 @@ public class FilesUncheckTest {
@Test
public void testLinesPath() {
- assertEquals(0, FilesUncheck.lines(FILE_PATH_EMPTY).count());
+ try (Stream<String> stream = FilesUncheck.lines(FILE_PATH_EMPTY)) {
+ assertEquals(0, stream.count());
+ }
}
@Test
public void testLinesPathCharset() {
- assertEquals(0, FilesUncheck.lines(FILE_PATH_EMPTY, StandardCharsets.UTF_8).count());
+ try (Stream<String> stream = FilesUncheck.lines(FILE_PATH_EMPTY, StandardCharsets.UTF_8)) {
+ assertEquals(0, stream.count());
+ }
}
@Test
public void testList() {
- assertEquals(1, FilesUncheck.list(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0")).count());
+ try (Stream<Path> stream = FilesUncheck.list(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"))) {
+ assertEquals(1, stream.count());
+ }
}
@Test
@@ -426,12 +435,16 @@ public class FilesUncheckTest {
@Test
public void testWalkPathFileVisitOptionArray() {
- assertTrue(0 < FilesUncheck.walk(TARGET_PATH, FileVisitOption.FOLLOW_LINKS).count());
+ try (Stream<Path> stream = FilesUncheck.walk(TARGET_PATH, FileVisitOption.FOLLOW_LINKS)) {
+ assertTrue(0 < stream.count());
+ }
}
@Test
public void testWalkPathIntFileVisitOptionArray() {
- assertEquals(1, FilesUncheck.walk(TARGET_PATH, 0, FileVisitOption.FOLLOW_LINKS).count());
+ try (Stream<Path> stream = FilesUncheck.walk(TARGET_PATH, 0, FileVisitOption.FOLLOW_LINKS)) {
+ assertEquals(1, stream.count());
+ }
}
@Test
diff --git a/src/test/java/org/apache/commons/io/filefilter/AbstractConditionalFileFilterTest.java b/src/test/java/org/apache/commons/io/filefilter/AbstractConditionalFileFilterTest.java
index 5a99d620..a663e5f6 100644
--- a/src/test/java/org/apache/commons/io/filefilter/AbstractConditionalFileFilterTest.java
+++ b/src/test/java/org/apache/commons/io/filefilter/AbstractConditionalFileFilterTest.java
@@ -104,7 +104,7 @@ public abstract class AbstractConditionalFileFilterTest extends AbstractIOFileFi
final boolean[] trueResults = testTrueResults.get(i);
final boolean[] falseResults = testFalseResults.get(i);
final boolean fileResults = testFileResults.get(i);
- final boolean filenameResults = testFilenameResults.get(i);
+ final boolean fileNameResults = testFilenameResults.get(i);
// Test conditional AND filter created by passing filters to the constructor
final IOFileFilter filter = this.buildFilterUsingAdd(filters);
@@ -116,10 +116,10 @@ public abstract class AbstractConditionalFileFilterTest extends AbstractIOFileFi
assertTrueFiltersInvoked(i, trueFilters, trueResults);
assertFalseFiltersInvoked(i, falseFilters, falseResults);
- // Test as a filename filter
+ // Test as a file name filter
resetTrueFilters(this.trueFilters);
resetFalseFilters(this.falseFilters);
- assertFilenameFiltering(i, filter, this.file, filenameResults);
+ assertFilenameFiltering(i, filter, this.file, fileNameResults);
assertTrueFiltersInvoked(i, trueFilters, trueResults);
assertFalseFiltersInvoked(i, falseFilters, falseResults);
}
@@ -138,7 +138,7 @@ public abstract class AbstractConditionalFileFilterTest extends AbstractIOFileFi
final boolean[] trueResults = testTrueResults.get(i);
final boolean[] falseResults = testFalseResults.get(i);
final boolean fileResults = testFileResults.get(i);
- final boolean filenameResults = testFilenameResults.get(i);
+ final boolean fileNameResults = testFilenameResults.get(i);
// Test conditional AND filter created by passing filters to the constructor
final IOFileFilter filter = this.buildFilterUsingConstructor(filters);
@@ -150,10 +150,10 @@ public abstract class AbstractConditionalFileFilterTest extends AbstractIOFileFi
assertTrueFiltersInvoked(i, trueFilters, trueResults);
assertFalseFiltersInvoked(i, falseFilters, falseResults);
- // Test as a filename filter
+ // Test as a file name filter
resetTrueFilters(this.trueFilters);
resetFalseFilters(this.falseFilters);
- assertFilenameFiltering(i, filter, this.file, filenameResults);
+ assertFilenameFiltering(i, filter, this.file, fileNameResults);
assertTrueFiltersInvoked(i, trueFilters, trueResults);
assertFalseFiltersInvoked(i, falseFilters, falseResults);
}
diff --git a/src/test/java/org/apache/commons/io/function/IOBaseStreamTest.java b/src/test/java/org/apache/commons/io/function/IOBaseStreamTest.java
index 1c05418c..a0bd3e47 100644
--- a/src/test/java/org/apache/commons/io/function/IOBaseStreamTest.java
+++ b/src/test/java/org/apache/commons/io/function/IOBaseStreamTest.java
@@ -67,7 +67,7 @@ public class IOBaseStreamTest {
/**
* Implements IOBaseStream with a concrete type.
*/
- private static class IOBaseStreamPathFixture<B extends BaseStream<Path, B>> extends IOBaseStreamFixture<Path, IOBaseStreamPathFixture<B>, B> {
+ private static final class IOBaseStreamPathFixture<B extends BaseStream<Path, B>> extends IOBaseStreamFixture<Path, IOBaseStreamPathFixture<B>, B> {
private IOBaseStreamPathFixture(final B baseStream) {
super(baseStream);
@@ -80,7 +80,7 @@ public class IOBaseStreamTest {
}
- private static class MyRuntimeException extends RuntimeException {
+ private static final class MyRuntimeException extends RuntimeException {
private static final long serialVersionUID = 1L;
diff --git a/src/test/java/org/apache/commons/io/function/IOBinaryOperatorStreamTest.java b/src/test/java/org/apache/commons/io/function/IOBinaryOperatorStreamTest.java
index a591e780..501d75f8 100644
--- a/src/test/java/org/apache/commons/io/function/IOBinaryOperatorStreamTest.java
+++ b/src/test/java/org/apache/commons/io/function/IOBinaryOperatorStreamTest.java
@@ -88,14 +88,19 @@ public class IOBinaryOperatorStreamTest {
public void testReduce() throws IOException {
// A silly example to pass in a IOBinaryOperator.
final Path current = PathUtils.current();
- final Path expected = Files.list(current).reduce((t, u) -> {
- try {
- return t.toRealPath();
- } catch (final IOException e) {
- return fail(e);
- }
- }).get();
- assertEquals(expected, Files.list(current).reduce(REAL_PATH_BO).get());
+ final Path expected;
+ try (Stream<Path> stream = Files.list(current)) {
+ expected = stream.reduce((t, u) -> {
+ try {
+ return t.toRealPath();
+ } catch (final IOException e) {
+ return fail(e);
+ }
+ }).get();
+ }
+ try (Stream<Path> stream = Files.list(current)) {
+ assertEquals(expected, stream.reduce(REAL_PATH_BO).get());
+ }
}
}
diff --git a/src/test/java/org/apache/commons/io/function/IOConsumerTest.java b/src/test/java/org/apache/commons/io/function/IOConsumerTest.java
index 5bfeb401..1871be48 100644
--- a/src/test/java/org/apache/commons/io/function/IOConsumerTest.java
+++ b/src/test/java/org/apache/commons/io/function/IOConsumerTest.java
@@ -76,11 +76,11 @@ public class IOConsumerTest {
public void testForAllArrayOf1() throws IOException {
IOConsumer.forAll(TestUtils.throwingIOConsumer(), (String[]) null);
IOConsumer.forAll(null, (String[]) null);
- assertThrows(IOExceptionList.class, () -> IOConsumer.forAll(TestUtils.throwingIOConsumer(), new String[] {"1"}));
+ assertThrows(IOExceptionList.class, () -> IOConsumer.forAll(TestUtils.throwingIOConsumer(), "1"));
//
final AtomicReference<String> ref = new AtomicReference<>("0");
final IOConsumer<String> consumer1 = s -> ref.set(ref.get() + s);
- IOConsumer.forAll(consumer1, new String[] {"1"});
+ IOConsumer.forAll(consumer1, "1");
assertEquals("01", ref.get());
}
@@ -88,11 +88,11 @@ public class IOConsumerTest {
public void testForAllArrayOf2() throws IOException {
IOConsumer.forAll(TestUtils.throwingIOConsumer(), (String[]) null);
IOConsumer.forAll(null, (String[]) null);
- assertThrows(IOExceptionList.class, () -> IOConsumer.forAll(TestUtils.throwingIOConsumer(), new String[] {"1", "2"}));
+ assertThrows(IOExceptionList.class, () -> IOConsumer.forAll(TestUtils.throwingIOConsumer(), "1", "2"));
//
final AtomicReference<String> ref = new AtomicReference<>("0");
final IOConsumer<String> consumer1 = s -> ref.set(ref.get() + s);
- IOConsumer.forAll(consumer1, new String[] {"1", "2"});
+ IOConsumer.forAll(consumer1, "1", "2");
assertEquals("012", ref.get());
}
diff --git a/src/test/java/org/apache/commons/io/function/IOFunctionTest.java b/src/test/java/org/apache/commons/io/function/IOFunctionTest.java
index 1032aeee..af859aba 100644
--- a/src/test/java/org/apache/commons/io/function/IOFunctionTest.java
+++ b/src/test/java/org/apache/commons/io/function/IOFunctionTest.java
@@ -38,7 +38,7 @@ import org.junit.jupiter.api.Test;
*/
public class IOFunctionTest {
- private static class Holder<T> {
+ private static final class Holder<T> {
T value;
}
@@ -168,7 +168,7 @@ public class IOFunctionTest {
public void testIdentity() throws IOException {
assertEquals(IOFunction.identity(), IOFunction.identity());
final IOFunction<byte[], byte[]> identityFunction = IOFunction.identity();
- final byte[] buf = new byte[] {(byte) 0xa, (byte) 0xb, (byte) 0xc};
+ final byte[] buf = {(byte) 0xa, (byte) 0xb, (byte) 0xc};
assertEquals(buf, identityFunction.apply(buf));
assertArrayEquals(buf, identityFunction.apply(buf));
}
diff --git a/src/test/java/org/apache/commons/io/function/IOLongSupplierTest.java b/src/test/java/org/apache/commons/io/function/IOLongSupplierTest.java
index 07748ded..dce0a426 100644
--- a/src/test/java/org/apache/commons/io/function/IOLongSupplierTest.java
+++ b/src/test/java/org/apache/commons/io/function/IOLongSupplierTest.java
@@ -49,7 +49,7 @@ public class IOLongSupplierTest {
}
@Test
- public void testAsSupplier() throws IOException {
+ public void testAsSupplier() {
assertThrows(UncheckedIOException.class, () -> TestConstants.THROWING_IO_LONG_SUPPLIER.asSupplier().getAsLong());
assertEquals(1L, getThrowsNone(() -> TestUtils.compareAndSetThrowsIO(atomicLong, 1L)));
assertEquals(1L, atomicLong.get());
diff --git a/src/test/java/org/apache/commons/io/function/IOStreamTest.java b/src/test/java/org/apache/commons/io/function/IOStreamTest.java
index 198a361c..3e2ef9c5 100644
--- a/src/test/java/org/apache/commons/io/function/IOStreamTest.java
+++ b/src/test/java/org/apache/commons/io/function/IOStreamTest.java
@@ -402,7 +402,7 @@ public class IOStreamTest {
@SuppressWarnings("resource") // custom stream not recognized by compiler warning machinery
@Test
- public void testOnCloseMultipleHandlers() throws IOException {
+ public void testOnCloseMultipleHandlers() {
//
final AtomicReference<String> ref = new AtomicReference<>();
// Sanity check
@@ -511,13 +511,14 @@ public class IOStreamTest {
assertEquals(1, IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count());
assertEquals(1, IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count());
assertNull(ref.get());
- } else if (AT_LEAST_JAVA_11) {
- assertThrows(RuntimeException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count());
- assertThrows(IOException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count());
- assertEquals("B", ref.get());
} else {
- assertThrows(RuntimeException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count());
- assertThrows(IOException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count());
+ if (AT_LEAST_JAVA_11) {
+ assertThrows(RuntimeException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count());
+ assertThrows(IOException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count());
+ } else {
+ assertThrows(RuntimeException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetRE(ref, null, e)).count());
+ assertThrows(IOException.class, () -> IOStream.of("C", "D").skip(1).peek(e -> compareAndSetIO(ref, null, e)).count());
+ }
assertEquals("B", ref.get());
}
}
diff --git a/src/test/java/org/apache/commons/io/function/TestConstants.java b/src/test/java/org/apache/commons/io/function/TestConstants.java
index bafe7ef0..dfea176a 100644
--- a/src/test/java/org/apache/commons/io/function/TestConstants.java
+++ b/src/test/java/org/apache/commons/io/function/TestConstants.java
@@ -44,17 +44,17 @@ class TestConstants {
static IOFunction<Object, Object> THROWING_IO_FUNCTION = t -> throwIOException();
- static IOIntSupplier THROWING_IO_INT_SUPPLIER = () -> throwIOException();
+ static IOIntSupplier THROWING_IO_INT_SUPPLIER = TestConstants::throwIOException;
- static IOLongSupplier THROWING_IO_LONG_SUPPLIER = () -> throwIOException();
+ static IOLongSupplier THROWING_IO_LONG_SUPPLIER = TestConstants::throwIOException;
static IOPredicate<Object> THROWING_IO_PREDICATE = t -> throwIOException();
static IOQuadFunction<Object, Object, Object, Object, Object> THROWING_IO_QUAD_FUNCTION = (t, u, v, w) -> throwIOException();
- static IORunnable THROWING_IO_RUNNABLE = () -> throwIOException();
+ static IORunnable THROWING_IO_RUNNABLE = TestConstants::throwIOException;
- static IOSupplier<Object> THROWING_IO_SUPPLIER = () -> throwIOException();
+ static IOSupplier<Object> THROWING_IO_SUPPLIER = TestConstants::throwIOException;
static IOTriConsumer<Object, Object, Object> THROWING_IO_TRI_CONSUMER = (t, u, v) -> throwIOException();
diff --git a/src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java b/src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java
index a79cb1c9..9ce5d54e 100644
--- a/src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java
@@ -52,7 +52,7 @@ public class BOMInputStreamTest {
/**
* A mock InputStream that expects {@code close()} to be called.
*/
- private static class ExpectCloseInputStream extends InputStream {
+ private static final class ExpectCloseInputStream extends InputStream {
private boolean _closeCalled;
public void assertCloseCalled() {
@@ -415,7 +415,7 @@ public class BOMInputStreamTest {
assertThrows(IllegalArgumentException.class, () -> BOMInputStream.builder()
.setInputStream(createUtf8Input(data, true))
.setInclude(true)
- .setByteOrderMarks(new ByteOrderMark[0])
+ .setByteOrderMarks()
.get()
.close());
}
diff --git a/src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java b/src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java
index 7bc997e0..a8e06b81 100644
--- a/src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java
@@ -32,9 +32,12 @@ import java.util.Random;
import java.util.Set;
import org.apache.commons.io.Charsets;
+import org.apache.commons.io.CharsetsTest;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
public class CharSequenceInputStreamTest {
@@ -78,11 +81,11 @@ public class CharSequenceInputStreamTest {
"Shift_JIS".equalsIgnoreCase(csName);
}
- @Test
- public void testAvailable() throws Exception {
- for (final String csName : Charset.availableCharsets().keySet()) {
- // prevent java.lang.UnsupportedOperationException at sun.nio.cs.ext.ISO2022_CN.newEncoder.
- // also try and avoid the following exception
+ @ParameterizedTest(name = "{0}")
+ @MethodSource(CharsetsTest.AVAIL_CHARSETS)
+ public void testAvailable(final String csName) throws Exception {
+ // prevent java.lang.UnsupportedOperationException at sun.nio.cs.ext.ISO2022_CN.newEncoder.
+ // also try and avoid the following exception
// java.lang.UnsupportedOperationException: null
// at java.nio.CharBuffer.array(CharBuffer.java:940)
// at sun.nio.cs.ext.COMPOUND_TEXT_Encoder.encodeLoop(COMPOUND_TEXT_Encoder.java:75)
@@ -92,14 +95,13 @@ public class CharSequenceInputStreamTest {
// at org.apache.commons.io.input.CharSequenceInputStreamTest.testAvailableRead(CharSequenceInputStreamTest.java:412)
// at org.apache.commons.io.input.CharSequenceInputStreamTest.testAvailable(CharSequenceInputStreamTest.java:424)
- try {
- if (isAvailabilityTestableForCharset(csName)) {
- testAvailableSkip(csName);
- testAvailableRead(csName);
- }
- } catch (final UnsupportedOperationException e){
- fail("Operation not supported for " + csName);
+ try {
+ if (isAvailabilityTestableForCharset(csName)) {
+ testAvailableSkip(csName);
+ testAvailableRead(csName);
}
+ } catch (final UnsupportedOperationException e) {
+ fail("Operation not supported for " + csName);
}
}
@@ -157,13 +159,12 @@ public class CharSequenceInputStreamTest {
// at sun.nio.cs.ext.COMPOUND_TEXT_Encoder.encodeLoop(COMPOUND_TEXT_Encoder.java:75)
// at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:544)
// at org.apache.commons.io.input.CharSequenceInputStream.fillBuffer(CharSequenceInputStream.java:111)
- @Test
- public void testBufferedRead_AvailableCharset() throws IOException {
- for (final String csName : Charset.availableCharsets().keySet()) {
- // prevent java.lang.UnsupportedOperationException at sun.nio.cs.ext.ISO2022_CN.newEncoder.
- if (isAvailabilityTestableForCharset(csName)) {
- testBufferedRead(TEST_STRING, csName);
- }
+ @ParameterizedTest(name = "{0}")
+ @MethodSource(CharsetsTest.AVAIL_CHARSETS)
+ public void testBufferedRead_AvailableCharset(final String csName) throws IOException {
+ // prevent java.lang.UnsupportedOperationException at sun.nio.cs.ext.ISO2022_CN.newEncoder.
+ if (isAvailabilityTestableForCharset(csName)) {
+ testBufferedRead(TEST_STRING, csName);
}
}
diff --git a/src/test/java/org/apache/commons/io/input/ClassLoaderObjectInputStreamTest.java b/src/test/java/org/apache/commons/io/input/ClassLoaderObjectInputStreamTest.java
index 2e8d0f53..3b341ba0 100644
--- a/src/test/java/org/apache/commons/io/input/ClassLoaderObjectInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/ClassLoaderObjectInputStreamTest.java
@@ -43,7 +43,7 @@ public class ClassLoaderObjectInputStreamTest {
A, B, C
}
- private static class Test implements Serializable {
+ private static final class Test implements Serializable {
private static final long serialVersionUID = 1L;
private final int i;
diff --git a/src/test/java/org/apache/commons/io/input/MarkShieldInputStreamTest.java b/src/test/java/org/apache/commons/io/input/MarkShieldInputStreamTest.java
index a72e0f3c..ba0944ef 100644
--- a/src/test/java/org/apache/commons/io/input/MarkShieldInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/MarkShieldInputStreamTest.java
@@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test;
public class MarkShieldInputStreamTest {
- private static class MarkTestableInputStream extends ProxyInputStream {
+ private static final class MarkTestableInputStream extends ProxyInputStream {
int markcount;
int readlimit;
diff --git a/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.java b/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.java
index 517a014e..9123c41f 100644
--- a/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.java
@@ -20,40 +20,57 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import java.io.ByteArrayInputStream;
import java.security.MessageDigest;
-import java.util.Random;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.codec.digest.MessageDigestAlgorithms;
+import org.apache.commons.io.input.MessageDigestCalculatingInputStream.Builder;
import org.junit.jupiter.api.Test;
/**
* Tests {@link MessageDigestCalculatingInputStream}.
*/
+@SuppressWarnings("deprecation")
public class MessageDigestCalculatingInputStreamTest {
- public static byte[] generateRandomByteStream(final int pSize) {
- final byte[] buffer = new byte[pSize];
- final Random rnd = new Random();
- rnd.nextBytes(buffer);
- return buffer;
- }
-
@Test
- public void test() throws Exception {
+ public void testNormalUse() throws Exception {
for (int i = 256; i < 8192; i = i * 2) {
- final byte[] buffer = generateRandomByteStream(i);
- final MessageDigest messageDigest = MessageDigestCalculatingInputStream.getDefaultMessageDigest();
- final byte[] expect = messageDigest.digest(buffer);
+ final byte[] buffer = MessageDigestInputStreamTest.generateRandomByteStream(i);
+ final MessageDigest defaultMessageDigest = MessageDigestCalculatingInputStream.getDefaultMessageDigest();
+ final byte[] defaultExpect = defaultMessageDigest.digest(buffer);
+ // Defaults
try (MessageDigestCalculatingInputStream messageDigestInputStream = new MessageDigestCalculatingInputStream(new ByteArrayInputStream(buffer))) {
messageDigestInputStream.consume();
- assertArrayEquals(expect, messageDigestInputStream.getMessageDigest().digest());
+ assertArrayEquals(defaultExpect, messageDigestInputStream.getMessageDigest().digest());
}
try (MessageDigestCalculatingInputStream messageDigestInputStream = MessageDigestCalculatingInputStream.builder()
.setInputStream(new ByteArrayInputStream(buffer)).get()) {
messageDigestInputStream.consume();
- assertArrayEquals(expect, messageDigestInputStream.getMessageDigest().digest());
+ assertArrayEquals(defaultExpect, messageDigestInputStream.getMessageDigest().digest());
}
try (MessageDigestCalculatingInputStream messageDigestInputStream = MessageDigestCalculatingInputStream.builder().setByteArray(buffer).get()) {
messageDigestInputStream.consume();
- assertArrayEquals(expect, messageDigestInputStream.getMessageDigest().digest());
+ assertArrayEquals(defaultExpect, messageDigestInputStream.getMessageDigest().digest());
+ }
+ // SHA-512
+ final byte[] sha512Expect = DigestUtils.sha512(buffer);
+ {
+ final Builder builder = MessageDigestCalculatingInputStream.builder();
+ builder.setMessageDigest(MessageDigestAlgorithms.SHA_512);
+ builder.setInputStream(new ByteArrayInputStream(buffer));
+ try (MessageDigestCalculatingInputStream messageDigestInputStream = builder.get()) {
+ messageDigestInputStream.consume();
+ assertArrayEquals(sha512Expect, messageDigestInputStream.getMessageDigest().digest());
+ }
+ }
+ {
+ final Builder builder = MessageDigestCalculatingInputStream.builder();
+ builder.setMessageDigest(MessageDigestAlgorithms.SHA_512);
+ builder.setInputStream(new ByteArrayInputStream(buffer));
+ try (MessageDigestCalculatingInputStream messageDigestInputStream = builder.get()) {
+ messageDigestInputStream.consume();
+ assertArrayEquals(sha512Expect, messageDigestInputStream.getMessageDigest().digest());
+ }
}
}
}
diff --git a/src/test/java/org/apache/commons/io/input/MessageDigestInputStreamTest.java b/src/test/java/org/apache/commons/io/input/MessageDigestInputStreamTest.java
new file mode 100644
index 00000000..d41da0b7
--- /dev/null
+++ b/src/test/java/org/apache/commons/io/input/MessageDigestInputStreamTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.io.input;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.ByteArrayInputStream;
+import java.util.Random;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.codec.digest.MessageDigestAlgorithms;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link MessageDigestInputStream}.
+ */
+public class MessageDigestInputStreamTest {
+
+ static byte[] generateRandomByteStream(final int pSize) {
+ final byte[] buffer = new byte[pSize];
+ final Random rnd = new Random();
+ rnd.nextBytes(buffer);
+ return buffer;
+ }
+
+ @Test
+ public void testNoDefault() throws Exception {
+ assertThrows(IllegalStateException.class, () -> MessageDigestInputStream.builder().get());
+ assertThrows(NullPointerException.class, () -> MessageDigestInputStream.builder().setInputStream(new ByteArrayInputStream(new byte[] { 1 })).get());
+ }
+
+ @Test
+ public void testNormalUse() throws Exception {
+ for (int i = 256; i < 8192; i = i * 2) {
+ final byte[] buffer = generateRandomByteStream(i);
+ final byte[] expect = DigestUtils.sha512(buffer);
+ try (MessageDigestInputStream messageDigestInputStream = MessageDigestInputStream.builder().setMessageDigest(MessageDigestAlgorithms.SHA_512)
+ .setInputStream(new ByteArrayInputStream(buffer)).get()) {
+ messageDigestInputStream.consume();
+ assertArrayEquals(expect, messageDigestInputStream.getMessageDigest().digest());
+ }
+ try (MessageDigestInputStream messageDigestInputStream = MessageDigestInputStream.builder().setByteArray(buffer)
+ .setMessageDigest(DigestUtils.getSha512Digest()).get()) {
+ messageDigestInputStream.consume();
+ assertArrayEquals(expect, messageDigestInputStream.getMessageDigest().digest());
+ }
+ }
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java b/src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java
index 0a0e9150..8c099ade 100644
--- a/src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java
@@ -35,7 +35,7 @@ import org.junit.jupiter.api.Test;
*/
public class ObservableInputStreamTest {
- private static class DataViewObserver extends MethodCountObserver {
+ private static final class DataViewObserver extends MethodCountObserver {
private byte[] buffer;
private int lastValue = -1;
private int length = -1;
@@ -55,7 +55,7 @@ public class ObservableInputStreamTest {
}
}
- private static class LengthObserver extends Observer {
+ private static final class LengthObserver extends Observer {
private long total;
@Override
@@ -153,8 +153,7 @@ public class ObservableInputStreamTest {
*/
@Test
public void testDataByteCalled_add() throws Exception {
- final byte[] buffer = MessageDigestCalculatingInputStreamTest
- .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
+ final byte[] buffer = MessageDigestInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
final DataViewObserver lko = new DataViewObserver();
try (ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer))) {
assertEquals(-1, lko.lastValue);
@@ -185,8 +184,7 @@ public class ObservableInputStreamTest {
*/
@Test
public void testDataByteCalled_ctor() throws Exception {
- final byte[] buffer = MessageDigestCalculatingInputStreamTest
- .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
+ final byte[] buffer = MessageDigestInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
final DataViewObserver lko = new DataViewObserver();
try (ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer), lko)) {
assertEquals(-1, lko.lastValue);
@@ -216,10 +214,9 @@ public class ObservableInputStreamTest {
*/
@Test
public void testDataBytesCalled() throws Exception {
- final byte[] buffer = MessageDigestCalculatingInputStreamTest
- .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
+ final byte[] buffer = MessageDigestInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
try (ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
- final ObservableInputStream ois = new ObservableInputStream(bais)) {
+ final ObservableInputStream ois = new ObservableInputStream(bais)) {
final DataViewObserver observer = new DataViewObserver();
final byte[] readBuffer = new byte[23];
assertNull(observer.buffer);
diff --git a/src/test/java/org/apache/commons/io/input/ProxyReaderTest.java b/src/test/java/org/apache/commons/io/input/ProxyReaderTest.java
index b176d480..110d11d2 100644
--- a/src/test/java/org/apache/commons/io/input/ProxyReaderTest.java
+++ b/src/test/java/org/apache/commons/io/input/ProxyReaderTest.java
@@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test;
public class ProxyReaderTest {
/** Custom NullReader implementation. */
- private static class CustomNullReader extends NullReader {
+ private static final class CustomNullReader extends NullReader {
CustomNullReader(final int len) {
super(len);
}
@@ -45,7 +45,7 @@ public class ProxyReaderTest {
}
/** ProxyReader implementation. */
- private static class ProxyReaderImpl extends ProxyReader {
+ private static final class ProxyReaderImpl extends ProxyReader {
ProxyReaderImpl(final Reader proxy) {
super(proxy);
}
diff --git a/src/test/java/org/apache/commons/io/input/TailerTest.java b/src/test/java/org/apache/commons/io/input/TailerTest.java
index f0e1f340..783e1718 100644
--- a/src/test/java/org/apache/commons/io/input/TailerTest.java
+++ b/src/test/java/org/apache/commons/io/input/TailerTest.java
@@ -60,7 +60,7 @@ import org.junit.jupiter.api.io.TempDir;
*/
public class TailerTest {
- private static class NonStandardTailable implements Tailer.Tailable {
+ private static final class NonStandardTailable implements Tailer.Tailable {
private final File file;
@@ -115,7 +115,7 @@ public class TailerTest {
/**
* Test {@link TailerListener} implementation.
*/
- private static class TestTailerListener extends TailerListenerAdapter {
+ private static final class TestTailerListener extends TailerListenerAdapter {
// Must be synchronized because it is written by one thread and read by another
private final List<String> lines = Collections.synchronizedList(new ArrayList<>());
@@ -266,16 +266,6 @@ public class TailerTest {
}
@Test
- public void testCreatorWithDelayAndFromStartWithReopen() throws Exception {
- final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-reopen.txt");
- createFile(file, 0);
- final TestTailerListener listener = new TestTailerListener(1);
- try (Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, false)) {
- validateTailer(listener, file);
- }
- }
-
- @Test
public void testCreateWithDelay() throws Exception {
final File file = new File(temporaryFolder, "tailer-create-with-delay.txt");
createFile(file, 0);
@@ -325,6 +315,16 @@ public class TailerTest {
}
}
+ @Test
+ public void testCreatorWithDelayAndFromStartWithReopen() throws Exception {
+ final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-reopen.txt");
+ createFile(file, 0);
+ final TestTailerListener listener = new TestTailerListener(1);
+ try (Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, false)) {
+ validateTailer(listener, file);
+ }
+ }
+
/*
* Tests [IO-357][Tailer] InterruptedException while the thread is sleeping is silently ignored.
*/
diff --git a/src/test/java/org/apache/commons/io/input/TimestampedObserverTest.java b/src/test/java/org/apache/commons/io/input/TimestampedObserverTest.java
index 54922005..ea37b381 100644
--- a/src/test/java/org/apache/commons/io/input/TimestampedObserverTest.java
+++ b/src/test/java/org/apache/commons/io/input/TimestampedObserverTest.java
@@ -51,7 +51,7 @@ public class TimestampedObserverTest {
assertTrue(timestampedObserver.getOpenToNowDuration().toNanos() > 0);
assertNull(timestampedObserver.getCloseInstant());
assertFalse(timestampedObserver.isClosed());
- final byte[] buffer = MessageDigestCalculatingInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
+ final byte[] buffer = MessageDigestInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
try (ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer), timestampedObserver)) {
assertTrue(timestampedObserver.getOpenInstant().isAfter(before));
assertTrue(timestampedObserver.getOpenToNowDuration().toNanos() > 0);
@@ -68,7 +68,7 @@ public class TimestampedObserverTest {
@Test
public void testExample() throws IOException {
final TimestampedObserver timestampedObserver = new TimestampedObserver();
- final byte[] buffer = MessageDigestCalculatingInputStreamTest
+ final byte[] buffer = MessageDigestInputStreamTest
.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
try (ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer),
timestampedObserver)) {
diff --git a/src/test/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStreamTest.java b/src/test/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStreamTest.java
index f7fcba81..d2e969ca 100644
--- a/src/test/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/UnsynchronizedBufferedInputStreamTest.java
@@ -21,7 +21,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -31,6 +30,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedBufferedInputStream.Builder;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@@ -50,12 +50,16 @@ public class UnsynchronizedBufferedInputStreamTest {
Path fileName;
- private BufferedInputStream is;
+ private UnsynchronizedBufferedInputStream is;
private InputStream isFile;
byte[] ibuf = new byte[BUFFER_SIZE];
+ private Builder builder() {
+ return new UnsynchronizedBufferedInputStream.Builder();
+ }
+
/**
* Sets up the fixture, for example, open a network connection. This method is called before a test is executed.
*
@@ -67,7 +71,7 @@ public class UnsynchronizedBufferedInputStreamTest {
Files.write(fileName, DATA.getBytes(StandardCharsets.UTF_8));
isFile = Files.newInputStream(fileName);
- is = new BufferedInputStream(isFile);
+ is = builder().setInputStream(isFile).get();
}
/**
@@ -82,7 +86,7 @@ public class UnsynchronizedBufferedInputStreamTest {
}
/**
- * Tests java.io.BufferedInputStream#available()
+ * Tests {@link UnsynchronizedBufferedInputStream#available()}.
*
* @throws IOException Thrown on test failure.
*/
@@ -91,7 +95,8 @@ public class UnsynchronizedBufferedInputStreamTest {
assertEquals(DATA.length(), is.available(), "Returned incorrect number of available bytes");
// Test that a closed stream throws an IOE for available()
- final BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(new byte[] { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' }));
+ final UnsynchronizedBufferedInputStream bis = builder()
+ .setInputStream(new ByteArrayInputStream(new byte[] { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' })).get();
final int available = bis.available();
bis.close();
assertTrue(available != 0);
@@ -100,18 +105,13 @@ public class UnsynchronizedBufferedInputStreamTest {
}
/**
- * Tests java.io.BufferedInputStream#close()
+ * Tests {@link UnsynchronizedBufferedInputStream#close()}.
*
* @throws IOException Thrown on test failure.
*/
@Test
public void test_close() throws IOException {
- new BufferedInputStream(isFile).close();
-
- // regression for HARMONY-667
- try (BufferedInputStream buf = new BufferedInputStream(null, 5)) {
- // closes
- }
+ builder().setInputStream(isFile).get().close();
try (InputStream in = new InputStream() {
Object lock = new Object();
@@ -140,7 +140,7 @@ public class UnsynchronizedBufferedInputStreamTest {
return 1;
}
}) {
- final BufferedInputStream bufin = new BufferedInputStream(in);
+ final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(in).get();
final Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
@@ -155,28 +155,24 @@ public class UnsynchronizedBufferedInputStreamTest {
}
/*
- * Tests java.io.BufferedInputStream(InputStream)
+ * Tests {@link UnsynchronizedBufferedInputStream#Builder()}.
*/
@Test
- public void test_ConstructorLjava_io_InputStream() throws IOException {
- try (BufferedInputStream str = new BufferedInputStream(null)) {
- assertThrows(IOException.class, () -> str.read(), "Expected an IOException");
- }
+ public void test_ConstructorLjava_io_InputStream() {
+ assertThrows(NullPointerException.class, () -> builder().setInputStream(null).get());
}
/*
- * Tests java.io.BufferedInputStream(InputStream)
+ * Tests {@link UnsynchronizedBufferedInputStream#Builder()}.
*/
@Test
public void test_ConstructorLjava_io_InputStreamI() throws IOException {
- try (BufferedInputStream str = new BufferedInputStream(null, 1)) {
- assertThrows(IOException.class, () -> str.read(), "Expected an IOException");
- }
+ assertThrows(NullPointerException.class, () -> builder().setInputStream(null).setBufferSize(1).get());
- // Test for method java.io.BufferedInputStream(java.io.InputStream, int)
+ // Test for method UnsynchronizedBufferedInputStream(InputStream, int)
// Create buffer with exact size of file
- is = new BufferedInputStream(isFile, this.DATA.length());
+ is = builder().setInputStream(isFile).setBufferSize(DATA.length()).get();
// Ensure buffer gets filled by evaluating one read
is.read();
// Close underlying FileInputStream, all but 1 buffered bytes should
@@ -184,16 +180,17 @@ public class UnsynchronizedBufferedInputStreamTest {
isFile.close();
// Read the remaining buffered characters, no IOException should
// occur.
- is.skip(this.DATA.length() - 2);
+ is.skip(DATA.length() - 2);
is.read();
// is.read should now throw an exception because it will have to be filled.
assertThrows(IOException.class, () -> is.read());
- assertThrows(NullPointerException.class, () -> UnsynchronizedBufferedInputStream.builder().setInputStream(null).setBufferSize(100).get());
+ assertThrows(NullPointerException.class, () -> builder().setInputStream(null).setBufferSize(100).get());
+ assertThrows(NullPointerException.class, () -> builder().setInputStream(null));
}
/**
- * Tests java.io.BufferedInputStream#mark(int)
+ * Tests {@link UnsynchronizedBufferedInputStream#mark(int)}.
*
* @throws IOException Thrown on test failure.
*/
@@ -213,21 +210,21 @@ public class UnsynchronizedBufferedInputStreamTest {
for (int i = 0; i < 256; i++) {
bytes[i] = (byte) i;
}
- InputStream in = new BufferedInputStream(new ByteArrayInputStream(bytes), 12);
+ InputStream in = builder().setInputStream(new ByteArrayInputStream(bytes)).setBufferSize(12).get();
in.skip(6);
in.mark(14);
in.read(new byte[14], 0, 14);
in.reset();
assertTrue(in.read() == 6 && in.read() == 7, "Wrong bytes");
- in = new BufferedInputStream(new ByteArrayInputStream(bytes), 12);
+ in = builder().setInputStream(new ByteArrayInputStream(bytes)).setBufferSize(12).get();
in.skip(6);
in.mark(8);
in.skip(7);
in.reset();
assertTrue(in.read() == 6 && in.read() == 7, "Wrong bytes 2");
- BufferedInputStream buf = new BufferedInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 }), 2);
+ UnsynchronizedBufferedInputStream buf = builder().setInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 })).setBufferSize(2).get();
buf.mark(3);
bytes = new byte[3];
int result = buf.read(bytes);
@@ -237,7 +234,7 @@ public class UnsynchronizedBufferedInputStreamTest {
assertEquals(2, bytes[2], "Assert 2:");
assertEquals(3, buf.read(), "Assert 3:");
- buf = new BufferedInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 }), 2);
+ buf = builder().setInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 })).setBufferSize(2).get();
buf.mark(3);
bytes = new byte[4];
result = buf.read(bytes);
@@ -249,14 +246,14 @@ public class UnsynchronizedBufferedInputStreamTest {
assertEquals(4, buf.read(), "Assert 8:");
assertEquals(-1, buf.read(), "Assert 9:");
- buf = new BufferedInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 }), 2);
+ buf = builder().setInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 })).setBufferSize(2).get();
buf.mark(Integer.MAX_VALUE);
buf.read();
buf.close();
}
/**
- * Tests java.io.BufferedInputStream#markSupported()
+ * Tests {@link UnsynchronizedBufferedInputStream#markSupported()}.
*/
@Test
public void test_markSupported() {
@@ -264,7 +261,7 @@ public class UnsynchronizedBufferedInputStreamTest {
}
/**
- * Tests java.io.BufferedInputStream#read()
+ * Tests {@link UnsynchronizedBufferedInputStream#read()}.
*
* @throws IOException Thrown on test failure.
*/
@@ -278,7 +275,7 @@ public class UnsynchronizedBufferedInputStreamTest {
for (int i = 0; i < 256; i++) {
bytes[i] = (byte) i;
}
- final InputStream in = new BufferedInputStream(new ByteArrayInputStream(bytes), 12);
+ final InputStream in = builder().setInputStream(new ByteArrayInputStream(bytes)).setBufferSize(12).get();
assertEquals(0, in.read(), "Wrong initial byte"); // Fill the buffer
final byte[] buf = new byte[14];
in.read(buf, 0, 14); // Read greater than the buffer
@@ -287,7 +284,7 @@ public class UnsynchronizedBufferedInputStreamTest {
}
/**
- * Tests java.io.BufferedInputStream#read(byte[], int, int)
+ * Tests {@link UnsynchronizedBufferedInputStream#read(byte[], int, int)}.
*
* @throws IOException Thrown on test failure.
*/
@@ -299,7 +296,7 @@ public class UnsynchronizedBufferedInputStreamTest {
is.read(buf1, 0, buf1.length);
assertTrue(new String(buf1, 0, buf1.length).equals(DATA.substring(3000, 3100)), "Failed to read correct data");
- try (BufferedInputStream bufin = new BufferedInputStream(new InputStream() {
+ try (UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new InputStream() {
int size = 2, pos = 0;
byte[] contents = new byte[size];
@@ -330,7 +327,7 @@ public class UnsynchronizedBufferedInputStreamTest {
pos += toRead;
return toRead;
}
- })) {
+ }).get()) {
bufin.read();
final int result = bufin.read(new byte[2], 0, 2);
assertEquals(1, result, () -> "Incorrect result: " + result);
@@ -338,26 +335,7 @@ public class UnsynchronizedBufferedInputStreamTest {
}
/**
- * Tests java.io.BufferedInputStream#read(byte[], int, int)
- *
- * @throws IOException Thrown on test failure.
- */
- @Test
- public void test_read$BII_Exception() throws IOException {
- final BufferedInputStream bis = new BufferedInputStream(null);
- assertThrows(NullPointerException.class, () -> bis.read(null, -1, -1));
-
- assertThrows(IndexOutOfBoundsException.class, () -> bis.read(new byte[0], -1, -1));
- assertThrows(IndexOutOfBoundsException.class, () -> bis.read(new byte[0], 1, -1));
- assertThrows(IndexOutOfBoundsException.class, () -> bis.read(new byte[0], 1, 1));
-
- bis.close();
-
- assertThrows(IOException.class, () -> bis.read(null, -1, -1));
- }
-
- /**
- * Tests java.io.BufferedInputStream#reset()
+ * Tests {@link UnsynchronizedBufferedInputStream#reset()}.
*
* @throws IOException Thrown on test failure.
*/
@@ -372,7 +350,7 @@ public class UnsynchronizedBufferedInputStreamTest {
is.reset();
assertTrue(new String(buf1, 0, buf1.length).equals(new String(buf2, 0, buf2.length)), "Reset failed");
- final BufferedInputStream bIn = new BufferedInputStream(new ByteArrayInputStream("1234567890".getBytes()));
+ final UnsynchronizedBufferedInputStream bIn = builder().setInputStream(new ByteArrayInputStream("1234567890".getBytes())).get();
bIn.mark(10);
for (int i = 0; i < 11; i++) {
bIn.read();
@@ -381,36 +359,14 @@ public class UnsynchronizedBufferedInputStreamTest {
}
/**
- * Tests java.io.BufferedInputStream#reset()
- *
- * @throws IOException Thrown on test failure.
- */
- @Test
- public void test_reset_Exception() throws IOException {
- final BufferedInputStream bis = new BufferedInputStream(null);
-
- // throws IOException with message "Mark has been invalidated"
- assertThrows(IOException.class, () -> bis.reset());
-
- // does not throw IOException
- bis.mark(1);
- bis.reset();
-
- bis.close();
-
- // throws IOException with message "stream is closed"
- assertThrows(IOException.class, () -> bis.reset());
- }
-
- /**
- * Tests java.io.BufferedInputStream#reset()
+ * Tests {@link UnsynchronizedBufferedInputStream#reset()}.
*
* @throws IOException Thrown on test failure.
*/
@Test
public void test_reset_scenario1() throws IOException {
final byte[] input = "12345678900".getBytes();
- final BufferedInputStream bufin = new BufferedInputStream(new ByteArrayInputStream(input));
+ final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new ByteArrayInputStream(input)).get();
bufin.read();
bufin.mark(5);
bufin.skip(5);
@@ -418,33 +374,31 @@ public class UnsynchronizedBufferedInputStreamTest {
}
/**
- * Tests java.io.BufferedInputStream#reset()
+ * Tests {@link UnsynchronizedBufferedInputStream#reset()}.
*
* @throws IOException Thrown on test failure.
*/
@Test
public void test_reset_scenario2() throws IOException {
final byte[] input = "12345678900".getBytes();
- final BufferedInputStream bufin = new BufferedInputStream(new ByteArrayInputStream(input));
+ final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new ByteArrayInputStream(input)).get();
bufin.mark(5);
bufin.skip(6);
bufin.reset();
}
/**
- * Tests java.io.BufferedInputStream#skip(long)
+ * Tests {@link UnsynchronizedBufferedInputStream#skip(long)}.
*
* @throws IOException Thrown on test failure.
*/
@Test
public void test_skip_NullInputStream() throws IOException {
- try (BufferedInputStream buf = new BufferedInputStream(null, 5)) {
- assertEquals(0, buf.skip(0));
- }
+ assertThrows(NullPointerException.class, () -> builder().setInputStream(null).setBufferSize(5).get());
}
/**
- * Tests java.io.BufferedInputStream#skip(long)
+ * Tests {@link UnsynchronizedBufferedInputStream#skip(long)}.
*
* @throws IOException Thrown on test failure.
*/
@@ -456,10 +410,5 @@ public class UnsynchronizedBufferedInputStreamTest {
is.read(buf1, 0, buf1.length);
is.reset();
assertTrue(new String(buf1, 0, buf1.length).equals(DATA.substring(1000, 1010)), "Failed to skip to correct position");
-
- // regression for HARMONY-667
- try (BufferedInputStream buf = new BufferedInputStream(null, 5)) {
- assertThrows(IOException.class, () -> buf.skip(10));
- }
}
}
diff --git a/src/test/java/org/apache/commons/io/input/XmlStreamReaderTest.java b/src/test/java/org/apache/commons/io/input/XmlStreamReaderTest.java
index 555cf7ca..63d587a8 100644
--- a/src/test/java/org/apache/commons/io/input/XmlStreamReaderTest.java
+++ b/src/test/java/org/apache/commons/io/input/XmlStreamReaderTest.java
@@ -30,6 +30,7 @@ import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLConnection;
+import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -37,10 +38,15 @@ import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.MessageFormat;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
+import org.apache.commons.io.CharsetsTest;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.function.IOFunction;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
import org.junitpioneer.jupiter.DefaultLocale;
public class XmlStreamReaderTest {
@@ -162,6 +168,14 @@ public class XmlStreamReaderTest {
return new ByteArrayInputStream(baos.toByteArray());
}
+ private void parseCharset(final String hdr, final String enc, final IOFunction<InputStream, XmlStreamReader> factory) throws Exception {
+ try (final InputStream stream = new ByteArrayInputStream(hdr.getBytes(StandardCharsets.UTF_8))) {
+ try (final XmlStreamReader xml = factory.apply(stream)) {
+ assertEquals(enc.toUpperCase(Locale.ROOT), xml.getEncoding(), enc);
+ }
+ }
+ }
+
public void testAlternateDefaultEncoding(final String contentType, final String bomEnc, final String streamEnc, final String prologEnc,
final String alternateEnc) throws Exception {
try (InputStream is = getXmlInputStream(bomEnc, prologEnc == null ? XML1 : XML3, streamEnc, prologEnc);
@@ -276,6 +290,8 @@ public class XmlStreamReaderTest {
assertThrows(NullPointerException.class, () -> new XmlStreamReader((URL) null));
}
+ // XML Stream generator
+
@Test
public void testEncodingAttributeXML() throws Exception {
try (InputStream is = new ByteArrayInputStream(ENCODING_ATTRIBUTE_XML.getBytes(StandardCharsets.UTF_8));
@@ -294,8 +310,6 @@ public class XmlStreamReaderTest {
}
}
- // XML Stream generator
-
@Test
public void testHttp() throws Exception {
// niallp 2010-10-06 - remove following 2 tests - I reinstated
@@ -431,6 +445,20 @@ public class XmlStreamReaderTest {
}
}
+ @ParameterizedTest(name = "{0}")
+ @MethodSource(CharsetsTest.AVAIL_CHARSETS)
+ public void testIO_815(final String csName) throws Exception {
+ final MessageFormat fmt = new MessageFormat("<?xml version=\"1.0\" encoding=''{0}''?>\n<root>text</root>");
+ final IOFunction<InputStream, XmlStreamReader> factoryCtor = XmlStreamReader::new;
+ final IOFunction<InputStream, XmlStreamReader> factoryBuilder = stream -> XmlStreamReader.builder().setInputStream(stream).get();
+ parseCharset(fmt.format(new Object[] { csName }), csName, factoryCtor);
+ parseCharset(fmt.format(new Object[] { csName }), csName, factoryBuilder);
+ for (final String alias : Charset.forName(csName).aliases()) {
+ parseCharset(fmt.format(new Object[] { alias }), alias, factoryCtor);
+ parseCharset(fmt.format(new Object[] { alias }), alias, factoryBuilder);
+ }
+ }
+
// Turkish language has specific rules to convert dotted and dotless i character.
@Test
@DefaultLocale(language = "tr")
diff --git a/src/test/java/org/apache/commons/io/input/XmlStreamReaderUtilitiesTest.java b/src/test/java/org/apache/commons/io/input/XmlStreamReaderUtilitiesTest.java
index e2cd2e68..821df8a6 100644
--- a/src/test/java/org/apache/commons/io/input/XmlStreamReaderUtilitiesTest.java
+++ b/src/test/java/org/apache/commons/io/input/XmlStreamReaderUtilitiesTest.java
@@ -31,7 +31,7 @@ import org.junit.jupiter.api.Test;
public class XmlStreamReaderUtilitiesTest {
/** Mock {@link XmlStreamReader} implementation */
- private static class MockXmlStreamReader extends XmlStreamReader {
+ private static final class MockXmlStreamReader extends XmlStreamReader {
MockXmlStreamReader(final String defaultEncoding) throws IOException {
super(CharSequenceInputStream.builder().setCharSequence("").get(), null, true, defaultEncoding);
}
diff --git a/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderUtilitiesCompatibilityTest.java b/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderUtilitiesCompatibilityTest.java
index ee4310a8..acfeb742 100644
--- a/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderUtilitiesCompatibilityTest.java
+++ b/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderUtilitiesCompatibilityTest.java
@@ -27,7 +27,7 @@ import org.apache.commons.io.input.XmlStreamReaderUtilitiesTest;
public class XmlStreamReaderUtilitiesCompatibilityTest extends XmlStreamReaderUtilitiesTest {
/** Mock {@link XmlStreamReader} implementation */
- private static class MockXmlStreamReader extends XmlStreamReader {
+ private static final class MockXmlStreamReader extends XmlStreamReader {
MockXmlStreamReader(final String defaultEncoding) throws IOException {
super(CharSequenceInputStream.builder().setCharSequence("").get(), null, true, defaultEncoding);
}
diff --git a/src/test/java/org/apache/commons/io/jmh/PathUtilsContentEqualsBenchmark.java b/src/test/java/org/apache/commons/io/jmh/PathUtilsContentEqualsBenchmark.java
new file mode 100644
index 00000000..20e49e71
--- /dev/null
+++ b/src/test/java/org/apache/commons/io/jmh/PathUtilsContentEqualsBenchmark.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.io.jmh;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.io.RandomAccessFileMode;
+import org.apache.commons.io.RandomAccessFiles;
+import org.apache.commons.io.file.PathUtils;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.infra.Blackhole;
+
+/**
+ * Test different implementations of {@link PathUtils#fileContentEquals(Path, Path)}.
+ *
+ * <pre>
+ * Benchmark Mode Cnt Score Error Units
+ * PathUtilsContentEqualsBenchmark.testCurrent_fileContentEquals avgt 5 4.538 ▒ 1.010 ms/op
+ * PathUtilsContentEqualsBenchmark.testCurrent_fileContentEquals_Blackhole avgt 5 110.627 ▒ 30.317 ms/op
+ * PathUtilsContentEqualsBenchmark.testProposal_contentEquals avgt 5 1.812 ▒ 0.634 ms/op
+ * PathUtilsContentEqualsBenchmark.testProposal_contentEquals_Blackhole avgt 5 43.521 ▒ 6.762 ms/op
+ * </pre>
+ */
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Thread)
+@Warmup(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS)
+@Measurement(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS)
+@Fork(value = 1, jvmArgs = { "-server" })
+public class PathUtilsContentEqualsBenchmark {
+
+ private static final Path bigFile1;
+ private static final Path bigFile2;
+
+ static {
+ // Set up test fixtures
+ try {
+ bigFile1 = Files.createTempFile(PathUtilsContentEqualsBenchmark.class.getSimpleName(), "-1.bin");
+ bigFile2 = Files.createTempFile(PathUtilsContentEqualsBenchmark.class.getSimpleName(), "-2.bin");
+ final int newLength = 1_000_000;
+ final byte[] bytes1 = new byte[newLength];
+ Arrays.fill(bytes1, (byte) 1);
+ Files.write(bigFile1, bytes1);
+ Files.copy(bigFile1, bigFile2, StandardCopyOption.REPLACE_EXISTING);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ public static boolean newFileContentEquals(final Path path1, final Path path2) throws IOException {
+ try (RandomAccessFile raf1 = RandomAccessFileMode.READ_ONLY.create(path1);
+ RandomAccessFile raf2 = RandomAccessFileMode.READ_ONLY.create(path2)) {
+ return RandomAccessFiles.contentEquals(raf1, raf2);
+ }
+ }
+
+ @Benchmark
+ public boolean[] testCurrent_fileContentEquals() throws IOException {
+ final boolean[] res = new boolean[1];
+ res[0] = PathUtils.fileContentEquals(bigFile1, bigFile2);
+ return res;
+ }
+
+ @Benchmark
+ public void testCurrent_fileContentEquals_Blackhole(final Blackhole blackhole) throws IOException {
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 5; j++) {
+ blackhole.consume(PathUtils.fileContentEquals(bigFile1, bigFile2));
+ }
+ }
+ }
+
+ @Benchmark
+ public boolean[] testProposal_contentEquals() throws IOException {
+ final boolean[] res = new boolean[1];
+ res[0] = newFileContentEquals(bigFile1, bigFile2);
+ return res;
+ }
+
+ @Benchmark
+ public void testProposal_contentEquals_Blackhole(final Blackhole blackhole) throws IOException {
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 5; j++) {
+ blackhole.consume(newFileContentEquals(bigFile1, bigFile2));
+ }
+ }
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/io/output/ByteArrayOutputStreamTest.java b/src/test/java/org/apache/commons/io/output/ByteArrayOutputStreamTest.java
index 2d11e58c..a65961d0 100644
--- a/src/test/java/org/apache/commons/io/output/ByteArrayOutputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/output/ByteArrayOutputStreamTest.java
@@ -46,7 +46,7 @@ public class ByteArrayOutputStreamTest {
T newInstance(final int size);
}
- private static class ByteArrayOutputStreamFactory implements BAOSFactory<ByteArrayOutputStream> {
+ private static final class ByteArrayOutputStreamFactory implements BAOSFactory<ByteArrayOutputStream> {
@Override
public ByteArrayOutputStream newInstance() {
return new ByteArrayOutputStream();
@@ -58,7 +58,7 @@ public class ByteArrayOutputStreamTest {
}
}
- private static class UnsynchronizedByteArrayOutputStreamFactory implements BAOSFactory<UnsynchronizedByteArrayOutputStream> {
+ private static final class UnsynchronizedByteArrayOutputStreamFactory implements BAOSFactory<UnsynchronizedByteArrayOutputStream> {
@Override
public UnsynchronizedByteArrayOutputStream newInstance() {
return new UnsynchronizedByteArrayOutputStream();
diff --git a/src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java b/src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java
index dd1299e0..080a4927 100644
--- a/src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java
@@ -33,7 +33,7 @@ import org.junit.jupiter.api.Test;
public class ThresholdingOutputStreamTest {
@Test
- public void testSetByteCount_Stream() throws Exception {
+ public void testSetByteCount_OutputStream() throws Exception {
final AtomicBoolean reached = new AtomicBoolean(false);
try (ThresholdingOutputStream tos = new ThresholdingOutputStream(3) {
{
@@ -41,7 +41,7 @@ public class ThresholdingOutputStreamTest {
}
@Override
- protected OutputStream getStream() throws IOException {
+ protected OutputStream getOutputStream() throws IOException {
return new ByteArrayOutputStream(4);
}
@@ -58,7 +58,7 @@ public class ThresholdingOutputStreamTest {
}
@Test
- public void testSetByteCount_OutputStream() throws Exception {
+ public void testSetByteCount_Stream() throws Exception {
final AtomicBoolean reached = new AtomicBoolean(false);
try (ThresholdingOutputStream tos = new ThresholdingOutputStream(3) {
{
@@ -66,7 +66,7 @@ public class ThresholdingOutputStreamTest {
}
@Override
- protected OutputStream getOutputStream() throws IOException {
+ protected OutputStream getStream() throws IOException {
return new ByteArrayOutputStream(4);
}
diff --git a/src/test/java/org/apache/commons/io/test/TestUtils.java b/src/test/java/org/apache/commons/io/test/TestUtils.java
index 0620603d..3a01f702 100644
--- a/src/test/java/org/apache/commons/io/test/TestUtils.java
+++ b/src/test/java/org/apache/commons/io/test/TestUtils.java
@@ -224,11 +224,11 @@ public abstract class TestUtils {
}
}
- public static File newFile(final File testDirectory, final String filename) throws IOException {
- final File destination = new File(testDirectory, filename);
+ public static File newFile(final File testDirectory, final String fileName) throws IOException {
+ final File destination = new File(testDirectory, fileName);
/*
- assertTrue( filename + "Test output data file shouldn't previously exist",
- !destination.exists() );
+ assertTrue(fileName + "Test output data file shouldn't previously exist",
+ !destination.exists());
*/
if (destination.exists()) {
FileUtils.forceDelete(destination);
diff --git a/src/test/resources/org/apache/commons/io/test-file-empty2.bin b/src/test/resources/org/apache/commons/io/test-file-empty2.bin
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/test/resources/org/apache/commons/io/test-file-empty2.bin