diff --git a/framework-platform/framework-platform.gradle b/framework-platform/framework-platform.gradle index 839a07cbdbff..a62040b80dfb 100644 --- a/framework-platform/framework-platform.gradle +++ b/framework-platform/framework-platform.gradle @@ -16,8 +16,8 @@ dependencies { api(platform("org.apache.groovy:groovy-bom:4.0.21")) api(platform("org.apache.logging.log4j:log4j-bom:2.21.1")) api(platform("org.assertj:assertj-bom:3.26.0")) - api(platform("org.eclipse.jetty:jetty-bom:12.0.10")) - api(platform("org.eclipse.jetty.ee10:jetty-ee10-bom:12.0.10")) + api(platform("org.eclipse.jetty:jetty-bom:12.0.11")) + api(platform("org.eclipse.jetty.ee10:jetty-ee10-bom:12.0.11")) api(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3")) api(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.6.0")) api(platform("org.junit:junit-bom:5.10.2")) diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/JettyCoreServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/reactive/JettyCoreServerHttpResponse.java index 4ba19b3a2894..74df330a2a45 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/JettyCoreServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/JettyCoreServerHttpResponse.java @@ -32,6 +32,7 @@ import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.Content; import org.eclipse.jetty.io.RetainableByteBuffer; +import org.eclipse.jetty.io.content.ByteBufferContentSource; import org.eclipse.jetty.server.HttpCookieUtils; import org.eclipse.jetty.server.Response; import org.eclipse.jetty.util.BufferUtil; @@ -119,10 +120,7 @@ public Mono writeWith(Path file, long position, long count) { Callback.Completable callback = new Callback.Completable(); Mono mono = Mono.fromFuture(callback); try { - // The method can block, but it is not expected to do so for any significant time. - @SuppressWarnings("BlockingMethodInNonBlockingContext") - SeekableByteChannel channel = Files.newByteChannel(file, StandardOpenOption.READ); - new ContentWriterIteratingCallback(channel, position, count, this.response, callback).iterate(); + Content.copy(Content.Source.from(null, file, position, count), this.response, callback); } catch (Throwable th) { callback.failed(th); @@ -244,66 +242,4 @@ public Map getAttributes() { return Collections.emptyMap(); } } - - private static class ContentWriterIteratingCallback extends IteratingCallback { - private final SeekableByteChannel source; - - private final Content.Sink sink; - - private final Callback callback; - - private final RetainableByteBuffer buffer; - - private final long length; - - private long totalRead = 0; - - public ContentWriterIteratingCallback(SeekableByteChannel content, long position, long count, Response target, Callback callback) throws IOException { - this.source = content; - this.sink = target; - this.callback = callback; - this.length = count; - this.source.position(position); - - ByteBufferPool bufferPool = target.getRequest().getComponents().getByteBufferPool(); - int outputBufferSize = target.getRequest().getConnectionMetaData().getHttpConfiguration().getOutputBufferSize(); - boolean useOutputDirectByteBuffers = target.getRequest().getConnectionMetaData().getHttpConfiguration().isUseOutputDirectByteBuffers(); - this.buffer = bufferPool.acquire(outputBufferSize, useOutputDirectByteBuffers); - } - - @Override - protected Action process() throws Throwable { - if (!this.source.isOpen() || this.totalRead == this.length) { - return Action.SUCCEEDED; - } - - ByteBuffer byteBuffer = this.buffer.getByteBuffer(); - BufferUtil.clearToFill(byteBuffer); - byteBuffer.limit((int) Math.min(this.buffer.capacity(), this.length - this.totalRead)); - int read = this.source.read(byteBuffer); - if (read == -1) { - IO.close(this.source); - this.sink.write(true, BufferUtil.EMPTY_BUFFER, this); - return Action.SCHEDULED; - } - this.totalRead += read; - BufferUtil.flipToFlush(byteBuffer, 0); - this.sink.write(false, byteBuffer, this); - return Action.SCHEDULED; - } - - @Override - protected void onCompleteSuccess() { - this.buffer.release(); - IO.close(this.source); - this.callback.succeeded(); - } - - @Override - protected void onCompleteFailure(Throwable x) { - this.buffer.release(); - IO.close(this.source); - this.callback.failed(x); - } - } }