提交 c13f8419 编写于 作者: J Juergen Hoeller

Minor revision of reactive support layout (ahead of 5.0 M1)

DataSourceUtils moved to main core.io.buffer package.
Consistently named Jackson2JsonDecoder/Encoder and Jaxb2XmlDecoder/Encoder.
Plenty of related polishing.
上级 3d6a5bcd
......@@ -17,7 +17,6 @@
package org.springframework.core.codec;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.reactivestreams.Publisher;
......@@ -36,7 +35,7 @@ import org.springframework.util.MimeType;
*/
public abstract class AbstractDecoder<T> implements Decoder<T> {
private List<MimeType> decodableMimeTypes = Collections.emptyList();
private final List<MimeType> decodableMimeTypes;
protected AbstractDecoder(MimeType... supportedMimeTypes) {
......@@ -54,7 +53,7 @@ public abstract class AbstractDecoder<T> implements Decoder<T> {
if (mimeType == null) {
return true;
}
return this.decodableMimeTypes.stream().anyMatch(m -> m.isCompatibleWith(mimeType));
return this.decodableMimeTypes.stream().anyMatch(candidate -> candidate.isCompatibleWith(mimeType));
}
@Override
......
......@@ -17,7 +17,6 @@
package org.springframework.core.codec;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.springframework.core.ResolvableType;
......@@ -32,7 +31,7 @@ import org.springframework.util.MimeType;
*/
public abstract class AbstractEncoder<T> implements Encoder<T> {
private List<MimeType> encodableMimeTypes = Collections.emptyList();
private final List<MimeType> encodableMimeTypes;
protected AbstractEncoder(MimeType... supportedMimeTypes) {
......@@ -50,7 +49,7 @@ public abstract class AbstractEncoder<T> implements Encoder<T> {
if (mimeType == null) {
return true;
}
return this.encodableMimeTypes.stream().anyMatch(m -> m.isCompatibleWith(mimeType));
return this.encodableMimeTypes.stream().anyMatch(candidate -> candidate.isCompatibleWith(mimeType));
}
}
......@@ -40,9 +40,8 @@ public abstract class AbstractSingleValueEncoder<T> extends AbstractEncoder<T> {
@Override
public final Flux<DataBuffer> encode(Publisher<? extends T> inputStream,
DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType,
Object... hints) {
public final Flux<DataBuffer> encode(Publisher<? extends T> inputStream, DataBufferFactory bufferFactory,
ResolvableType elementType, MimeType mimeType, Object... hints) {
return Flux.from(inputStream).
take(1).
......
......@@ -23,7 +23,7 @@ import reactor.core.publisher.Flux;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
......@@ -36,7 +36,6 @@ import org.springframework.util.MimeTypeUtils;
*/
public class ByteBufferDecoder extends AbstractDecoder<ByteBuffer> {
public ByteBufferDecoder() {
super(MimeTypeUtils.ALL);
}
......@@ -61,4 +60,4 @@ public class ByteBufferDecoder extends AbstractDecoder<ByteBuffer> {
});
}
}
\ No newline at end of file
}
......@@ -35,7 +35,6 @@ import org.springframework.util.MimeTypeUtils;
*/
public class ByteBufferEncoder extends AbstractEncoder<ByteBuffer> {
public ByteBufferEncoder() {
super(MimeTypeUtils.ALL);
}
......@@ -55,4 +54,4 @@ public class ByteBufferEncoder extends AbstractEncoder<ByteBuffer> {
return Flux.from(inputStream).map(bufferFactory::wrap);
}
}
\ No newline at end of file
}
......@@ -30,7 +30,7 @@ import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.util.MimeType;
/**
* Encode from a CharSequence stream to a bytes stream.
* Encode from a {@code CharSequence} stream to a bytes stream.
*
* @author Sebastien Deleuze
* @author Arjen Poutsma
......
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
......@@ -27,12 +27,12 @@ import org.springframework.core.NestedRuntimeException;
@SuppressWarnings("serial")
public class CodecException extends NestedRuntimeException {
public CodecException(String msg, Throwable cause) {
super(msg, cause);
}
public CodecException(String msg) {
super(msg);
}
public CodecException(String msg, Throwable cause) {
super(msg, cause);
}
}
......@@ -32,15 +32,14 @@ import org.springframework.util.MimeType;
*
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
* @param <T> the type of elements in the output stream
* @since 5.0
* @param <T> the type of elements in the output stream
*/
public interface Decoder<T> {
/**
* Whether the decoder supports the given target element type and the MIME
* type of the source stream.
*
* @param elementType the target element type for the output stream
* @param mimeType the mime type associated with the stream to decode
* @param hints additional information about how to do decode, optional
......@@ -50,7 +49,6 @@ public interface Decoder<T> {
/**
* Decode a {@link DataBuffer} input stream into a Flux of {@code T}.
*
* @param inputStream the {@code DataBuffer} input stream to decode
* @param elementType the expected type of elements in the output stream;
* this type must have been previously passed to the {@link #canDecode}
......@@ -64,7 +62,6 @@ public interface Decoder<T> {
/**
* Decode a {@link DataBuffer} input stream into a Mono of {@code T}.
*
* @param inputStream the {@code DataBuffer} input stream to decode
* @param elementType the expected type of elements in the output stream;
* this type must have been previously passed to the {@link #canDecode}
......
......@@ -32,15 +32,14 @@ import org.springframework.util.MimeType;
*
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
* @param <T> the type of elements in the input stream
* @since 5.0
* @param <T> the type of elements in the input stream
*/
public interface Encoder<T> {
/**
* Whether the encoder supports the given source element type and the MIME
* type for the output stream.
*
* @param elementType the type of elements in the source stream
* @param mimeType the MIME type for the output stream
* @param hints additional information about how to do encode, optional
......@@ -51,7 +50,6 @@ public interface Encoder<T> {
/**
* Encode a stream of Objects of type {@code T} into a {@link DataBuffer}
* output stream.
*
* @param inputStream the input stream of Objects to encode
* @param bufferFactory for creating output stream {@code DataBuffer}'s
* @param elementType the expected type of elements in the input stream;
......
......@@ -27,7 +27,7 @@ import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
......@@ -39,7 +39,6 @@ import org.springframework.util.MimeTypeUtils;
*/
public class ResourceDecoder extends AbstractDecoder<Resource> {
public ResourceDecoder() {
super(MimeTypeUtils.ALL);
}
......@@ -79,4 +78,5 @@ public class ResourceDecoder extends AbstractDecoder<Resource> {
return Flux.error(new IllegalStateException("Unsupported resource class: " + clazz));
}
}
}
......@@ -25,7 +25,7 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.io.Resource;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.util.Assert;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
......@@ -41,7 +41,6 @@ public class ResourceEncoder extends AbstractSingleValueEncoder<Resource> {
public static final int DEFAULT_BUFFER_SIZE = StreamUtils.BUFFER_SIZE;
private final int bufferSize;
......
......@@ -29,16 +29,16 @@ import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
/**
* Decode from a bytes stream to a String stream.
* Decode from a bytes stream to a {@code String} stream.
*
* <p>By default, this decoder will split the received {@link DataBuffer}s along newline
* characters ({@code \r\n}), but this can be changed by passing {@code false} as
* constructor argument.
* <p>By default, this decoder will split the received {@link DataBuffer}s
* along newline characters ({@code \r\n}), but this can be changed by
* passing {@code false} as a constructor argument.
*
* @author Sebastien Deleuze
* @author Brian Clozel
......@@ -59,7 +59,6 @@ public class StringDecoder extends AbstractDecoder<String> {
/**
* Create a {@code StringDecoder} that decodes a bytes stream to a String stream
*
* <p>By default, this decoder will split along new lines.
*/
public StringDecoder() {
......@@ -68,7 +67,6 @@ public class StringDecoder extends AbstractDecoder<String> {
/**
* Create a {@code StringDecoder} that decodes a bytes stream to a String stream
*
* @param splitOnNewline whether this decoder should split the received data buffers
* along newline characters
*/
......@@ -80,8 +78,8 @@ public class StringDecoder extends AbstractDecoder<String> {
@Override
public boolean canDecode(ResolvableType elementType, MimeType mimeType, Object... hints) {
return super.canDecode(elementType, mimeType, hints) &&
String.class.equals(elementType.getRawClass());
return (super.canDecode(elementType, mimeType, hints) &&
String.class.equals(elementType.getRawClass()));
}
@Override
......
......@@ -30,13 +30,13 @@ import java.util.function.IntPredicate;
public interface DataBuffer {
/**
* Returns the {@link DataBufferFactory} that created this buffer.
* Return the {@link DataBufferFactory} that created this buffer.
* @return the creating buffer factory
*/
DataBufferFactory factory();
/**
* Returns the index of the first byte in this buffer that matches the given
* Return the index of the first byte in this buffer that matches the given
* predicate.
* @param predicate the predicate to match
* @param fromIndex the index to start the search from
......@@ -46,7 +46,7 @@ public interface DataBuffer {
int indexOf(IntPredicate predicate, int fromIndex);
/**
* Returns the index of the last byte in this buffer that matches the given
* Return the index of the last byte in this buffer that matches the given
* predicate.
* @param predicate the predicate to match
* @param fromIndex the index to start the search from
......@@ -56,28 +56,27 @@ public interface DataBuffer {
int lastIndexOf(IntPredicate predicate, int fromIndex);
/**
* Returns the number of bytes that can be read from this data buffer.
* Return the number of bytes that can be read from this data buffer.
* @return the readable byte count
*/
int readableByteCount();
/**
* Reads a single byte from the current reading position of this data buffer.
* Read a single byte from the current reading position of this data buffer.
* @return the byte at this buffer's current reading position
*/
byte read();
/**
* Reads this buffer's data into the specified destination, starting at the current
* Read this buffer's data into the specified destination, starting at the current
* reading position of this buffer.
*
* @param destination the array into which the bytes are to be written
* @return this buffer
*/
DataBuffer read(byte[] destination);
/**
* Reads at most {@code length} bytes of this buffer into the specified destination,
* Read at most {@code length} bytes of this buffer into the specified destination,
* starting at the current reading position of this buffer.
* @param destination the array into which the bytes are to be written
* @param offset the index within {@code destination} of the first byte to be written
......@@ -94,7 +93,7 @@ public interface DataBuffer {
DataBuffer write(byte b);
/**
* Writes the given source into this buffer, startin at the current writing position
* Write the given source into this buffer, startin at the current writing position
* of this buffer.
* @param source the bytes to be written into this buffer
* @return this buffer
......@@ -102,7 +101,7 @@ public interface DataBuffer {
DataBuffer write(byte[] source);
/**
* Writes at most {@code length} bytes of the given source into this buffer, starting
* Write at most {@code length} bytes of the given source into this buffer, starting
* at the current writing position of this buffer.
* @param source the bytes to be written into this buffer
* @param offset the index withing {@code source} to start writing from
......@@ -112,7 +111,7 @@ public interface DataBuffer {
DataBuffer write(byte[] source, int offset, int length);
/**
* Writes one or more {@code DataBuffer}s to this buffer, starting at the current
* Write one or more {@code DataBuffer}s to this buffer, starting at the current
* writing position.
* @param buffers the byte buffers to write into this buffer
* @return this buffer
......@@ -120,7 +119,7 @@ public interface DataBuffer {
DataBuffer write(DataBuffer... buffers);
/**
* Writes one or more {@link ByteBuffer} to this buffer, starting at the current
* Write one or more {@link ByteBuffer} to this buffer, starting at the current
* writing position.
* @param buffers the byte buffers to write into this buffer
* @return this buffer
......@@ -128,7 +127,7 @@ public interface DataBuffer {
DataBuffer write(ByteBuffer... buffers);
/**
* Creates a new {@code DataBuffer} whose contents is a shared subsequence of this
* Create a new {@code DataBuffer} whose contents is a shared subsequence of this
* data buffer's content. Data between this data buffer and the returned buffer is
* shared; though changes in the returned buffer's position will not be reflected
* in the reading nor writing position of this data buffer.
......@@ -139,23 +138,23 @@ public interface DataBuffer {
DataBuffer slice(int index, int length);
/**
* Exposes this buffer's bytes as a {@link ByteBuffer}. Data between this {@code
* DataBuffer} and the returned {@code ByteBuffer} is shared; though changes in the
* returned buffer's {@linkplain ByteBuffer#position() position} will not be reflected
* in the reading nor writing position of this data buffer.
* Expose this buffer's bytes as a {@link ByteBuffer}. Data between this
* {@code DataBuffer} and the returned {@code ByteBuffer} is shared; though
* changes in the returned buffer's {@linkplain ByteBuffer#position() position}
* will not be reflected in the reading nor writing position of this data buffer.
* @return this data buffer as a byte buffer
*/
ByteBuffer asByteBuffer();
/**
* Exposes this buffer's data as an {@link InputStream}. Both data and position are
* Expose this buffer's data as an {@link InputStream}. Both data and position are
* shared between the returned stream and this data buffer.
* @return this data buffer as an input stream
*/
InputStream asInputStream();
/**
* Exposes this buffer's data as an {@link OutputStream}. Both data and position are
* Expose this buffer's data as an {@link OutputStream}. Both data and position are
* shared between the returned stream and this data buffer.
* @return this data buffer as an output stream
*/
......
......@@ -23,8 +23,8 @@ import java.nio.ByteBuffer;
* data buffers.
*
* @author Arjen Poutsma
* @see DataBuffer
* @since 5.0
* @see DataBuffer
*/
public interface DataBufferFactory {
......
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.core.io.buffer.support;
package org.springframework.core.io.buffer;
import java.io.IOException;
import java.io.InputStream;
......@@ -29,9 +29,6 @@ import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.SynchronousSink;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.PooledDataBuffer;
import org.springframework.util.Assert;
/**i
......@@ -48,12 +45,13 @@ public abstract class DataBufferUtils {
channel.close();
}
}
catch (IOException ignored) {
catch (IOException ex) {
}
};
/**
* Reads the given {@code InputStream} into a {@code Flux} of
* Read the given {@code InputStream} into a {@code Flux} of
* {@code DataBuffer}s. Closes the input stream when the flux is terminated.
* @param inputStream the input stream to read from
* @param dataBufferFactory the factory to create data buffers with
......@@ -62,15 +60,16 @@ public abstract class DataBufferUtils {
*/
public static Flux<DataBuffer> read(InputStream inputStream,
DataBufferFactory dataBufferFactory, int bufferSize) {
Assert.notNull(inputStream, "'inputStream' must not be null");
Assert.notNull(dataBufferFactory, "'dataBufferFactory' must not be null");
Assert.notNull(inputStream, "InputStream must not be null");
Assert.notNull(dataBufferFactory, "DataBufferFactory must not be null");
ReadableByteChannel channel = Channels.newChannel(inputStream);
return read(channel, dataBufferFactory, bufferSize);
}
/**
* Reads the given {@code ReadableByteChannel} into a {@code Flux} of
* Read the given {@code ReadableByteChannel} into a {@code Flux} of
* {@code DataBuffer}s. Closes the channel when the flux is terminated.
* @param channel the channel to read from
* @param dataBufferFactory the factory to create data buffers with
......@@ -79,8 +78,9 @@ public abstract class DataBufferUtils {
*/
public static Flux<DataBuffer> read(ReadableByteChannel channel,
DataBufferFactory dataBufferFactory, int bufferSize) {
Assert.notNull(channel, "'channel' must not be null");
Assert.notNull(dataBufferFactory, "'dataBufferFactory' must not be null");
Assert.notNull(channel, "ReadableByteChannel must not be null");
Assert.notNull(dataBufferFactory, "DataBufferFactory must not be null");
return Flux.generate(() -> channel,
new ReadableByteChannelGenerator(dataBufferFactory, bufferSize),
......@@ -88,18 +88,16 @@ public abstract class DataBufferUtils {
}
/**
* Relays buffers from the given {@link Publisher} until the total
* {@linkplain DataBuffer#readableByteCount() byte count} reaches the given
* maximum byte count, or until the publisher is complete.
* Relay buffers from the given {@link Publisher} until the total
* {@linkplain DataBuffer#readableByteCount() byte count} reaches
* the given maximum byte count, or until the publisher is complete.
* @param publisher the publisher to filter
* @param maxByteCount the maximum byte count
* @return a flux whose maximum byte count is {@code maxByteCount}
*/
public static Flux<DataBuffer> takeUntilByteCount(Publisher<DataBuffer> publisher,
long maxByteCount) {
Assert.notNull(publisher, "'publisher' must not be null");
public static Flux<DataBuffer> takeUntilByteCount(Publisher<DataBuffer> publisher, long maxByteCount) {
Assert.notNull(publisher, "Publisher must not be null");
Assert.isTrue(maxByteCount >= 0, "'maxByteCount' must be a positive number");
AtomicLong byteCountDown = new AtomicLong(maxByteCount);
return Flux.from(publisher).
......@@ -122,7 +120,7 @@ public abstract class DataBufferUtils {
}
/**
* Retains the given data buffer, it it is a {@link PooledDataBuffer}.
* Retain the given data buffer, it it is a {@link PooledDataBuffer}.
* @param dataBuffer the data buffer to retain
* @return the retained buffer
*/
......@@ -137,7 +135,7 @@ public abstract class DataBufferUtils {
}
/**
* Releases the given data buffer, if it is a {@link PooledDataBuffer}.
* Release the given data buffer, if it is a {@link PooledDataBuffer}.
* @param dataBuffer the data buffer to release
* @return {@code true} if the buffer was released; {@code false} otherwise.
*/
......@@ -148,23 +146,21 @@ public abstract class DataBufferUtils {
return false;
}
private static class ReadableByteChannelGenerator
implements BiFunction<ReadableByteChannel, SynchronousSink<DataBuffer>,
ReadableByteChannel> {
implements BiFunction<ReadableByteChannel, SynchronousSink<DataBuffer>, ReadableByteChannel> {
private final DataBufferFactory dataBufferFactory;
private final int chunkSize;
public ReadableByteChannelGenerator(DataBufferFactory dataBufferFactory,
int chunkSize) {
public ReadableByteChannelGenerator(DataBufferFactory dataBufferFactory, int chunkSize) {
this.dataBufferFactory = dataBufferFactory;
this.chunkSize = chunkSize;
}
@Override
public ReadableByteChannel apply(ReadableByteChannel
channel, SynchronousSink<DataBuffer> sub) {
public ReadableByteChannel apply(ReadableByteChannel channel, SynchronousSink<DataBuffer> sub) {
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(chunkSize);
int read;
......
......@@ -46,6 +46,7 @@ public class DefaultDataBuffer implements DataBuffer {
private int writePosition;
/**
* Create a new {@code DefaultDataBuffer} based on the given
* {@code ByteBuffer}. Both reading and writing position of this buffer are
......@@ -59,6 +60,7 @@ public class DefaultDataBuffer implements DataBuffer {
DefaultDataBuffer(ByteBuffer byteBuffer, int readPosition, int writePosition,
DefaultDataBufferFactory dataBufferFactory) {
Assert.notNull(byteBuffer, "'byteBuffer' must not be null");
Assert.isTrue(readPosition >= 0, "'readPosition' must be 0 or higher");
Assert.isTrue(writePosition >= 0, "'writePosition' must be 0 or higher");
......@@ -72,10 +74,6 @@ public class DefaultDataBuffer implements DataBuffer {
this.dataBufferFactory = dataBufferFactory;
}
@Override
public DefaultDataBufferFactory factory() {
return this.dataBufferFactory;
}
/**
* Directly exposes the native {@code ByteBuffer} that this buffer is based on.
......@@ -85,6 +83,11 @@ public class DefaultDataBuffer implements DataBuffer {
return this.byteBuffer;
}
@Override
public DefaultDataBufferFactory factory() {
return this.dataBufferFactory;
}
@Override
public int indexOf(IntPredicate predicate, int fromIndex) {
Assert.notNull(predicate, "'predicate' must not be null");
......@@ -130,18 +133,14 @@ public class DefaultDataBuffer implements DataBuffer {
@Override
public DefaultDataBuffer read(byte[] destination) {
Assert.notNull(destination, "'destination' must not be null");
readInternal(b -> b.get(destination));
return this;
}
@Override
public DefaultDataBuffer read(byte[] destination, int offset, int length) {
Assert.notNull(destination, "'destination' must not be null");
readInternal(b -> b.get(destination, offset, length));
return this;
}
......@@ -163,14 +162,12 @@ public class DefaultDataBuffer implements DataBuffer {
public DefaultDataBuffer write(byte b) {
ensureExtraCapacity(1);
writeInternal(buffer -> buffer.put(b));
return this;
}
@Override
public DefaultDataBuffer write(byte[] source) {
Assert.notNull(source, "'source' must not be null");
ensureExtraCapacity(source.length);
writeInternal(buffer -> buffer.put(source));
return this;
......@@ -179,7 +176,6 @@ public class DefaultDataBuffer implements DataBuffer {
@Override
public DefaultDataBuffer write(byte[] source, int offset, int length) {
Assert.notNull(source, "'source' must not be null");
ensureExtraCapacity(length);
writeInternal(buffer -> buffer.put(source, offset, length));
return this;
......@@ -199,15 +195,10 @@ public class DefaultDataBuffer implements DataBuffer {
@Override
public DefaultDataBuffer write(ByteBuffer... byteBuffers) {
Assert.notEmpty(byteBuffers, "'byteBuffers' must not be empty");
int extraCapacity =
Arrays.stream(byteBuffers).mapToInt(ByteBuffer::remaining).sum();
int extraCapacity = Arrays.stream(byteBuffers).mapToInt(ByteBuffer::remaining).sum();
ensureExtraCapacity(extraCapacity);
Arrays.stream(byteBuffers)
.forEach(byteBuffer -> writeInternal(buffer -> buffer.put(byteBuffer)));
return this;
}
......@@ -279,23 +270,23 @@ public class DefaultDataBuffer implements DataBuffer {
}
@Override
public int hashCode() {
return this.byteBuffer.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
else if (obj instanceof DefaultDataBuffer) {
DefaultDataBuffer other = (DefaultDataBuffer) obj;
return this.readPosition == other.readPosition &&
this.writePosition == other.writePosition &&
this.byteBuffer.equals(other.byteBuffer);
if (!(obj instanceof DefaultDataBuffer)) {
return false;
}
return false;
DefaultDataBuffer other = (DefaultDataBuffer) obj;
return (this.readPosition == other.readPosition &&
this.writePosition == other.writePosition &&
this.byteBuffer.equals(other.byteBuffer));
}
@Override
public int hashCode() {
return this.byteBuffer.hashCode();
}
@Override
......@@ -303,6 +294,7 @@ public class DefaultDataBuffer implements DataBuffer {
return this.byteBuffer.toString();
}
private class DefaultDataBufferInputStream extends InputStream {
@Override
......@@ -332,6 +324,7 @@ public class DefaultDataBuffer implements DataBuffer {
}
}
private class DefaultDataBufferOutputStream extends OutputStream {
@Override
......@@ -347,6 +340,7 @@ public class DefaultDataBuffer implements DataBuffer {
}
}
private static class SlicedDefaultDataBuffer extends DefaultDataBuffer {
SlicedDefaultDataBuffer(ByteBuffer byteBuffer, int readPosition,
......@@ -360,4 +354,5 @@ public class DefaultDataBuffer implements DataBuffer {
"Growing the capacity of a sliced buffer is not supported");
}
}
}
......@@ -70,8 +70,7 @@ public class DefaultDataBufferFactory implements DataBufferFactory {
* {@code false} otherwise
*/
public DefaultDataBufferFactory(boolean preferDirect, int defaultInitialCapacity) {
Assert.isTrue(defaultInitialCapacity > 0,
"'defaultInitialCapacity' should be larger than 0");
Assert.isTrue(defaultInitialCapacity > 0, "'defaultInitialCapacity' should be larger than 0");
this.preferDirect = preferDirect;
this.defaultInitialCapacity = defaultInitialCapacity;
}
......@@ -84,9 +83,9 @@ public class DefaultDataBufferFactory implements DataBufferFactory {
@Override
public DefaultDataBuffer allocateBuffer(int initialCapacity) {
return this.preferDirect ?
return (this.preferDirect ?
new DefaultDataBuffer(ByteBuffer.allocateDirect(initialCapacity), this) :
new DefaultDataBuffer(ByteBuffer.allocate(initialCapacity), this);
new DefaultDataBuffer(ByteBuffer.allocate(initialCapacity), this));
}
@Override
......@@ -97,7 +96,7 @@ public class DefaultDataBufferFactory implements DataBufferFactory {
@Override
public String toString() {
return "DefaultDataBufferFactory - preferDirect: " + this.preferDirect;
return "DefaultDataBufferFactory (preferDirect=" + this.preferDirect + ")";
}
}
......@@ -44,6 +44,7 @@ public class NettyDataBuffer implements PooledDataBuffer {
private ByteBuf byteBuf;
/**
* Creates a new {@code NettyDataBuffer} based on the given {@code ByteBuff}.
* @param byteBuf the buffer to base this buffer on
......@@ -56,10 +57,6 @@ public class NettyDataBuffer implements PooledDataBuffer {
this.dataBufferFactory = dataBufferFactory;
}
@Override
public NettyDataBufferFactory factory() {
return this.dataBufferFactory;
}
/**
* Directly exposes the native {@code ByteBuf} that this buffer is based on.
......@@ -69,6 +66,11 @@ public class NettyDataBuffer implements PooledDataBuffer {
return this.byteBuf;
}
@Override
public NettyDataBufferFactory factory() {
return this.dataBufferFactory;
}
@Override
public int indexOf(IntPredicate predicate, int fromIndex) {
Assert.notNull(predicate, "'predicate' must not be null");
......@@ -79,7 +81,6 @@ public class NettyDataBuffer implements PooledDataBuffer {
return -1;
}
int length = this.byteBuf.writerIndex() - fromIndex;
return this.byteBuf.forEachByte(fromIndex, length, predicate.negate()::test);
}
......@@ -90,7 +91,6 @@ public class NettyDataBuffer implements PooledDataBuffer {
return -1;
}
fromIndex = Math.min(fromIndex, this.byteBuf.writerIndex() - 1);
return this.byteBuf.forEachByteDesc(0, fromIndex, predicate.negate()::test);
}
......@@ -141,7 +141,6 @@ public class NettyDataBuffer implements PooledDataBuffer {
ByteBuf[] nativeBuffers = Arrays.stream(buffers)
.map(b -> ((NettyDataBuffer) b).getNativeBuffer())
.toArray(ByteBuf[]::new);
write(nativeBuffers);
}
else {
......@@ -157,10 +156,8 @@ public class NettyDataBuffer implements PooledDataBuffer {
@Override
public NettyDataBuffer write(ByteBuffer... buffers) {
Assert.notNull(buffers, "'buffers' must not be null");
ByteBuf[] wrappedBuffers = Arrays.stream(buffers).map(Unpooled::wrappedBuffer)
.toArray(ByteBuf[]::new);
return write(wrappedBuffers);
}
......@@ -173,9 +170,8 @@ public class NettyDataBuffer implements PooledDataBuffer {
public NettyDataBuffer write(ByteBuf... byteBufs) {
Assert.notNull(byteBufs, "'byteBufs' must not be null");
CompositeByteBuf composite =
new CompositeByteBuf(this.byteBuf.alloc(), this.byteBuf.isDirect(),
byteBufs.length + 1);
CompositeByteBuf composite = new CompositeByteBuf(
this.byteBuf.alloc(), this.byteBuf.isDirect(), byteBufs.length + 1);
composite.addComponent(this.byteBuf);
composite.addComponents(byteBufs);
......@@ -184,7 +180,6 @@ public class NettyDataBuffer implements PooledDataBuffer {
composite.writerIndex(writerIndex);
this.byteBuf = composite;
return this;
}
......@@ -219,25 +214,27 @@ public class NettyDataBuffer implements PooledDataBuffer {
return this.byteBuf.release();
}
@Override
public int hashCode() {
return this.byteBuf.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
else if (obj instanceof NettyDataBuffer) {
NettyDataBuffer other = (NettyDataBuffer) obj;
return this.byteBuf.equals(other.byteBuf);
if (!(obj instanceof NettyDataBuffer)) {
return false;
}
return false;
NettyDataBuffer other = (NettyDataBuffer) obj;
return this.byteBuf.equals(other.byteBuf);
}
@Override
public int hashCode() {
return this.byteBuf.hashCode();
}
@Override
public String toString() {
return this.byteBuf.toString();
}
}
......@@ -25,8 +25,8 @@ import io.netty.buffer.Unpooled;
import org.springframework.util.Assert;
/**
* Implementation of the {@code DataBufferFactory} interface based on a Netty
* {@link ByteBufAllocator}.
* Implementation of the {@code DataBufferFactory} interface based on a
* Netty {@link ByteBufAllocator}.
*
* @author Arjen Poutsma
* @since 5.0
......@@ -46,7 +46,6 @@ public class NettyDataBufferFactory implements DataBufferFactory {
*/
public NettyDataBufferFactory(ByteBufAllocator byteBufAllocator) {
Assert.notNull(byteBufAllocator, "'byteBufAllocator' must not be null");
this.byteBufAllocator = byteBufAllocator;
}
......@@ -70,7 +69,7 @@ public class NettyDataBufferFactory implements DataBufferFactory {
}
/**
* Wraps the given Netty {@link ByteBuf} in a {@code NettyDataBuffer}.
* Wrap the given Netty {@link ByteBuf} in a {@code NettyDataBuffer}.
* @param byteBuf the Netty byte buffer to wrap
* @return the wrapped buffer
*/
......@@ -79,7 +78,7 @@ public class NettyDataBufferFactory implements DataBufferFactory {
}
/**
* Returns the given Netty {@link DataBuffer} as a {@link ByteBuf}. Returns the
* Return the given Netty {@link DataBuffer} as a {@link ByteBuf}. Returns the
* {@linkplain NettyDataBuffer#getNativeBuffer() native buffer} if {@code buffer} is
* a {@link NettyDataBuffer}; returns {@link Unpooled#wrappedBuffer(ByteBuffer)}
* otherwise.
......
......@@ -26,13 +26,13 @@ package org.springframework.core.io.buffer;
public interface PooledDataBuffer extends DataBuffer {
/**
* Increases the reference count for this buffer by one.
* Increase the reference count for this buffer by one.
* @return this buffer
*/
PooledDataBuffer retain();
/**
* Decreases the reference count for this buffer by one, and releases it
* Decrease the reference count for this buffer by one, and release it
* once the count reaches zero.
* @return {@code true} if the buffer was released; {@code false} otherwise.
*/
......
/**
* Support classes for Spring's byte buffer abstraction.
*/
package org.springframework.core.io.buffer.support;
......@@ -16,8 +16,6 @@
package org.springframework.core.codec;
import java.nio.charset.StandardCharsets;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -28,7 +26,6 @@ import reactor.test.TestSubscriber;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import org.springframework.util.MimeTypeUtils;
import static org.junit.Assert.assertFalse;
......
......@@ -26,9 +26,8 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;
/**
* @author Arjen Poutsma
......
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.core.io.buffer.support;
package org.springframework.core.io.buffer;
import java.io.InputStream;
import java.net.URI;
......@@ -26,10 +26,7 @@ import org.junit.Test;
import reactor.core.publisher.Flux;
import reactor.test.TestSubscriber;
import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase;
import org.springframework.core.io.buffer.DataBuffer;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.*;
/**
* @author Arjen Poutsma
......@@ -38,10 +35,8 @@ public class DataBufferUtilsTests extends AbstractDataBufferAllocatingTestCase {
@Test
public void readChannel() throws Exception {
URI uri = DataBufferUtilsTests.class.getResource("DataBufferUtilsTests.txt")
.toURI();
URI uri = DataBufferUtilsTests.class.getResource("DataBufferUtilsTests.txt").toURI();
FileChannel channel = FileChannel.open(Paths.get(uri), StandardOpenOption.READ);
Flux<DataBuffer> flux = DataBufferUtils.read(channel, this.bufferFactory, 3);
TestSubscriber
......@@ -57,10 +52,8 @@ public class DataBufferUtilsTests extends AbstractDataBufferAllocatingTestCase {
@Test
public void readUnalignedChannel() throws Exception {
URI uri = DataBufferUtilsTests.class.getResource("DataBufferUtilsTests.txt")
.toURI();
URI uri = DataBufferUtilsTests.class.getResource("DataBufferUtilsTests.txt").toURI();
FileChannel channel = FileChannel.open(Paths.get(uri), StandardOpenOption.READ);
Flux<DataBuffer> flux = DataBufferUtils.read(channel, this.bufferFactory, 5);
TestSubscriber
......@@ -77,9 +70,7 @@ public class DataBufferUtilsTests extends AbstractDataBufferAllocatingTestCase {
@Test
public void readInputStream() {
InputStream is = DataBufferUtilsTests.class
.getResourceAsStream("DataBufferUtilsTests.txt");
InputStream is = DataBufferUtilsTests.class.getResourceAsStream("DataBufferUtilsTests.txt");
Flux<DataBuffer> flux = DataBufferUtils.read(is, this.bufferFactory, 3);
TestSubscriber
......@@ -97,7 +88,6 @@ public class DataBufferUtilsTests extends AbstractDataBufferAllocatingTestCase {
DataBuffer bar = stringBuffer("bar");
DataBuffer baz = stringBuffer("baz");
Flux<DataBuffer> flux = Flux.just(foo, bar, baz);
Flux<DataBuffer> result = DataBufferUtils.takeUntilByteCount(flux, 5L);
TestSubscriber
......@@ -109,4 +99,4 @@ public class DataBufferUtilsTests extends AbstractDataBufferAllocatingTestCase {
release(baz);
}
}
\ No newline at end of file
}
......@@ -24,16 +24,15 @@ import org.springframework.util.Assert;
/**
* Utility class for working with {@link DataBuffer}s in tests.
*
* <p>Note that this class is in the {@code test} tree of the project: the methods
* contained herein are not suitable for production code bases.
* <p>Note that this class is in the {@code test} tree of the project:
* the methods contained herein are not suitable for production code bases.
*
* @author Arjen Poutsma
*/
public abstract class DataBufferTestUtils {
/**
* Dumps all the bytes in the given data buffer, and returns them as a byte array.
*
* Dump all the bytes in the given data buffer, and returns them as a byte array.
* <p>Note that this method reads the entire buffer into the heap, which might
* consume a lot of memory.
* @param buffer the data buffer to dump the bytes of
......@@ -41,15 +40,13 @@ public abstract class DataBufferTestUtils {
*/
public static byte[] dumpBytes(DataBuffer buffer) {
Assert.notNull(buffer, "'buffer' must not be null");
byte[] bytes = new byte[buffer.readableByteCount()];
buffer.read(bytes);
return bytes;
}
/**
* Dumps all the bytes in the given data buffer, and returns them as a string.
*
* Dump all the bytes in the given data buffer, and returns them as a string.
* <p>Note that this method reads the entire buffer into the heap, which might
* consume a lot of memory.
* @param buffer the data buffer to dump the string contents of
......@@ -58,8 +55,8 @@ public abstract class DataBufferTestUtils {
*/
public static String dumpString(DataBuffer buffer, Charset charset) {
Assert.notNull(charset, "'charset' must not be null");
byte[] bytes = dumpBytes(buffer);
return new String(bytes, charset);
}
}
......@@ -39,16 +39,16 @@ import org.springframework.format.FormatterRegistry;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.MediaType;
import org.springframework.http.codec.json.JacksonJsonDecoder;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2Decoder;
import org.springframework.http.codec.xml.Jaxb2Encoder;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.SseEventHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.util.ClassUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
......@@ -249,10 +249,10 @@ public class WebReactiveConfiguration implements ApplicationContextAware {
readers.add(new DecoderHttpMessageReader<>(new StringDecoder()));
readers.add(new DecoderHttpMessageReader<>(new ResourceDecoder()));
if (jaxb2Present) {
readers.add(new DecoderHttpMessageReader<>(new Jaxb2Decoder()));
readers.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder()));
}
if (jackson2Present) {
readers.add(new DecoderHttpMessageReader<>(new JacksonJsonDecoder()));
readers.add(new DecoderHttpMessageReader<>(new Jackson2JsonDecoder()));
}
}
......@@ -371,10 +371,10 @@ public class WebReactiveConfiguration implements ApplicationContextAware {
writers.add(new EncoderHttpMessageWriter<>(new CharSequenceEncoder()));
writers.add(new ResourceHttpMessageWriter());
if (jaxb2Present) {
writers.add(new EncoderHttpMessageWriter<>(new Jaxb2Encoder()));
writers.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
}
if (jackson2Present) {
JacksonJsonEncoder jacksonEncoder = new JacksonJsonEncoder();
Jackson2JsonEncoder jacksonEncoder = new Jackson2JsonEncoder();
writers.add(new EncoderHttpMessageWriter<>(jacksonEncoder));
sseDataEncoders.add(jacksonEncoder);
}
......
......@@ -19,18 +19,14 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.core.Ordered;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.reactive.result.view.HttpMessageWriterView;
import org.springframework.web.reactive.result.view.UrlBasedViewResolver;
import org.springframework.web.reactive.result.view.View;
import org.springframework.web.reactive.result.view.freemarker.FreeMarkerConfigurer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
/**
* Unit tests for {@link ViewResolverRegistry}.
......@@ -80,7 +76,7 @@ public class ViewResolverRegistryTests {
@Test
public void defaultViews() throws Exception {
View view = new HttpMessageWriterView(new JacksonJsonEncoder());
View view = new HttpMessageWriterView(new Jackson2JsonEncoder());
this.registry.defaultViews(view);
assertEquals(1, this.registry.getDefaultViews().size());
......
......@@ -41,13 +41,13 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2Decoder;
import org.springframework.http.codec.xml.Jaxb2Encoder;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.http.server.reactive.MockServerHttpRequest;
import org.springframework.http.server.reactive.MockServerHttpResponse;
import org.springframework.util.MimeType;
......@@ -305,12 +305,12 @@ public class WebReactiveConfigurationTests {
@Override
protected void extendMessageReaders(List<HttpMessageReader<?>> messageReaders) {
messageReaders.add(new DecoderHttpMessageReader<>(new Jaxb2Decoder()));
messageReaders.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder()));
}
@Override
protected void extendMessageWriters(List<HttpMessageWriter<?>> messageWriters) {
messageWriters.add(new EncoderHttpMessageWriter<>(new Jaxb2Encoder()));
messageWriters.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
}
}
......@@ -320,7 +320,7 @@ public class WebReactiveConfigurationTests {
@Override
protected void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker();
registry.defaultViews(new HttpMessageWriterView(new JacksonJsonEncoder()));
registry.defaultViews(new HttpMessageWriterView(new Jackson2JsonEncoder()));
}
@Bean
......
......@@ -46,9 +46,9 @@ import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.codec.json.JacksonJsonDecoder;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.server.reactive.MockServerHttpRequest;
import org.springframework.http.server.reactive.MockServerHttpResponse;
import org.springframework.validation.Errors;
......@@ -62,12 +62,8 @@ import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.server.session.MockWebSessionManager;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.core.ResolvableType.forClass;
import static org.springframework.core.ResolvableType.forClassWithGenerics;
import static org.junit.Assert.*;
import static org.springframework.core.ResolvableType.*;
/**
* Unit tests for {@link AbstractMessageReaderArgumentResolver}.
......@@ -75,7 +71,7 @@ import static org.springframework.core.ResolvableType.forClassWithGenerics;
*/
public class MessageReaderArgumentResolverTests {
private AbstractMessageReaderArgumentResolver resolver = resolver(new JacksonJsonDecoder());
private AbstractMessageReaderArgumentResolver resolver = resolver(new Jackson2JsonDecoder());
private ServerWebExchange exchange;
......
......@@ -44,11 +44,11 @@ import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2Encoder;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.http.server.reactive.MockServerHttpRequest;
import org.springframework.http.server.reactive.MockServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
......@@ -60,11 +60,9 @@ import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.server.session.MockWebSessionManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8;
import static org.springframework.web.reactive.HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE;
import static org.junit.Assert.*;
import static org.springframework.http.MediaType.*;
import static org.springframework.web.reactive.HandlerMapping.*;
/**
* Unit tests for {@link AbstractMessageWriterResultHandler}.
......@@ -177,8 +175,8 @@ public class MessageWriterResultHandlerTests {
writerList.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new CharSequenceEncoder()));
writerList.add(new ResourceHttpMessageWriter());
writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2Encoder()));
writerList.add(new EncoderHttpMessageWriter<>(new JacksonJsonEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()));
}
else {
writerList = Arrays.asList(writers);
......
......@@ -45,7 +45,7 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.server.reactive.ZeroCopyIntegrationTests;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
......@@ -54,10 +54,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.config.WebReactiveConfiguration;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.springframework.http.MediaType.APPLICATION_XML;
import static java.util.Arrays.*;
import static org.junit.Assert.*;
import static org.springframework.http.MediaType.*;
/**
......@@ -286,7 +285,7 @@ public class RequestMappingMessageConversionIntegrationTests extends AbstractReq
@GetMapping("/publisher")
public Publisher<ByteBuffer> getPublisher() {
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
JacksonJsonEncoder encoder = new JacksonJsonEncoder();
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
return encoder.encode(Mono.just(new Person("Robert")), dataBufferFactory,
ResolvableType.forClass(Person.class), JSON).map(DataBuffer::asByteBuffer);
}
......
......@@ -29,11 +29,11 @@ import org.springframework.core.codec.ByteBufferEncoder;
import org.springframework.core.codec.CharSequenceEncoder;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2Encoder;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.http.server.reactive.MockServerHttpRequest;
import org.springframework.http.server.reactive.MockServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
......@@ -50,7 +50,7 @@ import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.server.session.MockWebSessionManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;
/**
......@@ -88,8 +88,8 @@ public class ResponseBodyResultHandlerTests {
writerList.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new CharSequenceEncoder()));
writerList.add(new ResourceHttpMessageWriter());
writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2Encoder()));
writerList.add(new EncoderHttpMessageWriter<>(new JacksonJsonEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()));
}
else {
writerList = Arrays.asList(writers);
......
......@@ -38,11 +38,11 @@ import org.springframework.core.io.buffer.support.DataBufferTestUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2Encoder;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.http.server.reactive.MockServerHttpRequest;
import org.springframework.http.server.reactive.MockServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
......@@ -55,11 +55,8 @@ import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.server.session.MockWebSessionManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.core.ResolvableType.forClassWithGenerics;
import static org.junit.Assert.*;
import static org.springframework.core.ResolvableType.*;
/**
* Unit tests for {@link ResponseEntityResultHandler}. When adding a test also
......@@ -93,8 +90,8 @@ public class ResponseEntityResultHandlerTests {
writerList.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new CharSequenceEncoder()));
writerList.add(new ResourceHttpMessageWriter());
writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2Encoder()));
writerList.add(new EncoderHttpMessageWriter<>(new JacksonJsonEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()));
}
else {
writerList = Arrays.asList(writers);
......
......@@ -35,8 +35,8 @@ import org.springframework.core.codec.CharSequenceEncoder;
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2Encoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.http.server.reactive.MockServerHttpRequest;
import org.springframework.http.server.reactive.MockServerHttpResponse;
import org.springframework.ui.ExtendedModelMap;
......@@ -50,7 +50,10 @@ import org.springframework.web.server.session.DefaultWebSessionManager;
import org.springframework.web.server.session.WebSessionManager;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
/**
......@@ -59,7 +62,7 @@ import static org.junit.Assert.*;
*/
public class HttpMessageWriterViewTests {
private HttpMessageWriterView view = new HttpMessageWriterView(new JacksonJsonEncoder());
private HttpMessageWriterView view = new HttpMessageWriterView(new Jackson2JsonEncoder());
private HandlerResult result;
......@@ -136,7 +139,7 @@ public class HttpMessageWriterViewTests {
@Test
public void extractObjectNotSupported() throws Exception {
HttpMessageWriterView view = new HttpMessageWriterView(new Jaxb2Encoder());
HttpMessageWriterView view = new HttpMessageWriterView(new Jaxb2XmlEncoder());
view.setModelKeys(new HashSet<>(Collections.singletonList("foo1")));
this.model.addAttribute("foo1", "bar1");
......
......@@ -28,12 +28,15 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.core.ResolvableType;
import org.springframework.util.Assert;
import org.springframework.util.MimeType;
/**
* Abstract base class for Jackson based decoder/encoder implementations.
*
* @author Sebastien Deleuze
*/
public class AbstractJacksonJsonCodec {
public class AbstractJackson2Codec {
protected static final List<MimeType> JSON_MIME_TYPES = Arrays.asList(
new MimeType("application", "json", StandardCharsets.UTF_8),
......@@ -42,10 +45,17 @@ public class AbstractJacksonJsonCodec {
protected final ObjectMapper mapper;
protected AbstractJacksonJsonCodec(ObjectMapper mapper) {
/**
* Create a new Jackson codec for the given mapper.
* @param mapper the Jackson ObjectMapper to use
*/
protected AbstractJackson2Codec(ObjectMapper mapper) {
Assert.notNull(mapper, "ObjectMapper must not be null");
this.mapper = mapper;
}
/**
* Return the Jackson {@link JavaType} for the specified type and context class.
* <p>The default implementation returns {@code typeFactory.constructType(type, contextClass)},
......
......@@ -32,35 +32,35 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.codec.CodecException;
import org.springframework.core.codec.Decoder;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.util.Assert;
import org.springframework.util.MimeType;
/**
* Decode a byte stream into JSON and convert to Object's with Jackson.
* Decode a byte stream into JSON and convert to Object's with Jackson 2.6+.
*
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
* @since 5.0
* @see JacksonJsonEncoder
* @see Jackson2JsonEncoder
*/
public class JacksonJsonDecoder extends AbstractJacksonJsonCodec implements Decoder<Object> {
public class Jackson2JsonDecoder extends AbstractJackson2Codec implements Decoder<Object> {
private final JsonObjectDecoder fluxObjectDecoder = new JsonObjectDecoder(true);
private final JsonObjectDecoder monoObjectDecoder = new JsonObjectDecoder(false);
public JacksonJsonDecoder() {
public Jackson2JsonDecoder() {
super(Jackson2ObjectMapperBuilder.json().build());
}
public JacksonJsonDecoder(ObjectMapper mapper) {
public Jackson2JsonDecoder(ObjectMapper mapper) {
super(mapper);
}
@Override
public boolean canDecode(ResolvableType elementType, MimeType mimeType, Object... hints) {
if (mimeType == null) {
......@@ -96,23 +96,23 @@ public class JacksonJsonDecoder extends AbstractJacksonJsonCodec implements Deco
Assert.notNull(inputStream, "'inputStream' must not be null");
Assert.notNull(elementType, "'elementType' must not be null");
MethodParameter methodParameter = (elementType.getSource() instanceof MethodParameter ?
(MethodParameter)elementType.getSource() : null);
Class<?> contextClass = (methodParameter != null ? methodParameter.getContainingClass() : null);
MethodParameter methodParam = (elementType.getSource() instanceof MethodParameter ?
(MethodParameter) elementType.getSource() : null);
Class<?> contextClass = (methodParam != null ? methodParam.getContainingClass() : null);
JavaType javaType = getJavaType(elementType.getType(), contextClass);
ObjectReader reader;
if (methodParameter != null && methodParameter.getParameter().getAnnotation(JsonView.class) != null) {
JsonView annotation = methodParameter.getParameter().getAnnotation(JsonView.class);
Class<?>[] classes = annotation.value();
ObjectReader reader;
JsonView jsonView = (methodParam != null ? methodParam.getParameterAnnotation(JsonView.class) : null);
if (jsonView != null) {
Class<?>[] classes = jsonView.value();
if (classes.length != 1) {
throw new IllegalArgumentException(
"@JsonView only supported for response body advice with exactly 1 class argument: " + methodParameter);
throw new IllegalArgumentException("@JsonView only supported for response body advice " +
"with exactly 1 class argument: " + methodParam);
}
reader = mapper.readerWithView(classes[0]).forType(javaType);
reader = this.mapper.readerWithView(classes[0]).forType(javaType);
}
else {
reader = mapper.readerFor(javaType);
reader = this.mapper.readerFor(javaType);
}
return objectDecoder.decode(inputStream, elementType, mimeType, hints)
......@@ -122,8 +122,8 @@ public class JacksonJsonDecoder extends AbstractJacksonJsonCodec implements Deco
DataBufferUtils.release(dataBuffer);
return value;
}
catch (IOException e) {
return Flux.error(new CodecException("Error while reading the data", e));
catch (IOException ex) {
return Flux.error(new CodecException("Error while reading the data", ex));
}
});
}
......
......@@ -41,14 +41,15 @@ import org.springframework.util.Assert;
import org.springframework.util.MimeType;
/**
* Encode from an {@code Object} stream to a byte stream of JSON objects.
* Encode from an {@code Object} stream to a byte stream of JSON objects,
* using Jackson 2.6+.
*
* @author Sebastien Deleuze
* @author Arjen Poutsma
* @since 5.0
* @see JacksonJsonDecoder
* @see Jackson2JsonDecoder
*/
public class JacksonJsonEncoder extends AbstractJacksonJsonCodec implements Encoder<Object> {
public class Jackson2JsonEncoder extends AbstractJackson2Codec implements Encoder<Object> {
private static final ByteBuffer START_ARRAY_BUFFER = ByteBuffer.wrap(new byte[]{'['});
......@@ -57,14 +58,15 @@ public class JacksonJsonEncoder extends AbstractJacksonJsonCodec implements Enco
private static final ByteBuffer END_ARRAY_BUFFER = ByteBuffer.wrap(new byte[]{']'});
public JacksonJsonEncoder() {
public Jackson2JsonEncoder() {
super(Jackson2ObjectMapperBuilder.json().build());
}
public JacksonJsonEncoder(ObjectMapper mapper) {
public Jackson2JsonEncoder(ObjectMapper mapper) {
super(mapper);
}
@Override
public boolean canEncode(ResolvableType elementType, MimeType mimeType, Object... hints) {
if (mimeType == null) {
......@@ -105,38 +107,38 @@ public class JacksonJsonEncoder extends AbstractJacksonJsonCodec implements Enco
private DataBuffer encodeValue(Object value, DataBufferFactory bufferFactory, ResolvableType type) {
TypeFactory typeFactory = this.mapper.getTypeFactory();
JavaType javaType = typeFactory.constructType(type.getType());
MethodParameter returnType = (type.getSource() instanceof MethodParameter ?
(MethodParameter)type.getSource() : null);
MethodParameter returnType =
(type.getSource() instanceof MethodParameter ? (MethodParameter) type.getSource() : null);
if (type != null && value != null && type.isAssignableFrom(value.getClass())) {
if (type.isInstance(value)) {
javaType = getJavaType(type.getType(), null);
}
ObjectWriter writer;
if (returnType != null && returnType.getMethodAnnotation(JsonView.class) != null) {
JsonView annotation = returnType.getMethodAnnotation(JsonView.class);
Class<?>[] classes = annotation.value();
ObjectWriter writer;
JsonView jsonView = (returnType != null ? returnType.getMethodAnnotation(JsonView.class) : null);
if (jsonView != null) {
Class<?>[] classes = jsonView.value();
if (classes.length != 1) {
throw new IllegalArgumentException(
"@JsonView only supported for response body advice with exactly 1 class argument: " + returnType);
throw new IllegalArgumentException("@JsonView only supported for response body advice " +
"with exactly 1 class argument: " + returnType);
}
writer = this.mapper.writerWithView(classes[0]);
}
else {
writer = this.mapper.writer();
}
if (javaType != null && javaType.isContainerType()) {
writer = writer.forType(javaType);
}
DataBuffer buffer = bufferFactory.allocateBuffer();
OutputStream outputStream = buffer.asOutputStream();
try {
writer.writeValue(outputStream, value);
}
catch (IOException e) {
throw new CodecException("Error while writing the data", e);
catch (IOException ex) {
throw new CodecException("Error while writing the data", ex);
}
return buffer;
......
......@@ -31,7 +31,7 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.codec.AbstractDecoder;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.util.MimeType;
/**
......@@ -109,17 +109,17 @@ class JsonObjectDecoder extends AbstractDecoder<DataBuffer> {
Integer writerIndex;
@Override
public Publisher<? extends DataBuffer> apply(DataBuffer b) {
public Publisher<? extends DataBuffer> apply(DataBuffer buffer) {
List<DataBuffer> chunks = new ArrayList<>();
if (this.input == null) {
this.input = Unpooled.copiedBuffer(b.asByteBuffer());
DataBufferUtils.release(b);
this.input = Unpooled.copiedBuffer(buffer.asByteBuffer());
DataBufferUtils.release(buffer);
this.writerIndex = this.input.writerIndex();
}
else {
this.input = Unpooled.copiedBuffer(this.input,
Unpooled.copiedBuffer(b.asByteBuffer()));
DataBufferUtils.release(b);
Unpooled.copiedBuffer(buffer.asByteBuffer()));
DataBufferUtils.release(buffer);
this.writerIndex = this.input.writerIndex();
}
if (this.state == ST_CORRUPTED) {
......@@ -133,7 +133,7 @@ class JsonObjectDecoder extends AbstractDecoder<DataBuffer> {
return Flux.error(new IllegalStateException("object length exceeds " +
maxObjectLength + ": " + this.writerIndex + " bytes discarded"));
}
DataBufferFactory dataBufferFactory = b.factory();
DataBufferFactory dataBufferFactory = buffer.factory();
for (/* use current index */; this.index < this.writerIndex; this.index++) {
byte c = this.input.getByte(this.index);
if (this.state == ST_DECODING_NORMAL) {
......
......@@ -50,9 +50,9 @@ import org.springframework.util.xml.StaxUtils;
* @author Sebastien Deleuze
* @author Arjen Poutsma
* @since 5.0
* @see Jaxb2Encoder
* @see Jaxb2XmlEncoder
*/
public class Jaxb2Decoder extends AbstractDecoder<Object> {
public class Jaxb2XmlDecoder extends AbstractDecoder<Object> {
/**
* The default value for JAXB annotations.
......@@ -61,14 +61,15 @@ public class Jaxb2Decoder extends AbstractDecoder<Object> {
* @see XmlType#name()
* @see XmlType#namespace()
*/
private final static String JAXB_DEFAULT_ANNOTATION_VALUE = "##default";
private static final String JAXB_DEFAULT_ANNOTATION_VALUE = "##default";
private final XmlEventDecoder xmlEventDecoder = new XmlEventDecoder();
private final JaxbContextContainer jaxbContexts = new JaxbContextContainer();
public Jaxb2Decoder() {
public Jaxb2XmlDecoder() {
super(MimeTypeUtils.APPLICATION_XML, MimeTypeUtils.TEXT_XML);
}
......
......@@ -39,22 +39,24 @@ import org.springframework.util.MimeTypeUtils;
* @author Sebastien Deleuze
* @author Arjen Poutsma
* @since 5.0
* @see Jaxb2Decoder
* @see Jaxb2XmlDecoder
*/
public class Jaxb2Encoder extends AbstractSingleValueEncoder<Object> {
public class Jaxb2XmlEncoder extends AbstractSingleValueEncoder<Object> {
private final JaxbContextContainer jaxbContexts = new JaxbContextContainer();
public Jaxb2Encoder() {
public Jaxb2XmlEncoder() {
super(MimeTypeUtils.APPLICATION_XML, MimeTypeUtils.TEXT_XML);
}
@Override
public boolean canEncode(ResolvableType elementType, MimeType mimeType, Object... hints) {
if (super.canEncode(elementType, mimeType, hints)) {
Class<?> outputClass = elementType.getRawClass();
return outputClass.isAnnotationPresent(XmlRootElement.class) ||
outputClass.isAnnotationPresent(XmlType.class);
return (outputClass.isAnnotationPresent(XmlRootElement.class) ||
outputClass.isAnnotationPresent(XmlType.class));
}
else {
return false;
......@@ -80,7 +82,4 @@ public class Jaxb2Encoder extends AbstractSingleValueEncoder<Object> {
}
}
}
......@@ -38,7 +38,7 @@ import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.AbstractDecoder;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.util.ClassUtils;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
......@@ -65,30 +65,32 @@ import org.springframework.util.MimeTypeUtils;
* <li>{@link javax.xml.stream.events.EndElement} {@code root}</li>
* </ol>
*
* Note that this decoder is not registered by default, but used internally by other
* decoders who are.
* Note that this decoder is not registered by default but used internally
* by other decoders who are there by default.
*
* @author Arjen Poutsma
* @since 5.0
*/
public class XmlEventDecoder extends AbstractDecoder<XMLEvent> {
private static final boolean aaltoPresent = ClassUtils
.isPresent("com.fasterxml.aalto.AsyncXMLStreamReader",
XmlEventDecoder.class.getClassLoader());
private static final boolean aaltoPresent = ClassUtils.isPresent(
"com.fasterxml.aalto.AsyncXMLStreamReader", XmlEventDecoder.class.getClassLoader());
private static final XMLInputFactory inputFactory = XMLInputFactory.newFactory();
boolean useAalto = true;
public XmlEventDecoder() {
super(MimeTypeUtils.APPLICATION_XML, MimeTypeUtils.TEXT_XML);
}
@Override
@SuppressWarnings("unchecked")
public Flux<XMLEvent> decode(Publisher<DataBuffer> inputStream, ResolvableType elementType,
MimeType mimeType, Object... hints) {
Flux<DataBuffer> flux = Flux.from(inputStream);
if (useAalto && aaltoPresent) {
return flux.flatMap(new AaltoDataBufferToXmlEvent());
......@@ -112,11 +114,11 @@ public class XmlEventDecoder extends AbstractDecoder<XMLEvent> {
}
}
/*
* Separate static class to isolate Aalto dependency.
*/
private static class AaltoDataBufferToXmlEvent
implements Function<DataBuffer, Publisher<? extends XMLEvent>> {
private static class AaltoDataBufferToXmlEvent implements Function<DataBuffer, Publisher<? extends XMLEvent>> {
private static final AsyncXMLInputFactory inputFactory = new InputFactoryImpl();
......@@ -154,4 +156,5 @@ public class XmlEventDecoder extends AbstractDecoder<XMLEvent> {
}
}
}
}
......@@ -30,7 +30,7 @@ import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.util.Assert;
/**
......
......@@ -38,15 +38,15 @@ import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.ClientHttpRequest;
import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.http.codec.json.JacksonJsonDecoder;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2Decoder;
import org.springframework.http.codec.xml.Jaxb2Encoder;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.util.ClassUtils;
/**
......@@ -106,8 +106,8 @@ public final class WebClient {
* <ul>
* <li>{@link ByteBufferEncoder} / {@link ByteBufferDecoder}</li>
* <li>{@link CharSequenceEncoder} / {@link StringDecoder}</li>
* <li>{@link Jaxb2Encoder} / {@link Jaxb2Decoder}</li>
* <li>{@link JacksonJsonEncoder} / {@link JacksonJsonDecoder}</li>
* <li>{@link Jaxb2XmlEncoder} / {@link Jaxb2XmlDecoder}</li>
* <li>{@link Jackson2JsonEncoder} / {@link Jackson2JsonDecoder}</li>
* </ul>
*
* @param clientHttpConnector the {@code ClientHttpRequestFactory} to use
......@@ -126,10 +126,10 @@ public final class WebClient {
messageReaders.add(new DecoderHttpMessageReader<>(new StringDecoder(false)));
messageReaders.add(new DecoderHttpMessageReader<>(new ResourceDecoder()));
if (jaxb2Present) {
messageReaders.add(new DecoderHttpMessageReader<>(new Jaxb2Decoder()));
messageReaders.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder()));
}
if (jackson2Present) {
messageReaders.add(new DecoderHttpMessageReader<>(new JacksonJsonDecoder()));
messageReaders.add(new DecoderHttpMessageReader<>(new Jackson2JsonDecoder()));
}
}
......@@ -141,10 +141,10 @@ public final class WebClient {
messageWriters.add(new EncoderHttpMessageWriter<>(new CharSequenceEncoder()));
messageWriters.add(new ResourceHttpMessageWriter());
if (jaxb2Present) {
messageWriters.add(new EncoderHttpMessageWriter<>(new Jaxb2Encoder()));
messageWriters.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
}
if (jackson2Present) {
messageWriters.add(new EncoderHttpMessageWriter<>(new JacksonJsonEncoder()));
messageWriters.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()));
}
}
......
......@@ -28,10 +28,7 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType;
import org.springframework.http.codec.Pojo;
import org.springframework.http.codec.SseEvent;
import org.springframework.http.codec.SseEventHttpMessageWriter;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.server.reactive.MockServerHttpResponse;
import static org.junit.Assert.*;
......@@ -39,11 +36,11 @@ import static org.junit.Assert.*;
/**
* @author Sebastien Deleuze
*/
public class SseEventHttpMessageWriterTests
extends AbstractDataBufferAllocatingTestCase {
public class SseEventHttpMessageWriterTests extends AbstractDataBufferAllocatingTestCase {
private SseEventHttpMessageWriter converter = new SseEventHttpMessageWriter(
Collections.singletonList(new JacksonJsonEncoder()));
Collections.singletonList(new Jackson2JsonEncoder()));
@Test
public void nullMimeType() {
......
......@@ -21,7 +21,6 @@ import java.util.Arrays;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonView;
import static org.junit.Assert.assertNull;
import org.junit.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
......@@ -33,19 +32,19 @@ import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType;
import org.springframework.http.codec.Pojo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
/**
* Unit tests for {@link JacksonJsonDecoder}.
* Unit tests for {@link Jackson2JsonDecoder}.
*
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
*/
public class JacksonJsonDecoderTests extends AbstractDataBufferAllocatingTestCase {
public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCase {
@Test
public void canDecode() {
JacksonJsonDecoder decoder = new JacksonJsonDecoder();
Jackson2JsonDecoder decoder = new Jackson2JsonDecoder();
assertTrue(decoder.canDecode(null, MediaType.APPLICATION_JSON));
assertFalse(decoder.canDecode(null, MediaType.APPLICATION_XML));
......@@ -55,7 +54,7 @@ public class JacksonJsonDecoderTests extends AbstractDataBufferAllocatingTestCas
public void decodePojo() {
Flux<DataBuffer> source = Flux.just(stringBuffer("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}"));
ResolvableType elementType = ResolvableType.forClass(Pojo.class);
Flux<Object> flux = new JacksonJsonDecoder().decode(source, elementType, null);
Flux<Object> flux = new Jackson2JsonDecoder().decode(source, elementType, null);
TestSubscriber.subscribe(flux).assertNoError().assertComplete().
assertValues(new Pojo("foofoo", "barbar"));
......@@ -68,7 +67,7 @@ public class JacksonJsonDecoderTests extends AbstractDataBufferAllocatingTestCas
Method method = getClass().getDeclaredMethod("handle", List.class);
ResolvableType elementType = ResolvableType.forMethodParameter(method, 0);
Mono<Object> mono = new JacksonJsonDecoder().decodeToMono(source, elementType, null);
Mono<Object> mono = new Jackson2JsonDecoder().decodeToMono(source, elementType, null);
TestSubscriber.subscribe(mono).assertNoError().assertComplete().
assertValues(Arrays.asList(new Pojo("f1", "b1"), new Pojo("f2", "b2")));
......@@ -80,7 +79,7 @@ public class JacksonJsonDecoderTests extends AbstractDataBufferAllocatingTestCas
"[{\"bar\":\"b1\",\"foo\":\"f1\"},{\"bar\":\"b2\",\"foo\":\"f2\"}]"));
ResolvableType elementType = ResolvableType.forClass(Pojo.class);
Flux<Object> flux = new JacksonJsonDecoder().decode(source, elementType, null);
Flux<Object> flux = new Jackson2JsonDecoder().decode(source, elementType, null);
TestSubscriber.subscribe(flux).assertNoError().assertComplete().
assertValues(new Pojo("f1", "b1"), new Pojo("f2", "b2"));
......@@ -92,7 +91,7 @@ public class JacksonJsonDecoderTests extends AbstractDataBufferAllocatingTestCas
stringBuffer("{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}"));
ResolvableType elementType = ResolvableType
.forMethodParameter(JacksonController.class.getMethod("foo", JacksonViewBean.class), 0);
Flux<JacksonViewBean> flux = new JacksonJsonDecoder()
Flux<JacksonViewBean> flux = new Jackson2JsonDecoder()
.decode(source, elementType, null).cast(JacksonViewBean.class);
TestSubscriber
......@@ -106,13 +105,16 @@ public class JacksonJsonDecoderTests extends AbstractDataBufferAllocatingTestCas
});
}
void handle(List<Pojo> list) {
}
private interface MyJacksonView1 {}
private interface MyJacksonView2 {}
@SuppressWarnings("unused")
private static class JacksonViewBean {
......@@ -149,6 +151,7 @@ public class JacksonJsonDecoderTests extends AbstractDataBufferAllocatingTestCas
}
}
private static class JacksonController {
public JacksonViewBean foo(@JsonView(MyJacksonView1.class) JacksonViewBean bean) {
......
......@@ -19,7 +19,6 @@ package org.springframework.http.codec.json;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.annotation.JsonView;
import org.junit.Before;
import org.junit.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
......@@ -31,21 +30,14 @@ import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType;
import org.springframework.http.codec.Pojo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
/**
* @author Sebastien Deleuze
*/
public class JacksonJsonEncoderTests extends AbstractDataBufferAllocatingTestCase {
public class Jackson2JsonEncoderTests extends AbstractDataBufferAllocatingTestCase {
private JacksonJsonEncoder encoder;
@Before
public void createEncoder() {
this.encoder = new JacksonJsonEncoder();
}
private final Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
@Test
......@@ -123,10 +115,12 @@ public class JacksonJsonEncoderTests extends AbstractDataBufferAllocatingTestCas
private static class Bar extends ParentClass {
}
private interface MyJacksonView1 {}
private interface MyJacksonView2 {}
@SuppressWarnings("unused")
private static class JacksonViewBean {
......@@ -163,6 +157,7 @@ public class JacksonJsonEncoderTests extends AbstractDataBufferAllocatingTestCas
}
}
private static class JacksonController {
@JsonView(MyJacksonView1.class)
......
......@@ -30,7 +30,6 @@ import org.springframework.core.io.buffer.DataBuffer;
*/
public class JsonObjectDecoderTests extends AbstractDataBufferAllocatingTestCase {
@Test
public void decodeSingleChunkToJsonObject() {
JsonObjectDecoder decoder = new JsonObjectDecoder();
......@@ -82,6 +81,7 @@ public class JsonObjectDecoderTests extends AbstractDataBufferAllocatingTestCase
"{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}");
}
private static String toString(DataBuffer buffer) {
byte[] b = new byte[buffer.readableByteCount()];
buffer.read(b);
......
......@@ -36,14 +36,12 @@ import org.springframework.http.codec.xml.jaxb.XmlType;
import org.springframework.http.codec.xml.jaxb.XmlTypeWithName;
import org.springframework.http.codec.xml.jaxb.XmlTypeWithNameAndNamespace;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
/**
* @author Sebastien Deleuze
*/
public class Jaxb2DecoderTests extends AbstractDataBufferAllocatingTestCase {
public class Jaxb2XmlDecoderTests extends AbstractDataBufferAllocatingTestCase {
private static final String POJO_ROOT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<pojo>" +
......@@ -64,7 +62,8 @@ public class Jaxb2DecoderTests extends AbstractDataBufferAllocatingTestCase {
"</pojo>" +
"<root/>";
private final Jaxb2Decoder decoder = new Jaxb2Decoder();
private final Jaxb2XmlDecoder decoder = new Jaxb2XmlDecoder();
private final XmlEventDecoder xmlEventDecoder = new XmlEventDecoder();
......
......@@ -18,7 +18,6 @@ package org.springframework.http.codec.xml;
import java.nio.charset.StandardCharsets;
import org.junit.Before;
import org.junit.Test;
import reactor.core.publisher.Flux;
import reactor.test.TestSubscriber;
......@@ -26,28 +25,22 @@ import reactor.test.TestSubscriber;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
import org.springframework.core.io.buffer.support.DataBufferUtils;
import org.springframework.http.MediaType;
import org.springframework.http.codec.Pojo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.xmlunit.matchers.CompareMatcher.isSimilarTo;
import static org.junit.Assert.*;
import static org.xmlunit.matchers.CompareMatcher.*;
/**
* @author Sebastien Deleuze
* @author Arjen Poutsma
*/
public class Jaxb2EncoderTests extends AbstractDataBufferAllocatingTestCase {
public class Jaxb2XmlEncoderTests extends AbstractDataBufferAllocatingTestCase {
private Jaxb2Encoder encoder;
private final Jaxb2XmlEncoder encoder = new Jaxb2XmlEncoder();
@Before
public void createEncoder() {
this.encoder = new Jaxb2Encoder();
}
@Test
public void canEncode() {
......@@ -59,7 +52,7 @@ public class Jaxb2EncoderTests extends AbstractDataBufferAllocatingTestCase {
MediaType.APPLICATION_JSON));
assertTrue(this.encoder.canEncode(
ResolvableType.forClass(Jaxb2DecoderTests.TypePojo.class),
ResolvableType.forClass(Jaxb2XmlDecoderTests.TypePojo.class),
MediaType.APPLICATION_XML));
assertFalse(this.encoder.canEncode(ResolvableType.forClass(getClass()),
......
/*
* Copyright 2002-2016 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
*
* http://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.web.client.reactive;
import java.io.UnsupportedEncodingException;
......@@ -19,18 +35,14 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.http.codec.json.JacksonJsonDecoder;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.BDDMockito.*;
import static org.mockito.Mockito.mock;
/**
......@@ -40,7 +52,7 @@ import static org.mockito.Mockito.mock;
*/
public class ResponseExtractorsTests {
private HttpHeaders headers = new HttpHeaders();
private HttpHeaders headers;
private ClientHttpResponse response;
......@@ -50,6 +62,7 @@ public class ResponseExtractorsTests {
private ResponseErrorHandler errorHandler;
@Before
public void setup() throws Exception {
this.headers = new HttpHeaders();
......@@ -57,13 +70,14 @@ public class ResponseExtractorsTests {
given(this.response.getHeaders()).willReturn(headers);
this.messageReaders = Arrays.asList(
new DecoderHttpMessageReader<>(new StringDecoder()),
new DecoderHttpMessageReader<>(new JacksonJsonDecoder()));
new DecoderHttpMessageReader<>(new Jackson2JsonDecoder()));
this.webClientConfig = mock(WebClientConfig.class);
this.errorHandler = mock(ResponseErrorHandler.class);
given(this.webClientConfig.getMessageReaders()).willReturn(this.messageReaders);
given(this.webClientConfig.getResponseErrorHandler()).willReturn(this.errorHandler);
}
@Test
public void shouldExtractResponseEntityMono() throws Exception {
this.headers.setContentType(MediaType.TEXT_PLAIN);
......@@ -189,7 +203,6 @@ public class ResponseExtractorsTests {
private Flux<DataBuffer> createFluxBody(String... items) throws Exception {
DefaultDataBufferFactory factory = new DefaultDataBufferFactory();
return Flux.just(items)
.map(item -> {
......@@ -204,7 +217,9 @@ public class ResponseExtractorsTests {
});
}
protected class SomePojo {
public String foo;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册