Introduce support for Netty 5 Buffer
This commit introduces support for Netty 5's Buffer, in the form of Netty5DataBuffer. Because of the new API offered by Buffer, several changes have been made to the DataBuffer API: - CloseableDataBuffer is a simpler alternative to PooledDataBuffer, and implemented by Netty5DataBuffer. DataBufferUtils::release can now handle CloseableDataBuffer as well as PooledDataBuffer. - PooledDataBuffer::touch has been moved into a separate interface: TouchableDataBuffer, which is implemented by Netty5DataBuffer. - The capacity of DataBuffers can no longer be reduced, they can only grow larger. As a consequence, DataBuffer::capacity(int) has been deprecated, but ensureWritable (formally ensureCapacity) still exists. - DataBuffer::slice and retainedSlice have been deprecated in favor of split, a new method that ensures that memory regions do not overlap. - DataBuffer::asByteBuffer has been deprecated in favor of toByteBuffer, a new method that returns a copy, instead of shared data. - DataBufferFactory::allocateBuffer has been deprecated in favor of allocateBuffer(int). Closes gh-28874
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,10 +42,10 @@ import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.PooledDataBuffer;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FastByteArrayOutputStream;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.web.reactive.result.view.AbstractUrlBasedView;
|
||||
import org.springframework.web.reactive.result.view.RequestContext;
|
||||
@@ -252,24 +252,21 @@ public class FreeMarkerView extends AbstractUrlBasedView {
|
||||
}
|
||||
|
||||
Locale locale = LocaleContextHolder.getLocale(exchange.getLocaleContext());
|
||||
DataBuffer dataBuffer = exchange.getResponse().bufferFactory().allocateBuffer();
|
||||
FastByteArrayOutputStream bos = new FastByteArrayOutputStream();
|
||||
try {
|
||||
Charset charset = getCharset(contentType);
|
||||
Writer writer = new OutputStreamWriter(dataBuffer.asOutputStream(), charset);
|
||||
Writer writer = new OutputStreamWriter(bos, charset);
|
||||
getTemplate(locale).process(freeMarkerModel, writer);
|
||||
return dataBuffer;
|
||||
|
||||
byte[] bytes = bos.toByteArrayUnsafe();
|
||||
return exchange.getResponse().bufferFactory().wrap(bytes);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
String message = "Could not load FreeMarker template for URL [" + getUrl() + "]";
|
||||
throw new IllegalStateException(message, ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
throw ex;
|
||||
}
|
||||
})
|
||||
.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release));
|
||||
.doOnDiscard(DataBuffer.class, DataBufferUtils::release));
|
||||
}
|
||||
|
||||
private Charset getCharset(@Nullable MediaType mediaType) {
|
||||
|
||||
@@ -84,7 +84,7 @@ public class JettyWebSocketSession extends AbstractListenerWebSocketSession<Sess
|
||||
|
||||
@Override
|
||||
protected boolean sendMessage(WebSocketMessage message) throws IOException {
|
||||
ByteBuffer buffer = message.getPayload().asByteBuffer();
|
||||
ByteBuffer buffer = message.getPayload().toByteBuffer();
|
||||
if (WebSocketMessage.Type.TEXT.equals(message.getType())) {
|
||||
getSendProcessor().setReadyToSend(false);
|
||||
String text = new String(buffer.array(), StandardCharsets.UTF_8);
|
||||
|
||||
@@ -73,7 +73,7 @@ public class StandardWebSocketSession extends AbstractListenerWebSocketSession<S
|
||||
|
||||
@Override
|
||||
protected boolean sendMessage(WebSocketMessage message) throws IOException {
|
||||
ByteBuffer buffer = message.getPayload().asByteBuffer();
|
||||
ByteBuffer buffer = message.getPayload().toByteBuffer();
|
||||
if (WebSocketMessage.Type.TEXT.equals(message.getType())) {
|
||||
getSendProcessor().setReadyToSend(false);
|
||||
String text = new String(buffer.array(), StandardCharsets.UTF_8);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,8 @@ package org.springframework.web.reactive.socket.adapter;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.undertow.websockets.WebSocketConnectionCallback;
|
||||
import io.undertow.websockets.core.AbstractReceiveListener;
|
||||
@@ -89,13 +91,14 @@ public class UndertowWebSocketHandlerAdapter extends AbstractReceiveListener {
|
||||
byte[] bytes = ((String) message).getBytes(StandardCharsets.UTF_8);
|
||||
return new WebSocketMessage(Type.TEXT, this.session.bufferFactory().wrap(bytes));
|
||||
}
|
||||
else if (Type.BINARY.equals(type)) {
|
||||
DataBuffer buffer = this.session.bufferFactory().allocateBuffer().write((ByteBuffer[]) message);
|
||||
return new WebSocketMessage(Type.BINARY, buffer);
|
||||
}
|
||||
else if (Type.PONG.equals(type)) {
|
||||
DataBuffer buffer = this.session.bufferFactory().allocateBuffer().write((ByteBuffer[]) message);
|
||||
return new WebSocketMessage(Type.PONG, buffer);
|
||||
else if (Type.BINARY.equals(type) || Type.PONG.equals(type)) {
|
||||
ByteBuffer[] byteBuffers = (ByteBuffer[]) message;
|
||||
List<DataBuffer> dataBuffers = new ArrayList<>(byteBuffers.length);
|
||||
for (ByteBuffer byteBuffer : byteBuffers) {
|
||||
dataBuffers.add(this.session.bufferFactory().wrap(byteBuffer));
|
||||
}
|
||||
DataBuffer joined = this.session.bufferFactory().join(dataBuffers);
|
||||
return new WebSocketMessage(type, joined);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unexpected message type: " + message);
|
||||
|
||||
@@ -76,7 +76,7 @@ public class UndertowWebSocketSession extends AbstractListenerWebSocketSession<W
|
||||
|
||||
@Override
|
||||
protected boolean sendMessage(WebSocketMessage message) throws IOException {
|
||||
ByteBuffer buffer = message.getPayload().asByteBuffer();
|
||||
ByteBuffer buffer = message.getPayload().toByteBuffer();
|
||||
if (WebSocketMessage.Type.TEXT.equals(message.getType())) {
|
||||
getSendProcessor().setReadyToSend(false);
|
||||
String text = new String(buffer.array(), StandardCharsets.UTF_8);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -112,7 +112,7 @@ public class DelegatingWebFluxConfigurationTests {
|
||||
boolean condition = initializer.getValidator() instanceof LocalValidatorFactoryBean;
|
||||
assertThat(condition).isTrue();
|
||||
assertThat(initializer.getConversionService()).isSameAs(formatterRegistry.getValue());
|
||||
assertThat(codecsConfigurer.getValue().getReaders().size()).isEqualTo(15);
|
||||
assertThat(codecsConfigurer.getValue().getReaders().size()).isEqualTo(16);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -144,7 +144,7 @@ public class WebFluxConfigurationSupportTests {
|
||||
assertThat(adapter).isNotNull();
|
||||
|
||||
List<HttpMessageReader<?>> readers = adapter.getMessageReaders();
|
||||
assertThat(readers.size()).isEqualTo(15);
|
||||
assertThat(readers.size()).isEqualTo(16);
|
||||
|
||||
ResolvableType multiValueMapType = forClassWithGenerics(MultiValueMap.class, String.class, String.class);
|
||||
|
||||
@@ -199,7 +199,7 @@ public class WebFluxConfigurationSupportTests {
|
||||
assertThat(handler.getOrder()).isEqualTo(0);
|
||||
|
||||
List<HttpMessageWriter<?>> writers = handler.getMessageWriters();
|
||||
assertThat(writers.size()).isEqualTo(13);
|
||||
assertThat(writers.size()).isEqualTo(14);
|
||||
|
||||
assertHasMessageWriter(writers, forClass(byte[].class), APPLICATION_OCTET_STREAM);
|
||||
assertHasMessageWriter(writers, forClass(ByteBuffer.class), APPLICATION_OCTET_STREAM);
|
||||
@@ -227,7 +227,7 @@ public class WebFluxConfigurationSupportTests {
|
||||
assertThat(handler.getOrder()).isEqualTo(100);
|
||||
|
||||
List<HttpMessageWriter<?>> writers = handler.getMessageWriters();
|
||||
assertThat(writers.size()).isEqualTo(13);
|
||||
assertThat(writers.size()).isEqualTo(14);
|
||||
|
||||
assertHasMessageWriter(writers, forClass(byte[].class), APPLICATION_OCTET_STREAM);
|
||||
assertHasMessageWriter(writers, forClass(ByteBuffer.class), APPLICATION_OCTET_STREAM);
|
||||
|
||||
Reference in New Issue
Block a user