Introduce AbstractSingleValueEncoder
This commit introduces the AbstractSingleValueEncoder, an abstract base class for encoders that only handle a single value.
This commit is contained in:
parent
9ed4bff4a9
commit
ad0a4e0cf8
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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.
|
||||
|
|
@ -31,8 +31,7 @@ public abstract class AbstractDecoder<T> implements Decoder<T> {
|
|||
|
||||
private List<MimeType> supportedMimeTypes = Collections.emptyList();
|
||||
|
||||
|
||||
public AbstractDecoder(MimeType... supportedMimeTypes) {
|
||||
protected AbstractDecoder(MimeType... supportedMimeTypes) {
|
||||
this.supportedMimeTypes = Arrays.asList(supportedMimeTypes);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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.
|
||||
|
|
@ -31,8 +31,7 @@ public abstract class AbstractEncoder<T> implements Encoder<T> {
|
|||
|
||||
private List<MimeType> supportedMimeTypes = Collections.emptyList();
|
||||
|
||||
|
||||
public AbstractEncoder(MimeType... supportedMimeTypes) {
|
||||
protected AbstractEncoder(MimeType... supportedMimeTypes) {
|
||||
this.supportedMimeTypes = Arrays.asList(supportedMimeTypes);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.core.codec.support;
|
||||
|
||||
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.DataBufferAllocator;
|
||||
import org.springframework.util.MimeType;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link org.springframework.core.codec.Encoder} classes that
|
||||
* can only deal with a single value.
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public abstract class AbstractSingleValueEncoder<T> extends AbstractEncoder<T> {
|
||||
|
||||
public AbstractSingleValueEncoder(MimeType... supportedMimeTypes) {
|
||||
super(supportedMimeTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Flux<DataBuffer> encode(Publisher<? extends T> inputStream,
|
||||
DataBufferAllocator allocator, ResolvableType type, MimeType mimeType,
|
||||
Object... hints) {
|
||||
return Flux.from(inputStream).
|
||||
take(1).
|
||||
concatMap(t -> {
|
||||
try {
|
||||
return encode(t, allocator, type, mimeType);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return Flux.error(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes {@code T} to an output {@link DataBuffer} stream.
|
||||
* @param t the value to process
|
||||
* @param allocator a buffer allocator used to create the output
|
||||
* @param type the stream element type to process
|
||||
* @param mimeType the mime type to process
|
||||
* @param hints Additional information about how to do decode, optional
|
||||
* @return the output stream
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
protected abstract Flux<DataBuffer> encode(T t, DataBufferAllocator allocator,
|
||||
ResolvableType type, MimeType mimeType, Object... hints) throws Exception;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -19,16 +19,13 @@ package org.springframework.core.codec.support;
|
|||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.MarshalException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.CodecException;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferAllocator;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
|
@ -42,7 +39,7 @@ import org.springframework.util.MimeTypeUtils;
|
|||
* @author Arjen Poutsma
|
||||
* @see Jaxb2Decoder
|
||||
*/
|
||||
public class Jaxb2Encoder extends AbstractEncoder<Object> {
|
||||
public class Jaxb2Encoder extends AbstractSingleValueEncoder<Object> {
|
||||
|
||||
private final JaxbContextContainer jaxbContexts = new JaxbContextContainer();
|
||||
|
||||
|
|
@ -64,29 +61,21 @@ public class Jaxb2Encoder extends AbstractEncoder<Object> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Flux<DataBuffer> encode(Publisher<?> inputStream,
|
||||
DataBufferAllocator allocator, ResolvableType type, MimeType mimeType,
|
||||
Object... hints) {
|
||||
|
||||
return Flux.from(inputStream).
|
||||
take(1). // only map 1 value to ensure valid XML output
|
||||
map(value -> {
|
||||
try {
|
||||
DataBuffer buffer = allocator.allocateBuffer(1024);
|
||||
OutputStream outputStream = buffer.asOutputStream();
|
||||
Class<?> clazz = ClassUtils.getUserClass(value);
|
||||
Marshaller marshaller = jaxbContexts.createMarshaller(clazz);
|
||||
marshaller.setProperty(Marshaller.JAXB_ENCODING, StandardCharsets.UTF_8.name());
|
||||
marshaller.marshal(value, outputStream);
|
||||
return buffer;
|
||||
}
|
||||
catch (MarshalException ex) {
|
||||
throw new CodecException("Could not marshal [" + value + "]: " + ex.getMessage(), ex);
|
||||
}
|
||||
catch (JAXBException ex) {
|
||||
throw new CodecException("Could not instantiate JAXBContext: " + ex.getMessage(), ex);
|
||||
}
|
||||
});
|
||||
protected Flux<DataBuffer> encode(Object value, DataBufferAllocator allocator,
|
||||
ResolvableType type, MimeType mimeType, Object... hints) {
|
||||
try {
|
||||
DataBuffer buffer = allocator.allocateBuffer(1024);
|
||||
OutputStream outputStream = buffer.asOutputStream();
|
||||
Class<?> clazz = ClassUtils.getUserClass(value);
|
||||
Marshaller marshaller = jaxbContexts.createMarshaller(clazz);
|
||||
marshaller
|
||||
.setProperty(Marshaller.JAXB_ENCODING, StandardCharsets.UTF_8.name());
|
||||
marshaller.marshal(value, outputStream);
|
||||
return Flux.just(buffer);
|
||||
}
|
||||
catch (JAXBException ex) {
|
||||
return Flux.error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,7 @@ package org.springframework.core.codec.support;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
|
@ -37,7 +35,7 @@ import org.springframework.util.StreamUtils;
|
|||
* An encoder for {@link Resource}s.
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class ResourceEncoder extends AbstractEncoder<Resource> {
|
||||
public class ResourceEncoder extends AbstractSingleValueEncoder<Resource> {
|
||||
|
||||
public static final int DEFAULT_BUFFER_SIZE = StreamUtils.BUFFER_SIZE;
|
||||
|
||||
|
|
@ -61,18 +59,10 @@ public class ResourceEncoder extends AbstractEncoder<Resource> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Flux<DataBuffer> encode(Publisher<? extends Resource> inputStream,
|
||||
DataBufferAllocator allocator, ResolvableType type, MimeType mimeType,
|
||||
Object... hints) {
|
||||
return Flux.from(inputStream).
|
||||
concatMap(resource -> {
|
||||
try {
|
||||
InputStream is = resource.getInputStream();
|
||||
return DataBufferUtils.read(is, allocator, this.bufferSize);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return Mono.error(ex);
|
||||
}
|
||||
});
|
||||
protected Flux<DataBuffer> encode(Resource resource, DataBufferAllocator allocator,
|
||||
ResolvableType type, MimeType mimeType, Object... hints) throws IOException {
|
||||
InputStream is = resource.getInputStream();
|
||||
return DataBufferUtils.read(is, allocator, bufferSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue