Remove Netty 5 support
Closes gh-34345
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.springframework.core.codec;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.netty5.buffer.Buffer;
|
||||
import io.netty5.buffer.DefaultBufferAllocators;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.Netty5DataBuffer;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
/**
|
||||
* Decoder for {@link Buffer Buffers}.
|
||||
*
|
||||
* @author Violeta Georgieva
|
||||
* @since 6.0
|
||||
*/
|
||||
public class Netty5BufferDecoder extends AbstractDataBufferDecoder<Buffer> {
|
||||
|
||||
public Netty5BufferDecoder() {
|
||||
super(MimeTypeUtils.ALL);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) {
|
||||
return (Buffer.class.isAssignableFrom(elementType.toClass()) &&
|
||||
super.canDecode(elementType, mimeType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buffer decode(DataBuffer dataBuffer, ResolvableType elementType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(Hints.getLogPrefix(hints) + "Read " + dataBuffer.readableByteCount() + " bytes");
|
||||
}
|
||||
if (dataBuffer instanceof Netty5DataBuffer netty5DataBuffer) {
|
||||
return netty5DataBuffer.getNativeBuffer();
|
||||
}
|
||||
byte[] bytes = new byte[dataBuffer.readableByteCount()];
|
||||
dataBuffer.read(bytes);
|
||||
Buffer buffer = DefaultBufferAllocators.preferredAllocator().copyOf(bytes);
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.springframework.core.codec;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.netty5.buffer.Buffer;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.Netty5DataBufferFactory;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
/**
|
||||
* Encoder for {@link Buffer Buffers}.
|
||||
*
|
||||
* @author Violeta Georgieva
|
||||
* @since 6.0
|
||||
*/
|
||||
public class Netty5BufferEncoder extends AbstractEncoder<Buffer> {
|
||||
|
||||
public Netty5BufferEncoder() {
|
||||
super(MimeTypeUtils.ALL);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canEncode(ResolvableType type, @Nullable MimeType mimeType) {
|
||||
Class<?> clazz = type.toClass();
|
||||
return super.canEncode(type, mimeType) && Buffer.class.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<DataBuffer> encode(Publisher<? extends Buffer> inputStream,
|
||||
DataBufferFactory bufferFactory, ResolvableType elementType, @Nullable MimeType mimeType,
|
||||
@Nullable Map<String, Object> hints) {
|
||||
|
||||
return Flux.from(inputStream).map(byteBuffer ->
|
||||
encodeValue(byteBuffer, bufferFactory, elementType, mimeType, hints));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBuffer encodeValue(Buffer buffer, DataBufferFactory bufferFactory, ResolvableType valueType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
if (logger.isDebugEnabled() && !Hints.isLoggingSuppressed(hints)) {
|
||||
String logPrefix = Hints.getLogPrefix(hints);
|
||||
logger.debug(logPrefix + "Writing " + buffer.readableBytes() + " bytes");
|
||||
}
|
||||
if (bufferFactory instanceof Netty5DataBufferFactory netty5DataBufferFactory) {
|
||||
return netty5DataBufferFactory.wrap(buffer);
|
||||
}
|
||||
byte[] bytes = new byte[buffer.readableBytes()];
|
||||
buffer.readBytes(bytes, 0, bytes.length);
|
||||
buffer.close();
|
||||
return bufferFactory.wrap(bytes);
|
||||
}
|
||||
}
|
||||
@@ -1,401 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.springframework.core.io.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.IntPredicate;
|
||||
|
||||
import io.netty5.buffer.Buffer;
|
||||
import io.netty5.buffer.BufferComponent;
|
||||
import io.netty5.buffer.ComponentIterator;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the {@code DataBuffer} interface that wraps a Netty 5
|
||||
* {@link Buffer}. Typically constructed with {@link Netty5DataBufferFactory}.
|
||||
*
|
||||
* @author Violeta Georgieva
|
||||
* @author Arjen Poutsma
|
||||
* @since 6.0
|
||||
*/
|
||||
public final class Netty5DataBuffer implements CloseableDataBuffer, TouchableDataBuffer {
|
||||
|
||||
private final Buffer buffer;
|
||||
|
||||
private final Netty5DataBufferFactory dataBufferFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code Netty5DataBuffer} based on the given {@code Buffer}.
|
||||
* @param buffer the buffer to base this buffer on
|
||||
*/
|
||||
Netty5DataBuffer(Buffer buffer, Netty5DataBufferFactory dataBufferFactory) {
|
||||
Assert.notNull(buffer, "Buffer must not be null");
|
||||
Assert.notNull(dataBufferFactory, "Netty5DataBufferFactory must not be null");
|
||||
this.buffer = buffer;
|
||||
this.dataBufferFactory = dataBufferFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Directly exposes the native {@code Buffer} that this buffer is based on.
|
||||
* @return the wrapped buffer
|
||||
*/
|
||||
public Buffer getNativeBuffer() {
|
||||
return this.buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBufferFactory factory() {
|
||||
return this.dataBufferFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(IntPredicate predicate, int fromIndex) {
|
||||
Assert.notNull(predicate, "IntPredicate must not be null");
|
||||
if (fromIndex < 0) {
|
||||
fromIndex = 0;
|
||||
}
|
||||
else if (fromIndex >= this.buffer.writerOffset()) {
|
||||
return -1;
|
||||
}
|
||||
int length = this.buffer.writerOffset() - fromIndex;
|
||||
int bytes = this.buffer.openCursor(fromIndex, length).process(predicate.negate()::test);
|
||||
return bytes == -1 ? -1 : fromIndex + bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(IntPredicate predicate, int fromIndex) {
|
||||
Assert.notNull(predicate, "IntPredicate must not be null");
|
||||
if (fromIndex < 0) {
|
||||
return -1;
|
||||
}
|
||||
fromIndex = Math.min(fromIndex, this.buffer.writerOffset() - 1);
|
||||
return this.buffer.openCursor(0, fromIndex + 1).process(predicate.negate()::test);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readableByteCount() {
|
||||
return this.buffer.readableBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writableByteCount() {
|
||||
return this.buffer.writableBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readPosition() {
|
||||
return this.buffer.readerOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer readPosition(int readPosition) {
|
||||
this.buffer.readerOffset(readPosition);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writePosition() {
|
||||
return this.buffer.writerOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer writePosition(int writePosition) {
|
||||
this.buffer.writerOffset(writePosition);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte(int index) {
|
||||
return this.buffer.getByte(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int capacity() {
|
||||
return this.buffer.capacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Netty5DataBuffer capacity(int capacity) {
|
||||
if (capacity <= 0) {
|
||||
throw new IllegalArgumentException(String.format("'newCapacity' %d must be higher than 0", capacity));
|
||||
}
|
||||
int diff = capacity - capacity();
|
||||
if (diff > 0) {
|
||||
this.buffer.ensureWritable(this.buffer.writableBytes() + diff);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBuffer ensureWritable(int capacity) {
|
||||
Assert.isTrue(capacity >= 0, "Capacity must be >= 0");
|
||||
this.buffer.ensureWritable(capacity);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte read() {
|
||||
return this.buffer.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer read(byte[] destination) {
|
||||
return read(destination, 0, destination.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer read(byte[] destination, int offset, int length) {
|
||||
this.buffer.readBytes(destination, offset, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer write(byte b) {
|
||||
this.buffer.writeByte(b);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer write(byte[] source) {
|
||||
this.buffer.writeBytes(source);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer write(byte[] source, int offset, int length) {
|
||||
this.buffer.writeBytes(source, offset, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer write(DataBuffer... dataBuffers) {
|
||||
if (!ObjectUtils.isEmpty(dataBuffers)) {
|
||||
if (hasNetty5DataBuffers(dataBuffers)) {
|
||||
Buffer[] nativeBuffers = new Buffer[dataBuffers.length];
|
||||
for (int i = 0; i < dataBuffers.length; i++) {
|
||||
nativeBuffers[i] = ((Netty5DataBuffer) dataBuffers[i]).getNativeBuffer();
|
||||
}
|
||||
return write(nativeBuffers);
|
||||
}
|
||||
else {
|
||||
ByteBuffer[] byteBuffers = new ByteBuffer[dataBuffers.length];
|
||||
for (int i = 0; i < dataBuffers.length; i++) {
|
||||
byteBuffers[i] = ByteBuffer.allocate(dataBuffers[i].readableByteCount());
|
||||
dataBuffers[i].toByteBuffer(byteBuffers[i]);
|
||||
}
|
||||
return write(byteBuffers);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private static boolean hasNetty5DataBuffers(DataBuffer[] buffers) {
|
||||
for (DataBuffer buffer : buffers) {
|
||||
if (!(buffer instanceof Netty5DataBuffer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer write(ByteBuffer... buffers) {
|
||||
if (!ObjectUtils.isEmpty(buffers)) {
|
||||
for (ByteBuffer buffer : buffers) {
|
||||
this.buffer.writeBytes(buffer);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes one or more Netty 5 {@link Buffer Buffers} to this buffer,
|
||||
* starting at the current writing position.
|
||||
* @param buffers the buffers to write into this buffer
|
||||
* @return this buffer
|
||||
*/
|
||||
public Netty5DataBuffer write(Buffer... buffers) {
|
||||
if (!ObjectUtils.isEmpty(buffers)) {
|
||||
for (Buffer buffer : buffers) {
|
||||
this.buffer.writeBytes(buffer);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBuffer write(CharSequence charSequence, Charset charset) {
|
||||
Assert.notNull(charSequence, "CharSequence must not be null");
|
||||
Assert.notNull(charset, "Charset must not be null");
|
||||
|
||||
this.buffer.writeCharSequence(charSequence, charset);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p><strong>Note</strong> that due to the lack of a {@code slice} method
|
||||
* in Netty 5's {@link Buffer}, this implementation returns a copy that
|
||||
* does <strong>not</strong> share its contents with this buffer.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public DataBuffer slice(int index, int length) {
|
||||
Buffer copy = this.buffer.copy(index, length);
|
||||
return new Netty5DataBuffer(copy, this.dataBufferFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBuffer split(int index) {
|
||||
Buffer split = this.buffer.split(index);
|
||||
return new Netty5DataBuffer(split, this.dataBufferFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public ByteBuffer asByteBuffer() {
|
||||
return toByteBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public ByteBuffer asByteBuffer(int index, int length) {
|
||||
return toByteBuffer(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public ByteBuffer toByteBuffer(int index, int length) {
|
||||
ByteBuffer copy = this.buffer.isDirect() ?
|
||||
ByteBuffer.allocateDirect(length) :
|
||||
ByteBuffer.allocate(length);
|
||||
|
||||
this.buffer.copyInto(index, copy, 0, length);
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toByteBuffer(int srcPos, ByteBuffer dest, int destPos, int length) {
|
||||
this.buffer.copyInto(srcPos, dest, destPos, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufferIterator readableByteBuffers() {
|
||||
return new BufferComponentIterator<>(this.buffer.forEachComponent(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufferIterator writableByteBuffers() {
|
||||
return new BufferComponentIterator<>(this.buffer.forEachComponent(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Charset charset) {
|
||||
Assert.notNull(charset, "Charset must not be null");
|
||||
return this.buffer.toString(charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(int index, int length, Charset charset) {
|
||||
Assert.notNull(charset, "Charset must not be null");
|
||||
byte[] data = new byte[length];
|
||||
this.buffer.copyInto(index, data, 0, length);
|
||||
return new String(data, 0, length, charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer touch(Object hint) {
|
||||
this.buffer.touch(hint);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.buffer.close();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
return (this == other || (other instanceof Netty5DataBuffer that && this.buffer.equals(that.buffer)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.buffer.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
private static final class BufferComponentIterator<T extends BufferComponent & ComponentIterator.Next>
|
||||
implements ByteBufferIterator {
|
||||
|
||||
private final ComponentIterator<T> delegate;
|
||||
|
||||
private final boolean readable;
|
||||
|
||||
private @Nullable T next;
|
||||
|
||||
public BufferComponentIterator(ComponentIterator<T> delegate, boolean readable) {
|
||||
Assert.notNull(delegate, "Delegate must not be null");
|
||||
this.delegate = delegate;
|
||||
this.readable = readable;
|
||||
this.next = readable ? this.delegate.firstReadable() : this.delegate.firstWritable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return this.next != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer next() {
|
||||
if (this.next != null) {
|
||||
ByteBuffer result;
|
||||
if (this.readable) {
|
||||
result = this.next.readableBuffer();
|
||||
this.next = this.next.nextReadable();
|
||||
}
|
||||
else {
|
||||
result = this.next.writableBuffer();
|
||||
this.next = this.next.nextWritable();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.delegate.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.springframework.core.io.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import io.netty5.buffer.Buffer;
|
||||
import io.netty5.buffer.BufferAllocator;
|
||||
import io.netty5.buffer.CompositeBuffer;
|
||||
import io.netty5.buffer.DefaultBufferAllocators;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of the {@code DataBufferFactory} interface based on a
|
||||
* Netty 5 {@link BufferAllocator}.
|
||||
*
|
||||
* @author Violeta Georgieva
|
||||
* @author Arjen Poutsma
|
||||
* @since 6.0
|
||||
*/
|
||||
public class Netty5DataBufferFactory implements DataBufferFactory {
|
||||
|
||||
private final BufferAllocator bufferAllocator;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code Netty5DataBufferFactory} based on the given factory.
|
||||
* @param bufferAllocator the factory to use
|
||||
*/
|
||||
public Netty5DataBufferFactory(BufferAllocator bufferAllocator) {
|
||||
Assert.notNull(bufferAllocator, "BufferAllocator must not be null");
|
||||
this.bufferAllocator = bufferAllocator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the {@code BufferAllocator} used by this factory.
|
||||
*/
|
||||
public BufferAllocator getBufferAllocator() {
|
||||
return this.bufferAllocator;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Netty5DataBuffer allocateBuffer() {
|
||||
Buffer buffer = this.bufferAllocator.allocate(256);
|
||||
return new Netty5DataBuffer(buffer, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer allocateBuffer(int initialCapacity) {
|
||||
Buffer buffer = this.bufferAllocator.allocate(initialCapacity);
|
||||
return new Netty5DataBuffer(buffer, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer wrap(ByteBuffer byteBuffer) {
|
||||
Buffer buffer = this.bufferAllocator.copyOf(byteBuffer);
|
||||
return new Netty5DataBuffer(buffer, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Netty5DataBuffer wrap(byte[] bytes) {
|
||||
Buffer buffer = this.bufferAllocator.copyOf(bytes);
|
||||
return new Netty5DataBuffer(buffer, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given Netty {@link Buffer} in a {@code Netty5DataBuffer}.
|
||||
* @param buffer the Netty buffer to wrap
|
||||
* @return the wrapped buffer
|
||||
*/
|
||||
public Netty5DataBuffer wrap(Buffer buffer) {
|
||||
buffer.touch("Wrap buffer");
|
||||
return new Netty5DataBuffer(buffer, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation uses Netty's {@link CompositeBuffer}.
|
||||
*/
|
||||
@Override
|
||||
public DataBuffer join(List<? extends DataBuffer> dataBuffers) {
|
||||
Assert.notEmpty(dataBuffers, "DataBuffer List must not be empty");
|
||||
if (dataBuffers.size() == 1) {
|
||||
return dataBuffers.get(0);
|
||||
}
|
||||
CompositeBuffer composite = this.bufferAllocator.compose();
|
||||
for (DataBuffer dataBuffer : dataBuffers) {
|
||||
Assert.isInstanceOf(Netty5DataBuffer.class, dataBuffer);
|
||||
composite.extendWith(((Netty5DataBuffer) dataBuffer).getNativeBuffer().send());
|
||||
}
|
||||
return new Netty5DataBuffer(composite, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirect() {
|
||||
return this.bufferAllocator.getAllocationType().isDirect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the given Netty {@link DataBuffer} as a {@link Buffer}.
|
||||
* <p>Returns the {@linkplain Netty5DataBuffer#getNativeBuffer() native buffer}
|
||||
* if {@code buffer} is a {@link Netty5DataBuffer}; returns
|
||||
* {@link BufferAllocator#copyOf(ByteBuffer)} otherwise.
|
||||
* @param buffer the {@code DataBuffer} to return a {@code Buffer} for
|
||||
* @return the netty {@code Buffer}
|
||||
*/
|
||||
public static Buffer toBuffer(DataBuffer buffer) {
|
||||
if (buffer instanceof Netty5DataBuffer netty5DataBuffer) {
|
||||
return netty5DataBuffer.getNativeBuffer();
|
||||
}
|
||||
else {
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(buffer.readableByteCount());
|
||||
buffer.toByteBuffer(byteBuffer);
|
||||
return DefaultBufferAllocators.preferredAllocator().copyOf(byteBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Netty5DataBufferFactory (" + this.bufferAllocator + ")";
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2024 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.springframework.core.codec;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import io.netty5.buffer.Buffer;
|
||||
import io.netty5.buffer.DefaultBufferAllocators;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.testfixture.codec.AbstractDecoderTests;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
class Netty5BufferDecoderTests extends AbstractDecoderTests<Netty5BufferDecoder> {
|
||||
|
||||
private final byte[] fooBytes = "foo".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
private final byte[] barBytes = "bar".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
|
||||
Netty5BufferDecoderTests() {
|
||||
super(new Netty5BufferDecoder());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
protected void canDecode() {
|
||||
assertThat(this.decoder.canDecode(ResolvableType.forClass(Buffer.class),
|
||||
MimeTypeUtils.TEXT_PLAIN)).isTrue();
|
||||
assertThat(this.decoder.canDecode(ResolvableType.forClass(Integer.class),
|
||||
MimeTypeUtils.TEXT_PLAIN)).isFalse();
|
||||
assertThat(this.decoder.canDecode(ResolvableType.forClass(Buffer.class),
|
||||
MimeTypeUtils.APPLICATION_JSON)).isTrue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
protected void decode() {
|
||||
Flux<DataBuffer> input = Flux.concat(
|
||||
dataBuffer(this.fooBytes),
|
||||
dataBuffer(this.barBytes));
|
||||
|
||||
testDecodeAll(input, Buffer.class, step -> step
|
||||
.consumeNextWith(expectByteBuffer(DefaultBufferAllocators.preferredAllocator().copyOf(this.fooBytes)))
|
||||
.consumeNextWith(expectByteBuffer(DefaultBufferAllocators.preferredAllocator().copyOf(this.barBytes)))
|
||||
.verifyComplete());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
protected void decodeToMono() {
|
||||
Flux<DataBuffer> input = Flux.concat(
|
||||
dataBuffer(this.fooBytes),
|
||||
dataBuffer(this.barBytes));
|
||||
|
||||
Buffer expected = DefaultBufferAllocators.preferredAllocator().allocate(this.fooBytes.length + this.barBytes.length)
|
||||
.writeBytes(this.fooBytes)
|
||||
.writeBytes(this.barBytes)
|
||||
.readerOffset(0);
|
||||
|
||||
testDecodeToMonoAll(input, Buffer.class, step -> step
|
||||
.consumeNextWith(expectByteBuffer(expected))
|
||||
.verifyComplete());
|
||||
}
|
||||
|
||||
private Consumer<Buffer> expectByteBuffer(Buffer expected) {
|
||||
return actual -> {
|
||||
try (actual; expected) {
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.springframework.core.codec;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import io.netty5.buffer.Buffer;
|
||||
import io.netty5.buffer.DefaultBufferAllocators;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.testfixture.codec.AbstractEncoderTests;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
class Netty5BufferEncoderTests extends AbstractEncoderTests<Netty5BufferEncoder> {
|
||||
|
||||
private final byte[] fooBytes = "foo".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
private final byte[] barBytes = "bar".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
Netty5BufferEncoderTests() {
|
||||
super(new Netty5BufferEncoder());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void canEncode() {
|
||||
assertThat(this.encoder.canEncode(ResolvableType.forClass(Buffer.class),
|
||||
MimeTypeUtils.TEXT_PLAIN)).isTrue();
|
||||
assertThat(this.encoder.canEncode(ResolvableType.forClass(Integer.class),
|
||||
MimeTypeUtils.TEXT_PLAIN)).isFalse();
|
||||
assertThat(this.encoder.canEncode(ResolvableType.forClass(Buffer.class),
|
||||
MimeTypeUtils.APPLICATION_JSON)).isTrue();
|
||||
|
||||
// gh-20024
|
||||
assertThat(this.encoder.canEncode(ResolvableType.NONE, null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
@SuppressWarnings("resource")
|
||||
public void encode() {
|
||||
Flux<Buffer> input = Flux.just(this.fooBytes, this.barBytes)
|
||||
.map(DefaultBufferAllocators.preferredAllocator()::copyOf);
|
||||
|
||||
testEncodeAll(input, Buffer.class, step -> step
|
||||
.consumeNextWith(expectBytes(this.fooBytes))
|
||||
.consumeNextWith(expectBytes(this.barBytes))
|
||||
.verifyComplete());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -28,7 +28,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatException;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeFalse;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
@@ -414,9 +413,6 @@ class DataBufferTests extends AbstractDataBufferAllocatingTests {
|
||||
@ParameterizedDataBufferAllocatingTest
|
||||
@SuppressWarnings("deprecation")
|
||||
void decreaseCapacityLowReadPosition(DataBufferFactory bufferFactory) {
|
||||
assumeFalse(bufferFactory instanceof Netty5DataBufferFactory,
|
||||
"Netty 5 does not support decreasing the capacity");
|
||||
|
||||
super.bufferFactory = bufferFactory;
|
||||
|
||||
DataBuffer buffer = createDataBuffer(2);
|
||||
@@ -430,9 +426,6 @@ class DataBufferTests extends AbstractDataBufferAllocatingTests {
|
||||
@ParameterizedDataBufferAllocatingTest
|
||||
@SuppressWarnings("deprecation")
|
||||
void decreaseCapacityHighReadPosition(DataBufferFactory bufferFactory) {
|
||||
assumeFalse(bufferFactory instanceof Netty5DataBufferFactory,
|
||||
"Netty 5 does not support decreasing the capacity");
|
||||
|
||||
super.bufferFactory = bufferFactory;
|
||||
|
||||
DataBuffer buffer = createDataBuffer(2);
|
||||
@@ -543,11 +536,6 @@ class DataBufferTests extends AbstractDataBufferAllocatingTests {
|
||||
ByteBuffer result = buffer.asByteBuffer(1, 2);
|
||||
assertThat(result.capacity()).isEqualTo(2);
|
||||
|
||||
assumeFalse(bufferFactory instanceof Netty5DataBufferFactory, () -> {
|
||||
DataBufferUtils.release(buffer);
|
||||
return "Netty 5 does share the internal buffer";
|
||||
});
|
||||
|
||||
buffer.write((byte) 'c');
|
||||
assertThat(result.remaining()).isEqualTo(2);
|
||||
|
||||
@@ -561,9 +549,6 @@ class DataBufferTests extends AbstractDataBufferAllocatingTests {
|
||||
@ParameterizedDataBufferAllocatingTest
|
||||
@SuppressWarnings("deprecation")
|
||||
void byteBufferContainsDataBufferChanges(DataBufferFactory bufferFactory) {
|
||||
assumeFalse(bufferFactory instanceof Netty5DataBufferFactory,
|
||||
"Netty 5 does not support sharing data between buffers");
|
||||
|
||||
super.bufferFactory = bufferFactory;
|
||||
|
||||
DataBuffer dataBuffer = createDataBuffer(1);
|
||||
@@ -581,9 +566,6 @@ class DataBufferTests extends AbstractDataBufferAllocatingTests {
|
||||
@ParameterizedDataBufferAllocatingTest
|
||||
@SuppressWarnings("deprecation")
|
||||
void dataBufferContainsByteBufferChanges(DataBufferFactory bufferFactory) {
|
||||
assumeFalse(bufferFactory instanceof Netty5DataBufferFactory,
|
||||
"Netty 5 does not support sharing data between buffers");
|
||||
|
||||
super.bufferFactory = bufferFactory;
|
||||
|
||||
DataBuffer dataBuffer = createDataBuffer(1);
|
||||
@@ -833,18 +815,13 @@ class DataBufferTests extends AbstractDataBufferAllocatingTests {
|
||||
result = new byte[2];
|
||||
slice.read(result);
|
||||
|
||||
if (!(bufferFactory instanceof Netty5DataBufferFactory)) {
|
||||
assertThat(result).isEqualTo(new byte[]{'b', 'c'});
|
||||
}
|
||||
assertThat(result).isEqualTo(new byte[]{'b', 'c'});
|
||||
release(buffer);
|
||||
}
|
||||
|
||||
@ParameterizedDataBufferAllocatingTest
|
||||
@SuppressWarnings("deprecation")
|
||||
void retainedSlice(DataBufferFactory bufferFactory) {
|
||||
assumeFalse(bufferFactory instanceof Netty5DataBufferFactory,
|
||||
"Netty 5 does not support retainedSlice");
|
||||
|
||||
super.bufferFactory = bufferFactory;
|
||||
|
||||
DataBuffer buffer = createDataBuffer(3);
|
||||
@@ -887,9 +864,7 @@ class DataBufferTests extends AbstractDataBufferAllocatingTests {
|
||||
|
||||
assertThat(result).isEqualTo(bytes);
|
||||
|
||||
if (bufferFactory instanceof Netty5DataBufferFactory) {
|
||||
release(slice);
|
||||
}
|
||||
release(slice);
|
||||
release(buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -20,7 +20,6 @@ import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import io.netty5.buffer.Buffer;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
@@ -210,13 +209,7 @@ public abstract class AbstractDecoderTests<D extends Decoder<?>> extends Abstrac
|
||||
|
||||
Flux<DataBuffer> flux = Mono.from(input).concatWith(Flux.error(new InputException()));
|
||||
assertThatExceptionOfType(InputException.class).isThrownBy(() ->
|
||||
this.decoder.decode(flux, outputType, mimeType, hints)
|
||||
.doOnNext(object -> {
|
||||
if (object instanceof Buffer buffer) {
|
||||
buffer.close();
|
||||
}
|
||||
})
|
||||
.blockLast(Duration.ofSeconds(5)));
|
||||
this.decoder.decode(flux, outputType, mimeType, hints).blockLast(Duration.ofSeconds(5)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,12 +226,7 @@ public abstract class AbstractDecoderTests<D extends Decoder<?>> extends Abstrac
|
||||
protected void testDecodeCancel(Publisher<DataBuffer> input, ResolvableType outputType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
Flux<?> result = this.decoder.decode(input, outputType, mimeType, hints)
|
||||
.doOnNext(object -> {
|
||||
if (object instanceof Buffer buffer) {
|
||||
buffer.close();
|
||||
}
|
||||
});
|
||||
Flux<?> result = this.decoder.decode(input, outputType, mimeType, hints);
|
||||
StepVerifier.create(result).expectNextCount(1).thenCancel().verify();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -34,8 +34,6 @@ import io.netty.buffer.PoolArenaMetric;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import io.netty.buffer.PooledByteBufAllocatorMetric;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
import io.netty5.buffer.BufferAllocator;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
@@ -48,7 +46,6 @@ import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.core.io.buffer.Netty5DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.NettyDataBufferFactory;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@@ -65,14 +62,6 @@ import static org.junit.jupiter.params.provider.Arguments.argumentSet;
|
||||
*/
|
||||
public abstract class AbstractDataBufferAllocatingTests {
|
||||
|
||||
private static BufferAllocator netty5OnHeapUnpooled;
|
||||
|
||||
private static BufferAllocator netty5OffHeapUnpooled;
|
||||
|
||||
private static BufferAllocator netty5OffHeapPooled;
|
||||
|
||||
private static BufferAllocator netty5OnHeapPooled;
|
||||
|
||||
private static UnpooledByteBufAllocator netty4OffHeapUnpooled;
|
||||
|
||||
private static UnpooledByteBufAllocator netty4OnHeapUnpooled;
|
||||
@@ -178,19 +167,6 @@ public abstract class AbstractDataBufferAllocatingTests {
|
||||
netty4OffHeapUnpooled = new UnpooledByteBufAllocator(true);
|
||||
netty4OnHeapPooled = new PooledByteBufAllocator(false, 1, 1, 4096, 4, 0, 0, 0, true);
|
||||
netty4OffHeapPooled = new PooledByteBufAllocator(true, 1, 1, 4096, 4, 0, 0, 0, true);
|
||||
|
||||
netty5OnHeapUnpooled = BufferAllocator.onHeapUnpooled();
|
||||
netty5OffHeapUnpooled = BufferAllocator.offHeapUnpooled();
|
||||
netty5OnHeapPooled = BufferAllocator.onHeapPooled();
|
||||
netty5OffHeapPooled = BufferAllocator.offHeapPooled();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void closeAllocators() {
|
||||
netty5OnHeapUnpooled.close();
|
||||
netty5OffHeapUnpooled.close();
|
||||
netty5OnHeapPooled.close();
|
||||
netty5OffHeapPooled.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -212,15 +188,6 @@ public abstract class AbstractDataBufferAllocatingTests {
|
||||
new NettyDataBufferFactory(netty4OffHeapPooled)),
|
||||
argumentSet("NettyDataBufferFactory - PooledByteBufAllocator - preferDirect = false",
|
||||
new NettyDataBufferFactory(netty4OnHeapPooled)),
|
||||
// Netty 5
|
||||
argumentSet("Netty5DataBufferFactory - BufferAllocator.onHeapUnpooled()",
|
||||
new Netty5DataBufferFactory(netty5OnHeapUnpooled)),
|
||||
argumentSet("Netty5DataBufferFactory - BufferAllocator.offHeapUnpooled()",
|
||||
new Netty5DataBufferFactory(netty5OffHeapUnpooled)),
|
||||
argumentSet("Netty5DataBufferFactory - BufferAllocator.onHeapPooled()",
|
||||
new Netty5DataBufferFactory(netty5OnHeapPooled)),
|
||||
argumentSet("Netty5DataBufferFactory - BufferAllocator.offHeapPooled()",
|
||||
new Netty5DataBufferFactory(netty5OffHeapPooled)),
|
||||
// Default
|
||||
argumentSet("DefaultDataBufferFactory - preferDirect = true",
|
||||
new DefaultDataBufferFactory(true)),
|
||||
|
||||
Reference in New Issue
Block a user