Nullability refinements and related polishing
This commit is contained in:
		
							parent
							
								
									c5b3848357
								
							
						
					
					
						commit
						cdf51c3d51
					
				| 
						 | 
				
			
			@ -211,9 +211,8 @@ final class ConfigurationClass {
 | 
			
		|||
 | 
			
		||||
	public void validate(ProblemReporter problemReporter) {
 | 
			
		||||
		// A configuration class may not be final (CGLIB limitation) unless it declares proxyBeanMethods=false
 | 
			
		||||
		String annotationName = Configuration.class.getName();
 | 
			
		||||
		if (this.metadata.isAnnotated(annotationName) &&
 | 
			
		||||
				(Boolean) this.metadata.getAnnotationAttributes(annotationName).get("proxyBeanMethods")) {
 | 
			
		||||
		Map<String, Object> attributes = this.metadata.getAnnotationAttributes(Configuration.class.getName());
 | 
			
		||||
		if (attributes != null && (Boolean) attributes.get("proxyBeanMethods")) {
 | 
			
		||||
			if (this.metadata.isFinal()) {
 | 
			
		||||
				problemReporter.error(new FinalConfigurationProblem());
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,7 +49,7 @@ import org.springframework.util.MimeType;
 | 
			
		|||
 * Base class for a return value handler that encodes return values to
 | 
			
		||||
 * {@code Flux<DataBuffer>} through the configured {@link Encoder}s.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>Sub-classes must implement the abstract method
 | 
			
		||||
 * <p>Subclasses must implement the abstract method
 | 
			
		||||
 * {@link #handleEncodedContent} to handle the resulting encoded content.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>This handler should be ordered last since its {@link #supportsReturnType}
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +69,6 @@ public abstract class AbstractEncoderMethodReturnValueHandler implements Handler
 | 
			
		|||
 | 
			
		||||
	protected final Log logger = LogFactory.getLog(getClass());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	private final List<Encoder<?>> encoders;
 | 
			
		||||
 | 
			
		||||
	private final ReactiveAdapterRegistry adapterRegistry;
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +117,6 @@ public abstract class AbstractEncoderMethodReturnValueHandler implements Handler
 | 
			
		|||
				.getOrDefault(HandlerMethodReturnValueHandler.DATA_BUFFER_FACTORY_HEADER, this.defaultBufferFactory);
 | 
			
		||||
 | 
			
		||||
		MimeType mimeType = (MimeType) message.getHeaders().get(MessageHeaders.CONTENT_TYPE);
 | 
			
		||||
 | 
			
		||||
		Flux<DataBuffer> encodedContent = encodeContent(
 | 
			
		||||
				returnValue, returnType, bufferFactory, mimeType, Collections.emptyMap());
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -147,8 +145,8 @@ public abstract class AbstractEncoderMethodReturnValueHandler implements Handler
 | 
			
		|||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			publisher = Mono.justOrEmpty(content);
 | 
			
		||||
			elementType = returnValueType.toClass() == Object.class && content != null ?
 | 
			
		||||
					ResolvableType.forInstance(content) : returnValueType;
 | 
			
		||||
			elementType = (returnValueType.toClass() == Object.class && content != null ?
 | 
			
		||||
					ResolvableType.forInstance(content) : returnValueType);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (elementType.resolve() == void.class || elementType.resolve() == Void.class) {
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +154,6 @@ public abstract class AbstractEncoderMethodReturnValueHandler implements Handler
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		Encoder<?> encoder = getEncoder(elementType, mimeType);
 | 
			
		||||
 | 
			
		||||
		return Flux.from((Publisher) publisher).map(value ->
 | 
			
		||||
				encodeValue(value, elementType, encoder, bufferFactory, mimeType, hints));
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -201,9 +198,8 @@ public abstract class AbstractEncoderMethodReturnValueHandler implements Handler
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Sub-classes implement this method to handle encoded values in some way
 | 
			
		||||
	 * Subclasses implement this method to handle encoded values in some way
 | 
			
		||||
	 * such as creating and sending messages.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param encodedContent the encoded content; each {@code DataBuffer}
 | 
			
		||||
	 * represents the fully-aggregated, encoded content for one value
 | 
			
		||||
	 * (i.e. payload) returned from the HandlerMethod.
 | 
			
		||||
| 
						 | 
				
			
			@ -229,9 +225,12 @@ public abstract class AbstractEncoderMethodReturnValueHandler implements Handler
 | 
			
		|||
	 */
 | 
			
		||||
	private static class KotlinDelegate {
 | 
			
		||||
 | 
			
		||||
		static private boolean isSuspend(Method method) {
 | 
			
		||||
		static private boolean isSuspend(@Nullable Method method) {
 | 
			
		||||
			if (method == null) {
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
			KFunction<?> function = ReflectJvmMapping.getKotlinFunction(method);
 | 
			
		||||
			return function != null && function.isSuspend();
 | 
			
		||||
			return (function != null && function.isSuspend());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,7 @@ import org.springframework.http.ReactiveHttpInputMessage;
 | 
			
		|||
import org.springframework.http.codec.HttpMessageReader;
 | 
			
		||||
import org.springframework.http.codec.LoggingCodecSupport;
 | 
			
		||||
import org.springframework.lang.Nullable;
 | 
			
		||||
import org.springframework.util.Assert;
 | 
			
		||||
import org.springframework.util.StringUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -57,8 +58,7 @@ import org.springframework.util.StringUtils;
 | 
			
		|||
 * @since 5.2
 | 
			
		||||
 * @see MultipartHttpMessageReader
 | 
			
		||||
 */
 | 
			
		||||
public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		||||
		implements HttpMessageReader<Part> {
 | 
			
		||||
public class DefaultMultipartMessageReader extends LoggingCodecSupport implements HttpMessageReader<Part> {
 | 
			
		||||
 | 
			
		||||
	private static final byte CR = '\r';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -74,8 +74,7 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
 | 
			
		||||
	private static final String HEADER_SEPARATOR = "\\r\\n";
 | 
			
		||||
 | 
			
		||||
	private static final DataBufferUtils.Matcher HEADER_MATCHER =
 | 
			
		||||
			DataBufferUtils.matcher(HEADER_BODY_SEPARATOR);
 | 
			
		||||
	private static final DataBufferUtils.Matcher HEADER_MATCHER = DataBufferUtils.matcher(HEADER_BODY_SEPARATOR);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
| 
						 | 
				
			
			@ -85,14 +84,12 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
 | 
			
		||||
	@Override
 | 
			
		||||
	public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType) {
 | 
			
		||||
		return Part.class.equals(elementType.toClass()) &&
 | 
			
		||||
				(mediaType == null || MediaType.MULTIPART_FORM_DATA.isCompatibleWith(mediaType));
 | 
			
		||||
		return (Part.class.equals(elementType.toClass()) &&
 | 
			
		||||
				(mediaType == null || MediaType.MULTIPART_FORM_DATA.isCompatibleWith(mediaType)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Flux<Part> read(ResolvableType elementType, ReactiveHttpInputMessage message,
 | 
			
		||||
			Map<String, Object> hints) {
 | 
			
		||||
 | 
			
		||||
	public Flux<Part> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) {
 | 
			
		||||
		byte[] boundary = boundary(message);
 | 
			
		||||
		if (boundary == null) {
 | 
			
		||||
			return Flux.error(new CodecException("No multipart boundary found in Content-Type: \"" +
 | 
			
		||||
| 
						 | 
				
			
			@ -126,12 +123,9 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
	 * all data until then. Note that the first boundary of a multipart message does not contain
 | 
			
		||||
	 * the initial \r\n, hence the need for a special boundary matcher.
 | 
			
		||||
	 */
 | 
			
		||||
	private static Flux<DataBuffer> skipUntilFirstBoundary(Flux<DataBuffer> dataBuffers,
 | 
			
		||||
			byte[] boundary) {
 | 
			
		||||
 | 
			
		||||
	private static Flux<DataBuffer> skipUntilFirstBoundary(Flux<DataBuffer> dataBuffers, byte[] boundary) {
 | 
			
		||||
		byte[] needle = concat(FIRST_BOUNDARY_PREFIX, boundary);
 | 
			
		||||
		DataBufferUtils.Matcher matcher = DataBufferUtils.matcher(needle);
 | 
			
		||||
 | 
			
		||||
		AtomicBoolean found = new AtomicBoolean();
 | 
			
		||||
 | 
			
		||||
		return dataBuffers.concatMap(dataBuffer -> {
 | 
			
		||||
| 
						 | 
				
			
			@ -152,7 +146,6 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
					return Mono.empty();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -163,8 +156,7 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
	private static boolean notLastBoundary(DataBuffer dataBuffer) {
 | 
			
		||||
		if (dataBuffer.readableByteCount() >= 2) {
 | 
			
		||||
			int readPosition = dataBuffer.readPosition();
 | 
			
		||||
			if ((dataBuffer.getByte(readPosition) == HYPHEN) &&
 | 
			
		||||
					(dataBuffer.getByte(readPosition + 1) == HYPHEN)) {
 | 
			
		||||
			if (dataBuffer.getByte(readPosition) == HYPHEN && dataBuffer.getByte(readPosition + 1) == HYPHEN) {
 | 
			
		||||
				DataBufferUtils.release(dataBuffer);
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -180,8 +172,7 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
	private static Part toPart(DataBuffer dataBuffer) {
 | 
			
		||||
		int readPosition = dataBuffer.readPosition();
 | 
			
		||||
		if (dataBuffer.readableByteCount() >= 2) {
 | 
			
		||||
			if ( (dataBuffer.getByte(readPosition) == CR) &&
 | 
			
		||||
				(dataBuffer.getByte(readPosition + 1) == LF)) {
 | 
			
		||||
			if (dataBuffer.getByte(readPosition) == CR && dataBuffer.getByte(readPosition + 1) == LF) {
 | 
			
		||||
				dataBuffer.readPosition(readPosition + 2);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -191,8 +182,7 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
		DataBuffer body;
 | 
			
		||||
		if (endIdx > 0) {
 | 
			
		||||
			readPosition = dataBuffer.readPosition();
 | 
			
		||||
			int headersLength =
 | 
			
		||||
					endIdx + 1 - (readPosition + HEADER_BODY_SEPARATOR.length);
 | 
			
		||||
			int headersLength = endIdx + 1 - (readPosition + HEADER_BODY_SEPARATOR.length);
 | 
			
		||||
			DataBuffer headersBuffer = dataBuffer.retainedSlice(readPosition, headersLength);
 | 
			
		||||
			int bodyLength = dataBuffer.writePosition() - (1 + endIdx);
 | 
			
		||||
			body = dataBuffer.retainedSlice(endIdx + 1, bodyLength);
 | 
			
		||||
| 
						 | 
				
			
			@ -275,7 +265,6 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
 | 
			
		||||
		protected final DataBuffer body;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		public DefaultPart(HttpHeaders headers, DataBuffer body) {
 | 
			
		||||
			this.headers = headers;
 | 
			
		||||
			this.body = body;
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +272,9 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String name() {
 | 
			
		||||
			return headers().getContentDisposition().getName();
 | 
			
		||||
			String name = headers().getContentDisposition().getName();
 | 
			
		||||
			Assert.state(name != null, "No name available");
 | 
			
		||||
			return name;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
| 
						 | 
				
			
			@ -295,7 +286,6 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
		public Flux<DataBuffer> content() {
 | 
			
		||||
			return Flux.just(this.body);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -342,14 +332,15 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String filename() {
 | 
			
		||||
			return headers().getContentDisposition().getFilename();
 | 
			
		||||
			String filename = headers().getContentDisposition().getFilename();
 | 
			
		||||
			Assert.state(filename != null, "No filename available");
 | 
			
		||||
			return filename;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Mono<Void> transferTo(Path dest) {
 | 
			
		||||
			return Mono.using(() -> AsynchronousFileChannel.open(dest, StandardOpenOption.WRITE),
 | 
			
		||||
					this::writeBody,
 | 
			
		||||
					this::close);
 | 
			
		||||
					this::writeBody, this::close);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private Mono<Void> writeBody(AsynchronousFileChannel channel) {
 | 
			
		||||
| 
						 | 
				
			
			@ -366,4 +357,5 @@ public class DefaultMultipartMessageReader extends LoggingCodecSupport
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue