You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by cs...@apache.org on 2026/10/20 16:59:48 UTC

(maven-resolver) branch master updated: fix: catch only expected IO failures (#2207)

This is an automated email from the ASF dual-hosted git repository.

cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git


The following commit(s) were added to refs/heads/master by this push:
     new bf02fa2a4 fix: catch only expected IO failures (#2207)
bf02fa2a4 is described below

commit bf02fa2a40974fba8bec5695d8de8f91c6c36deb
Author: Efe <go...@gmail.com>
AuthorDate: Tue Oct 20 19:59:43 2026 +0300

    fix: catch only expected IO failures (#2207)
    
    Fixes #1988.
    
    `PutTaskRequestContent.read()` and `rewind()` now convert only `IOException` into terminal content failures. Unexpected runtime exceptions propagate to the caller instead of being hidden as ordinary content failures. Regression tests cover both channel paths.
    
    Tests: focused Maven reactor verification passed with JDK 21; 105 Jetty tests passed and 10 were skipped. Spotless check passed with JDK 21.
    
    - [x] I hereby declare this contribution to be licensed under the Apache License Version 2.0, January 2004
    - [x] I hereby declare that I have filed an Apache Individual Contributor License Agreement.
---
 .../transport/jetty/PutTaskRequestContent.java     |   7 +-
 .../transport/jetty/PutTaskRequestContentTest.java | 115 +++++++++++++++++++++
 2 files changed, 118 insertions(+), 4 deletions(-)

diff --git a/maven-resolver-transport-jetty/src/main/java/org/eclipse/aether/transport/jetty/PutTaskRequestContent.java b/maven-resolver-transport-jetty/src/main/java/org/eclipse/aether/transport/jetty/PutTaskRequestContent.java
index 026b728cd..4117e9e0a 100644
--- a/maven-resolver-transport-jetty/src/main/java/org/eclipse/aether/transport/jetty/PutTaskRequestContent.java
+++ b/maven-resolver-transport-jetty/src/main/java/org/eclipse/aether/transport/jetty/PutTaskRequestContent.java
@@ -243,7 +243,7 @@ public class PutTaskRequestContent extends ByteBufferRequestContent implements R
                     return last;
                 }
                 lockedSetTerminal(Content.Chunk.EOF);
-            } catch (Exception e) {
+            } catch (IOException e) {
                 lockedSetTerminal(Content.Chunk.from(e, true));
             }
         }
@@ -295,11 +295,10 @@ public class PutTaskRequestContent extends ByteBufferRequestContent implements R
                 offsetRemaining = 0;
                 totalRead = 0;
                 return true;
-            } catch (Exception e) {
+            } catch (IOException e) {
                 lockedSetTerminal(Content.Chunk.from(e, true));
+                return false;
             }
-
-            return true;
         }
     }
 }
diff --git a/maven-resolver-transport-jetty/src/test/java/org/eclipse/aether/transport/jetty/PutTaskRequestContentTest.java b/maven-resolver-transport-jetty/src/test/java/org/eclipse/aether/transport/jetty/PutTaskRequestContentTest.java
index c904d9ed4..99b9432f8 100644
--- a/maven-resolver-transport-jetty/src/test/java/org/eclipse/aether/transport/jetty/PutTaskRequestContentTest.java
+++ b/maven-resolver-transport-jetty/src/test/java/org/eclipse/aether/transport/jetty/PutTaskRequestContentTest.java
@@ -18,6 +18,7 @@
  */
 package org.eclipse.aether.transport.jetty;
 
+import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.SeekableByteChannel;
@@ -25,9 +26,31 @@ import java.nio.channels.SeekableByteChannel;
 import org.eclipse.jetty.io.ByteBufferPool;
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
 class PutTaskRequestContentTest {
+    @Test
+    void readPropagatesUnexpectedRuntimeExceptionsFromChannel() {
+        ReadableByteChannel channel = new ReadableByteChannel() {
+            @Override
+            public int read(ByteBuffer destination) {
+                throw new IllegalStateException("unexpected read failure");
+            }
+
+            @Override
+            public boolean isOpen() {
+                return true;
+            }
+
+            @Override
+            public void close() {}
+        };
+        PutTaskRequestContent content = new PutTaskRequestContent(ByteBufferPool.SIZED_NON_POOLING, () -> channel);
+
+        assertThrows(IllegalStateException.class, content::read);
+    }
+
     @Test
     void readPropagatesErrorsFromChannel() {
         ReadableByteChannel channel = new ReadableByteChannel() {
@@ -49,6 +72,52 @@ class PutTaskRequestContentTest {
         assertThrows(AssertionError.class, content::read);
     }
 
+    @Test
+    void rewindPropagatesUnexpectedRuntimeExceptionsFromSeekableChannel() {
+        SeekableByteChannel channel = new SeekableByteChannel() {
+            @Override
+            public int read(ByteBuffer destination) {
+                return -1;
+            }
+
+            @Override
+            public int write(ByteBuffer source) {
+                return 0;
+            }
+
+            @Override
+            public long position() {
+                return 0;
+            }
+
+            @Override
+            public SeekableByteChannel position(long newPosition) {
+                throw new IllegalStateException("unexpected rewind failure");
+            }
+
+            @Override
+            public long size() {
+                return 0;
+            }
+
+            @Override
+            public SeekableByteChannel truncate(long size) {
+                return this;
+            }
+
+            @Override
+            public boolean isOpen() {
+                return true;
+            }
+
+            @Override
+            public void close() {}
+        };
+        PutTaskRequestContent content = new PutTaskRequestContent(ByteBufferPool.SIZED_NON_POOLING, () -> channel);
+
+        assertThrows(IllegalStateException.class, content::rewind);
+    }
+
     @Test
     void rewindPropagatesErrorsFromSeekableChannel() {
         SeekableByteChannel channel = new SeekableByteChannel() {
@@ -94,4 +163,50 @@ class PutTaskRequestContentTest {
 
         assertThrows(AssertionError.class, content::rewind);
     }
+
+    @Test
+    void rewindReturnsFalseWhenPositionFailsWithIOException() {
+        SeekableByteChannel channel = new SeekableByteChannel() {
+            @Override
+            public int read(ByteBuffer destination) {
+                return -1;
+            }
+
+            @Override
+            public int write(ByteBuffer source) {
+                return 0;
+            }
+
+            @Override
+            public long position() {
+                return 0;
+            }
+
+            @Override
+            public SeekableByteChannel position(long newPosition) throws IOException {
+                throw new IOException("rewind failed");
+            }
+
+            @Override
+            public long size() {
+                return 0;
+            }
+
+            @Override
+            public SeekableByteChannel truncate(long size) {
+                return this;
+            }
+
+            @Override
+            public boolean isOpen() {
+                return true;
+            }
+
+            @Override
+            public void close() {}
+        };
+        PutTaskRequestContent content = new PutTaskRequestContent(ByteBufferPool.SIZED_NON_POOLING, () -> channel);
+
+        assertFalse(content.rewind());
+    }
 }