001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.core.codec; 018 019import java.util.Map; 020 021import org.reactivestreams.Publisher; 022import reactor.core.publisher.Flux; 023import reactor.core.publisher.Mono; 024 025import org.springframework.core.ResolvableType; 026import org.springframework.core.io.buffer.DataBuffer; 027import org.springframework.core.io.buffer.DataBufferUtils; 028import org.springframework.lang.Nullable; 029import org.springframework.util.MimeType; 030 031/** 032 * Abstract base class for {@code Decoder} implementations that can decode 033 * a {@code DataBuffer} directly to the target element type. 034 * 035 * <p>Sub-classes must implement {@link #decodeDataBuffer} to provide a way to 036 * transform a {@code DataBuffer} to the target data type. The default 037 * {@link #decode} implementation transforms each individual data buffer while 038 * {@link #decodeToMono} applies "reduce" and transforms the aggregated buffer. 039 * 040 * <p>Sub-classes can override {@link #decode} in order to split the input stream 041 * along different boundaries (e.g. on new line characters for {@code String}) 042 * or always reduce to a single data buffer (e.g. {@code Resource}). 043 * 044 * @author Rossen Stoyanchev 045 * @since 5.0 046 * @param <T> the element type 047 */ 048@SuppressWarnings("deprecation") 049public abstract class AbstractDataBufferDecoder<T> extends AbstractDecoder<T> { 050 051 private int maxInMemorySize = 256 * 1024; 052 053 054 protected AbstractDataBufferDecoder(MimeType... supportedMimeTypes) { 055 super(supportedMimeTypes); 056 } 057 058 059 /** 060 * Configure a limit on the number of bytes that can be buffered whenever 061 * the input stream needs to be aggregated. This can be a result of 062 * decoding to a single {@code DataBuffer}, 063 * {@link java.nio.ByteBuffer ByteBuffer}, {@code byte[]}, 064 * {@link org.springframework.core.io.Resource Resource}, {@code String}, etc. 065 * It can also occur when splitting the input stream, e.g. delimited text, 066 * in which case the limit applies to data buffered between delimiters. 067 * <p>By default this is set to 256K. 068 * @param byteCount the max number of bytes to buffer, or -1 for unlimited 069 * @since 5.1.11 070 */ 071 public void setMaxInMemorySize(int byteCount) { 072 this.maxInMemorySize = byteCount; 073 } 074 075 /** 076 * Return the {@link #setMaxInMemorySize configured} byte count limit. 077 * @since 5.1.11 078 */ 079 public int getMaxInMemorySize() { 080 return this.maxInMemorySize; 081 } 082 083 084 @Override 085 public Flux<T> decode(Publisher<DataBuffer> input, ResolvableType elementType, 086 @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) { 087 088 return Flux.from(input).map(buffer -> decodeDataBuffer(buffer, elementType, mimeType, hints)); 089 } 090 091 @Override 092 public Mono<T> decodeToMono(Publisher<DataBuffer> input, ResolvableType elementType, 093 @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) { 094 095 return DataBufferUtils.join(input, this.maxInMemorySize) 096 .map(buffer -> decodeDataBuffer(buffer, elementType, mimeType, hints)); 097 } 098 099 /** 100 * How to decode a {@code DataBuffer} to the target element type. 101 * @deprecated as of 5.2, please implement 102 * {@link #decode(DataBuffer, ResolvableType, MimeType, Map)} instead 103 */ 104 @Deprecated 105 @Nullable 106 protected T decodeDataBuffer(DataBuffer buffer, ResolvableType elementType, 107 @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) { 108 109 return decode(buffer, elementType, mimeType, hints); 110 } 111 112}