Merge branch '6.1.x'

This commit is contained in:
Juergen Hoeller 2024-03-18 16:04:26 +01:00
commit 6df27644eb
16 changed files with 109 additions and 101 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -98,7 +98,9 @@ public final class ReactiveTypeDescriptor {
*/
public Object getEmptyValue() {
Assert.state(this.emptySupplier != null, "Empty values not supported");
return this.emptySupplier.get();
Object emptyValue = this.emptySupplier.get();
Assert.notNull(emptyValue, "Invalid null return value from emptySupplier");
return emptyValue;
}
/**

View File

@ -1170,22 +1170,21 @@ public class ResolvableType implements Serializable {
* @return a {@code ResolvableType} for the specific class and generics
* @see #forClassWithGenerics(Class, Class...)
*/
public static ResolvableType forClassWithGenerics(Class<?> clazz, ResolvableType... generics) {
public static ResolvableType forClassWithGenerics(Class<?> clazz, @Nullable ResolvableType... generics) {
Assert.notNull(clazz, "Class must not be null");
Assert.notNull(generics, "Generics array must not be null");
TypeVariable<?>[] variables = clazz.getTypeParameters();
Assert.isTrue(variables.length == generics.length,
() -> "Mismatched number of generics specified for " + clazz.toGenericString());
Type[] arguments = new Type[generics.length];
for (int i = 0; i < generics.length; i++) {
ResolvableType generic = generics[i];
if (generics != null) {
Assert.isTrue(variables.length == generics.length,
() -> "Mismatched number of generics specified for " + clazz.toGenericString());
}
Type[] arguments = new Type[variables.length];
for (int i = 0; i < variables.length; i++) {
ResolvableType generic = (generics != null ? generics[i] : null);
Type argument = (generic != null ? generic.getType() : null);
arguments[i] = (argument != null && !(argument instanceof TypeVariable) ? argument : variables[i]);
}
ParameterizedType syntheticType = new SyntheticParameterizedType(clazz, arguments);
return forType(syntheticType, new TypeVariablesVariableResolver(variables, generics));
return forType(new SyntheticParameterizedType(clazz, arguments),
(generics != null ? new TypeVariablesVariableResolver(variables, generics) : null));
}
/**
@ -1440,7 +1439,7 @@ public class ResolvableType implements Serializable {
*/
public static ResolvableType forArrayComponent(ResolvableType componentType) {
Assert.notNull(componentType, "Component type must not be null");
Class<?> arrayType = componentType.resolve().arrayType();
Class<?> arrayType = componentType.toClass().arrayType();
return new ResolvableType(arrayType, componentType, null, null);
}

View File

@ -278,6 +278,7 @@ public class AnnotatedMethod {
}
@Override
@Nullable
public <T extends Annotation> T getMethodAnnotation(Class<T> annotationType) {
return AnnotatedMethod.this.getMethodAnnotation(annotationType);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -114,19 +114,6 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
this(annotationType, false);
}
/**
* Create a new, empty {@link AnnotationAttributes} instance for the
* specified {@code annotationType}.
* @param annotationType the annotation type name represented by this
* {@code AnnotationAttributes} instance; never {@code null}
* @param classLoader the ClassLoader to try to load the annotation type on,
* or {@code null} to just store the annotation type name
* @since 4.3.2
*/
public AnnotationAttributes(String annotationType, @Nullable ClassLoader classLoader) {
this(getAnnotationType(annotationType, classLoader), false);
}
/**
* Create a possibly already validated new, empty
* {@link AnnotationAttributes} instance for the specified
@ -143,6 +130,21 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
this.validated = validated;
}
/**
* Create a new, empty {@link AnnotationAttributes} instance for the
* specified {@code annotationType}.
* @param annotationType the annotation type name represented by this
* {@code AnnotationAttributes} instance; never {@code null}
* @param classLoader the ClassLoader to try to load the annotation type on,
* or {@code null} to just store the annotation type name
* @since 4.3.2
*/
public AnnotationAttributes(String annotationType, @Nullable ClassLoader classLoader) {
Assert.notNull(annotationType, "'annotationType' must not be null");
this.annotationType = getAnnotationType(annotationType, classLoader);
this.displayName = annotationType;
this.validated = false;
}
@SuppressWarnings("unchecked")
@Nullable
@ -349,39 +351,29 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
private <T> T getRequiredAttribute(String attributeName, Class<T> expectedType) {
Assert.hasText(attributeName, "'attributeName' must not be null or empty");
Object value = get(attributeName);
assertAttributePresence(attributeName, value);
assertNotException(attributeName, value);
if (value == null) {
throw new IllegalArgumentException(String.format(
"Attribute '%s' not found in attributes for annotation [%s]",
attributeName, this.displayName));
}
if (value instanceof Throwable throwable) {
throw new IllegalArgumentException(String.format(
"Attribute '%s' for annotation [%s] was not resolvable due to exception [%s]",
attributeName, this.displayName, value), throwable);
}
if (!expectedType.isInstance(value) && expectedType.isArray() &&
expectedType.componentType().isInstance(value)) {
Object array = Array.newInstance(expectedType.componentType(), 1);
Array.set(array, 0, value);
value = array;
}
assertAttributeType(attributeName, value, expectedType);
return (T) value;
}
private void assertAttributePresence(String attributeName, Object attributeValue) {
Assert.notNull(attributeValue, () -> String.format(
"Attribute '%s' not found in attributes for annotation [%s]",
attributeName, this.displayName));
}
private void assertNotException(String attributeName, Object attributeValue) {
if (attributeValue instanceof Throwable throwable) {
throw new IllegalArgumentException(String.format(
"Attribute '%s' for annotation [%s] was not resolvable due to exception [%s]",
attributeName, this.displayName, attributeValue), throwable);
}
}
private void assertAttributeType(String attributeName, Object attributeValue, Class<?> expectedType) {
if (!expectedType.isInstance(attributeValue)) {
if (!expectedType.isInstance(value)) {
throw new IllegalArgumentException(String.format(
"Attribute '%s' is of type %s, but %s was expected in attributes for annotation [%s]",
attributeName, attributeValue.getClass().getSimpleName(), expectedType.getSimpleName(),
attributeName, value.getClass().getSimpleName(), expectedType.getSimpleName(),
this.displayName));
}
return (T) value;
}
@Override

View File

@ -985,8 +985,12 @@ public abstract class AnnotationUtils {
}
}
private static Object getAttributeValueForMirrorResolution(Method attribute, Object attributes) {
Object result = ((AnnotationAttributes) attributes).get(attribute.getName());
@Nullable
private static Object getAttributeValueForMirrorResolution(Method attribute, @Nullable Object attributes) {
if (!(attributes instanceof AnnotationAttributes annotationAttributes)) {
return null;
}
Object result = annotationAttributes.get(attribute.getName());
return (result instanceof DefaultValueHolder defaultValueHolder ? defaultValueHolder.defaultValue : result);
}

View File

@ -127,29 +127,31 @@ abstract class AnnotationsScanner {
if (result != null) {
return result;
}
Annotation[] declaredAnnotations = getDeclaredAnnotations(source, true);
if (relevant == null && declaredAnnotations.length > 0) {
relevant = root.getAnnotations();
remaining = relevant.length;
}
for (int i = 0; i < declaredAnnotations.length; i++) {
if (declaredAnnotations[i] != null) {
boolean isRelevant = false;
for (int relevantIndex = 0; relevantIndex < relevant.length; relevantIndex++) {
if (relevant[relevantIndex] != null &&
declaredAnnotations[i].annotationType() == relevant[relevantIndex].annotationType()) {
isRelevant = true;
relevant[relevantIndex] = null;
remaining--;
break;
Annotation[] declaredAnns = getDeclaredAnnotations(source, true);
if (declaredAnns.length > 0) {
if (relevant == null) {
relevant = root.getAnnotations();
remaining = relevant.length;
}
for (int i = 0; i < declaredAnns.length; i++) {
if (declaredAnns[i] != null) {
boolean isRelevant = false;
for (int relevantIndex = 0; relevantIndex < relevant.length; relevantIndex++) {
if (relevant[relevantIndex] != null &&
declaredAnns[i].annotationType() == relevant[relevantIndex].annotationType()) {
isRelevant = true;
relevant[relevantIndex] = null;
remaining--;
break;
}
}
if (!isRelevant) {
declaredAnns[i] = null;
}
}
if (!isRelevant) {
declaredAnnotations[i] = null;
}
}
}
result = processor.doWithAnnotations(context, aggregateIndex, source, declaredAnnotations);
result = processor.doWithAnnotations(context, aggregateIndex, source, declaredAnns);
if (result != null) {
return result;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -322,12 +322,13 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
@SuppressWarnings("unchecked")
protected A createSynthesizedAnnotation() {
// Check root annotation
if (isTargetAnnotation(this.rootAttributes) && !isSynthesizable((Annotation) this.rootAttributes)) {
return (A) this.rootAttributes;
if (this.rootAttributes instanceof Annotation ann && isTargetAnnotation(ann) && !isSynthesizable(ann)) {
return (A) ann;
}
// Check meta-annotation
else if (isTargetAnnotation(this.mapping.getAnnotation()) && !isSynthesizable(this.mapping.getAnnotation())) {
return (A) this.mapping.getAnnotation();
Annotation meta = this.mapping.getAnnotation();
if (meta != null && isTargetAnnotation(meta) && !isSynthesizable(meta)) {
return (A) meta;
}
return SynthesizedMergedAnnotationInvocationHandler.createProxy(this, getType());
}
@ -338,7 +339,7 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
* @param obj the object to check
* @since 5.3.22
*/
private boolean isTargetAnnotation(@Nullable Object obj) {
private boolean isTargetAnnotation(Object obj) {
return getType().isInstance(obj);
}
@ -432,7 +433,7 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
}
@Nullable
private Object getValueForMirrorResolution(Method attribute, Object annotation) {
private Object getValueForMirrorResolution(Method attribute, @Nullable Object annotation) {
int attributeIndex = this.mapping.getAttributes().indexOf(attribute);
boolean valueAttribute = VALUE.equals(attribute.getName());
return getValue(attributeIndex, !valueAttribute, true);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -95,20 +95,19 @@ public interface Decoder<T> {
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) throws DecodingException {
CompletableFuture<T> future = decodeToMono(Mono.just(buffer), targetType, mimeType, hints).toFuture();
Assert.state(future.isDone(), "DataBuffer decoding should have completed.");
Assert.state(future.isDone(), "DataBuffer decoding should have completed");
Throwable failure;
try {
return future.get();
}
catch (ExecutionException ex) {
failure = ex.getCause();
Throwable cause = ex.getCause();
throw (cause instanceof CodecException codecException ? codecException :
new DecodingException("Failed to decode: " + (cause != null ? cause.getMessage() : ex), cause));
}
catch (InterruptedException ex) {
failure = ex;
throw new DecodingException("Interrupted during decode", ex);
}
throw (failure instanceof CodecException codecException ? codecException :
new DecodingException("Failed to decode: " + failure.getMessage(), failure));
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -80,6 +80,7 @@ public class ResourceDecoder extends AbstractDataBufferDecoder<Resource> {
if (clazz == InputStreamResource.class) {
return new InputStreamResource(new ByteArrayInputStream(bytes)) {
@Override
@Nullable
public String getFilename() {
return filename;
}
@ -92,6 +93,7 @@ public class ResourceDecoder extends AbstractDataBufferDecoder<Resource> {
else if (Resource.class.isAssignableFrom(clazz)) {
return new ByteArrayResource(bytes) {
@Override
@Nullable
public String getFilename() {
return filename;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -136,7 +136,7 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter {
@Nullable
private static Executable getValidatedExecutable(Class<?> targetClass, Class<?> sourceClass) {
Executable executable = conversionExecutableCache.get(targetClass);
if (isApplicable(executable, sourceClass)) {
if (executable != null && isApplicable(executable, sourceClass)) {
return executable;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,6 +19,7 @@ package org.springframework.core.convert.support;
import java.util.regex.Pattern;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.Nullable;
/**
* Converts from a String to a {@link java.util.regex.Pattern}.
@ -30,6 +31,7 @@ import org.springframework.core.convert.converter.Converter;
final class StringToPatternConverter implements Converter<String, Pattern> {
@Override
@Nullable
public Pattern convert(String source) {
if (source.isEmpty()) {
return null;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,16 +19,19 @@ package org.springframework.core.convert.support;
import kotlin.text.Regex;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.Nullable;
/**
* Converts from a String to a Kotlin {@link Regex}.
*
* @author Stephane Nicoll
* @author Sebastien Deleuze
* @since 6.1
*/
class StringToRegexConverter implements Converter<String, Regex> {
@Override
@Nullable
public Regex convert(String source) {
if (source.isEmpty()) {
return null;

View File

@ -71,7 +71,6 @@ public abstract class DataBufferUtils {
private static final int DEFAULT_CHUNK_SIZE = 1024;
//---------------------------------------------------------------------
// Reading
//---------------------------------------------------------------------
@ -1083,7 +1082,7 @@ public abstract class DataBufferUtils {
attachment.iterator().close();
DataBuffer dataBuffer = attachment.dataBuffer();
if (this.state.get().equals(State.DISPOSED)) {
if (this.state.get() == State.DISPOSED) {
release(dataBuffer);
closeChannel(this.channel);
return;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,6 +20,8 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.function.Supplier;
import org.springframework.lang.Nullable;
/**
* Default "no op" {@code ApplicationStartup} implementation.
*
@ -52,6 +54,7 @@ class DefaultApplicationStartup implements ApplicationStartup {
}
@Override
@Nullable
public Long getParentId() {
return null;
}
@ -73,7 +76,6 @@ class DefaultApplicationStartup implements ApplicationStartup {
@Override
public void end() {
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -80,13 +80,13 @@ public abstract class AbstractTypeHierarchyTraversingFilter implements TypeFilte
else {
// Need to read superclass to determine a match...
try {
if (match(metadata.getSuperClassName(), metadataReaderFactory)) {
if (match(superClassName, metadataReaderFactory)) {
return true;
}
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not read superclass [" + metadata.getSuperClassName() +
logger.debug("Could not read superclass [" + superClassName +
"] of type-filtered class [" + metadata.getClassName() + "]");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -217,7 +217,7 @@ public abstract class JmsUtils {
try {
session.commit();
}
catch (jakarta.jms.TransactionInProgressException | jakarta.jms.IllegalStateException ex) {
catch (jakarta.jms.TransactionInProgressException ex) {
// Ignore -> can only happen in case of a JTA transaction.
}
}
@ -232,7 +232,7 @@ public abstract class JmsUtils {
try {
session.rollback();
}
catch (jakarta.jms.TransactionInProgressException | jakarta.jms.IllegalStateException ex) {
catch (jakarta.jms.TransactionInProgressException ex) {
// Ignore -> can only happen in case of a JTA transaction.
}
}