Skip to content

Commit b99664a

Browse files
committed
Merge remote-tracking branch 'apache/master' into feat/file-systems
2 parents 26dd573 + 4dc17b6 commit b99664a

File tree

7 files changed

+215
-70
lines changed

7 files changed

+215
-70
lines changed

.github/workflows/codeql-analysis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ jobs:
6262
6363
# Initializes the CodeQL tools for scanning.
6464
- name: Initialize CodeQL
65-
uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5
65+
uses: github/codeql-action/init@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # 3.29.5
6666
with:
6767
languages: ${{ matrix.language }}
6868
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -73,7 +73,7 @@ jobs:
7373
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
7474
# If this step fails, then you should remove it and run the build manually (see below)
7575
- name: Autobuild
76-
uses: github/codeql-action/autobuild@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5
76+
uses: github/codeql-action/autobuild@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # 3.29.5
7777

7878
# ℹ️ Command-line programs to run using the OS shell.
7979
# 📚 https://git.io/JvXDl
@@ -87,4 +87,4 @@ jobs:
8787
# make release
8888

8989
- name: Perform CodeQL Analysis
90-
uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5
90+
uses: github/codeql-action/analyze@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # 3.29.5

.github/workflows/scorecards-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,6 @@ jobs:
6666
retention-days: 5
6767

6868
- name: "Upload to code-scanning"
69-
uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5
69+
uses: github/codeql-action/upload-sarif@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # 3.29.5
7070
with:
7171
sarif_file: results.sarif

src/changes/changes.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ The <action> type attribute can be add,update,fix,remove.
5050
<action type="fix" dev="ggregory" due-to="Gary Gregory">When testing on Java 21 and up, enable -XX:+EnableDynamicAgentLoading.</action>
5151
<action type="fix" dev="ggregory" due-to="Gary Gregory">When testing on Java 24 and up, don't fail FileUtilsListFilesTest for a different behavior in the JRE.</action>
5252
<action type="fix" dev="ggregory" due-to="Stanislav Fort, Gary Gregory">ValidatingObjectInputStream does not validate dynamic proxy interfaces.</action>
53+
<action type="fix" dev="pkarwasz" due-to="Piotr P. Karwasz">BoundedInputStream.getRemaining() now reports Long.MAX_VALUE instead of 0 when no limit is set.</action>
54+
<action type="fix" dev="pkarwasz" due-to="Piotr P. Karwasz">BoundedInputStream.available() correctly accounts for the maximum read limit.</action>
55+
<action type="fix" dev="ggregory" due-to="Gary Gregory, Piotr P. Karwasz">Deprecate IOUtils.readFully(InputStream, int) in favor of toByteArray(InputStream, int).</action>
5356
<!-- ADD -->
5457
<action dev="ggregory" type="add" due-to="strangelookingnerd, Gary Gregory">FileUtils#byteCountToDisplaySize() supports Zettabyte, Yottabyte, Ronnabyte and Quettabyte #763.</action>
5558
<action dev="ggregory" type="add" due-to="strangelookingnerd, Gary Gregory">Add org.apache.commons.io.FileUtils.ONE_RB #763.</action>
@@ -61,7 +64,9 @@ The <action> type attribute can be add,update,fix,remove.
6164
<!-- UPDATE -->
6265
<action type="update" dev="ggregory" due-to="Gary Gregory, Dependabot">Bump org.apache.commons:commons-parent from 85 to 87 #774.</action>
6366
<action type="update" dev="ggregory" due-to="Gary Gregory">[test] Bump commons-codec:commons-codec from 1.18.0 to 1.19.0.</action>
64-
<action type="update" dev="ggregory" due-to="Gary Gregory">[test] Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #769.</action>
67+
<action type="update" dev="ggregory" due-to="Gary Gregory">[test] Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #769.</action>
68+
<!-- REMOVE -->
69+
<action type="remove" dev="pkarwasz" due-to="Piotr P. Karwasz">Inline private constant field ProxyInputStream.exceptionHandler #780.</action>
6570
</release>
6671
<release version="2.20.0" date="2025-07-13" description="Version 2.20.0: Java 8 or later is required.">
6772
<!-- FIX -->

src/main/java/org/apache/commons/io/IOUtils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2030,11 +2030,11 @@ public static void readFully(final InputStream input, final byte[] buffer, final
20302030
* @throws IllegalArgumentException if length is negative.
20312031
* @throws EOFException if the number of bytes read was incorrect.
20322032
* @since 2.5
2033+
* @deprecated Use {@link #toByteArray(InputStream, int)}.
20332034
*/
2035+
@Deprecated
20342036
public static byte[] readFully(final InputStream input, final int length) throws IOException {
2035-
final byte[] buffer = byteArray(length);
2036-
readFully(input, buffer, 0, buffer.length);
2037-
return buffer;
2037+
return toByteArray(input, length);
20382038
}
20392039

20402040
/**

src/main/java/org/apache/commons/io/input/BoundedInputStream.java

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@
7373
* .get();
7474
* }
7575
* </pre>
76-
* <h2>Listening for the max count reached</h2>
76+
* <h2>Listening for the maximum count reached</h2>
7777
* <pre>{@code
7878
* BoundedInputStream s = BoundedInputStream.builder()
7979
* .setPath(Paths.get("MyFile.xml"))
8080
* .setMaxCount(1024)
81-
* .setOnMaxCount((max, count) -> System.out.printf("Max count %,d reached with a last read count of %,d%n", max, count))
81+
* .setOnMaxCount((max, count) -> System.out.printf("Maximum count %,d reached with a last read count of %,d%n", max, count))
8282
* .get();
8383
* }
8484
* </pre>
@@ -98,7 +98,7 @@ abstract static class AbstractBuilder<T extends AbstractBuilder<T>> extends Prox
9898
/** The current count of bytes counted. */
9999
private long count;
100100

101-
/** The max count of bytes to read. */
101+
/** The maximum count of bytes to read. */
102102
private long maxCount = EOF;
103103

104104
private IOBiConsumer<Long, Long> onMaxCount = IOBiConsumer.noop();
@@ -156,7 +156,8 @@ public T setMaxCount(final long maxCount) {
156156
/**
157157
* Sets the default {@link BoundedInputStream#onMaxLength(long, long)} behavior, {@code null} resets to a NOOP.
158158
* <p>
159-
* The first Long is the max count of bytes to read. The second Long is the count of bytes read.
159+
* The first Long is the number of bytes remaining to read before the maximum is reached count of bytes to read. The second Long is the count of bytes
160+
* read.
160161
* </p>
161162
* <p>
162163
* This does <em>not</em> override a {@code BoundedInputStream} subclass' implementation of the {@link BoundedInputStream#onMaxLength(long, long)}
@@ -299,7 +300,7 @@ public static Builder builder() {
299300
/** The current mark. */
300301
private long mark;
301302

302-
/** The max count of bytes to read. */
303+
/** The maximum count of bytes to read. */
303304
private final long maxCount;
304305

305306
private final IOBiConsumer<Long, Long> onMaxCount;
@@ -350,15 +351,15 @@ public BoundedInputStream(final InputStream in) {
350351
*/
351352
@Deprecated
352353
public BoundedInputStream(final InputStream inputStream, final long maxCount) {
353-
// Some badly designed methods - e.g. the Servlet API - overload length
354+
// Some badly designed methods, for example the Servlet API, overload length
354355
// such that "-1" means stream finished
355356
this(inputStream, builder().setMaxCount(maxCount));
356357
}
357358

358359
/**
359360
* Adds the number of read bytes to the count.
360361
*
361-
* @param n number of bytes read, or -1 if no more bytes are available
362+
* @param n number of bytes read, or -1 if no more bytes are available.
362363
* @throws IOException Not thrown here but subclasses may throw.
363364
* @since 2.0
364365
*/
@@ -370,16 +371,11 @@ protected synchronized void afterRead(final int n) throws IOException {
370371
super.afterRead(n);
371372
}
372373

373-
/**
374-
* {@inheritDoc}
375-
*/
376374
@Override
377375
public int available() throws IOException {
378-
if (isMaxCount()) {
379-
onMaxLength(maxCount, getCount());
380-
return 0;
381-
}
382-
return in.available();
376+
// Safe cast: value is between 0 and Integer.MAX_VALUE
377+
final int remaining = (int) Math.min(getRemaining(), Integer.MAX_VALUE);
378+
return Math.min(super.available(), remaining);
383379
}
384380

385381
/**
@@ -405,19 +401,19 @@ public synchronized long getCount() {
405401
}
406402

407403
/**
408-
* Gets the max count of bytes to read.
404+
* Gets the maximum number of bytes to read.
409405
*
410-
* @return The max count of bytes to read.
406+
* @return The maximum number of bytes to read, or {@value IOUtils#EOF} if unbounded.
411407
* @since 2.16.0
412408
*/
413409
public long getMaxCount() {
414410
return maxCount;
415411
}
416412

417413
/**
418-
* Gets the max count of bytes to read.
414+
* Gets the maximum count of bytes to read.
419415
*
420-
* @return The max count of bytes to read.
416+
* @return The maximum count of bytes to read.
421417
* @since 2.12.0
422418
* @deprecated Use {@link #getMaxCount()}.
423419
*/
@@ -427,13 +423,21 @@ public long getMaxLength() {
427423
}
428424

429425
/**
430-
* Gets how many bytes remain to read.
426+
* Gets the number of bytes remaining to read before the maximum is reached.
427+
*
428+
* <p>
429+
* This method does <strong>not</strong> report the bytes available in the
430+
* underlying stream; it only reflects the remaining allowance imposed by this
431+
* {@code BoundedInputStream}.
432+
* </p>
431433
*
432-
* @return bytes how many bytes remain to read.
434+
* @return The number of bytes remaining to read before the maximum is reached,
435+
* or {@link Long#MAX_VALUE} if no bound is set.
433436
* @since 2.16.0
434437
*/
435438
public long getRemaining() {
436-
return Math.max(0, getMaxCount() - getCount());
439+
final long maxCount = getMaxCount();
440+
return maxCount == EOF ? Long.MAX_VALUE : Math.max(0, maxCount - getCount());
437441
}
438442

439443
private boolean isMaxCount() {
@@ -452,7 +456,7 @@ public boolean isPropagateClose() {
452456
/**
453457
* Invokes the delegate's {@link InputStream#mark(int)} method.
454458
*
455-
* @param readLimit read ahead limit
459+
* @param readLimit read ahead limit.
456460
*/
457461
@Override
458462
public synchronized void mark(final int readLimit) {
@@ -463,7 +467,7 @@ public synchronized void mark(final int readLimit) {
463467
/**
464468
* Invokes the delegate's {@link InputStream#markSupported()} method.
465469
*
466-
* @return true if mark is supported, otherwise false
470+
* @return true if mark is supported, otherwise false.
467471
*/
468472
@Override
469473
public boolean markSupported() {
@@ -476,7 +480,7 @@ public boolean markSupported() {
476480
* Delegates to the consumer set in {@link Builder#setOnMaxCount(IOBiConsumer)}.
477481
* </p>
478482
*
479-
* @param max The max count of bytes to read.
483+
* @param max The maximum count of bytes to read.
480484
* @param count The count of bytes read.
481485
* @throws IOException Subclasses may throw.
482486
* @since 2.12.0
@@ -505,7 +509,7 @@ public int read() throws IOException {
505509
/**
506510
* Invokes the delegate's {@link InputStream#read(byte[])} method.
507511
*
508-
* @param b the buffer to read the bytes into
512+
* @param b the buffer to read the bytes into.
509513
* @return the number of bytes read or -1 if the end of stream or the limit has been reached.
510514
* @throws IOException if an I/O error occurs.
511515
*/
@@ -517,9 +521,9 @@ public int read(final byte[] b) throws IOException {
517521
/**
518522
* Invokes the delegate's {@link InputStream#read(byte[], int, int)} method.
519523
*
520-
* @param b the buffer to read the bytes into
521-
* @param off The start offset
522-
* @param len The number of bytes to read
524+
* @param b the buffer to read the bytes into.
525+
* @param off The start offset.
526+
* @param len The number of bytes to read.
523527
* @return the number of bytes read or -1 if the end of stream or the limit has been reached.
524528
* @throws IOException if an I/O error occurs.
525529
*/
@@ -558,8 +562,8 @@ public synchronized void setPropagateClose(final boolean propagateClose) {
558562
/**
559563
* Invokes the delegate's {@link InputStream#skip(long)} method.
560564
*
561-
* @param n the number of bytes to skip
562-
* @return the actual number of bytes skipped
565+
* @param n the number of bytes to skip.
566+
* @return the actual number of bytes skipped.
563567
* @throws IOException if an I/O error occurs.
564568
*/
565569
@Override
@@ -576,7 +580,7 @@ private long toReadLen(final long len) {
576580
/**
577581
* Invokes the delegate's {@link InputStream#toString()} method.
578582
*
579-
* @return the delegate's {@link InputStream#toString()}
583+
* @return the delegate's {@link InputStream#toString()}.
580584
*/
581585
@Override
582586
public String toString() {

src/main/java/org/apache/commons/io/input/ProxyInputStream.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424

2525
import org.apache.commons.io.IOUtils;
2626
import org.apache.commons.io.build.AbstractStreamBuilder;
27-
import org.apache.commons.io.function.Erase;
28-
import org.apache.commons.io.function.IOConsumer;
2927
import org.apache.commons.io.function.IOIntConsumer;
3028

3129
/**
@@ -102,11 +100,6 @@ public B setAfterRead(final IOIntConsumer afterRead) {
102100
*/
103101
private volatile boolean closed;
104102

105-
/**
106-
* Handles exceptions.
107-
*/
108-
private final IOConsumer<IOException> exceptionHandler;
109-
110103
private final IOIntConsumer afterRead;
111104

112105
/**
@@ -130,7 +123,6 @@ protected ProxyInputStream(final AbstractBuilder<?, ?> builder) throws IOExcepti
130123
public ProxyInputStream(final InputStream proxy) {
131124
// the delegate is stored in a protected superclass variable named 'in'.
132125
super(proxy);
133-
this.exceptionHandler = Erase::rethrow;
134126
this.afterRead = IOIntConsumer.NOOP;
135127
}
136128

@@ -144,7 +136,6 @@ public ProxyInputStream(final InputStream proxy) {
144136
protected ProxyInputStream(final InputStream proxy, final AbstractBuilder<?, ?> builder) {
145137
// the delegate is stored in a protected superclass instance variable named 'in'.
146138
super(proxy);
147-
this.exceptionHandler = Erase::rethrow;
148139
this.afterRead = builder.getAfterRead() != null ? builder.getAfterRead() : IOIntConsumer.NOOP;
149140
}
150141

@@ -245,7 +236,7 @@ public void close() throws IOException {
245236
* @since 2.0
246237
*/
247238
protected void handleIOException(final IOException e) throws IOException {
248-
exceptionHandler.accept(e);
239+
throw e;
249240
}
250241

251242
/**

0 commit comments

Comments
 (0)