Index: 3rdParty_sources/spring/org/springframework/aop/aspectj/annotation/AspectJProxyFactory.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/aspectj/annotation/AspectJProxyFactory.java (.../AspectJProxyFactory.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/aspectj/annotation/AspectJProxyFactory.java (.../AspectJProxyFactory.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -34,7 +34,7 @@ /** * AspectJ-based proxy factory, allowing for programmatic building * of proxies which include AspectJ aspects (code style as well - * Java 5 annotation style). + * annotation style). * * @author Rob Harrop * @author Juergen Hoeller Index: 3rdParty_sources/spring/org/springframework/aop/aspectj/annotation/AspectMetadata.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/aspectj/annotation/AspectMetadata.java (.../AspectMetadata.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/aspectj/annotation/AspectMetadata.java (.../AspectMetadata.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -60,8 +60,8 @@ private final Class aspectClass; /** - * AspectJ reflection information (AspectJ 5 / Java 5 specific). - * Re-resolved on deserialization since it isn't serializable itself. + * AspectJ reflection information. + *

Re-resolved on deserialization since it isn't serializable itself. */ private transient AjType ajType; Index: 3rdParty_sources/spring/org/springframework/aop/framework/AopProxyUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/framework/AopProxyUtils.java (.../AopProxyUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/framework/AopProxyUtils.java (.../AopProxyUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -44,6 +44,7 @@ * * @author Rod Johnson * @author Juergen Hoeller + * @author Sam Brannen * @see org.springframework.aop.support.AopUtils */ public abstract class AopProxyUtils { @@ -133,7 +134,7 @@ if (targetClass.isInterface()) { advised.setInterfaces(targetClass); } - else if (Proxy.isProxyClass(targetClass)) { + else if (Proxy.isProxyClass(targetClass) || isLambda(targetClass)) { advised.setInterfaces(targetClass.getInterfaces()); } specifiedInterfaces = advised.getProxiedInterfaces(); @@ -244,4 +245,18 @@ return arguments; } + /** + * Determine if the supplied {@link Class} is a JVM-generated implementation + * class for a lambda expression or method reference. + *

This method makes a best-effort attempt at determining this, based on + * checks that work on modern, main stream JVMs. + * @param clazz the class to check + * @return {@code true} if the class is a lambda implementation class + * @since 5.3.16 + */ + static boolean isLambda(Class clazz) { + return (clazz.isSynthetic() && (clazz.getSuperclass() == Object.class) && + (clazz.getInterfaces().length > 0) && clazz.getName().contains("$$Lambda")); + } + } Index: 3rdParty_sources/spring/org/springframework/aop/framework/DefaultAopProxyFactory.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/framework/DefaultAopProxyFactory.java (.../DefaultAopProxyFactory.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/framework/DefaultAopProxyFactory.java (.../DefaultAopProxyFactory.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -40,15 +40,17 @@ * @author Rod Johnson * @author Juergen Hoeller * @author Sebastien Deleuze + * @author Sam Brannen * @since 12.03.2004 * @see AdvisedSupport#setOptimize * @see AdvisedSupport#setProxyTargetClass * @see AdvisedSupport#setInterfaces */ -@SuppressWarnings("serial") public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { + private static final long serialVersionUID = 7930414337282325166L; + @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (!NativeDetector.inNativeImage() && @@ -58,7 +60,7 @@ throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } - if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { + if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || AopProxyUtils.isLambda(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); Index: 3rdParty_sources/spring/org/springframework/aop/framework/ProxyFactoryBean.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/framework/ProxyFactoryBean.java (.../ProxyFactoryBean.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/framework/ProxyFactoryBean.java (.../ProxyFactoryBean.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -421,11 +421,7 @@ * are unaffected by such changes. */ private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException { - if (this.advisorChainInitialized) { - return; - } - - if (!ObjectUtils.isEmpty(this.interceptorNames)) { + if (!this.advisorChainInitialized && !ObjectUtils.isEmpty(this.interceptorNames)) { if (this.beanFactory == null) { throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " + "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames)); @@ -464,9 +460,9 @@ addAdvisorOnChainCreation(advice); } } - } - this.advisorChainInitialized = true; + this.advisorChainInitialized = true; + } } Index: 3rdParty_sources/spring/org/springframework/aop/framework/adapter/ThrowsAdviceAdapter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/framework/adapter/ThrowsAdviceAdapter.java (.../ThrowsAdviceAdapter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/framework/adapter/ThrowsAdviceAdapter.java (.../ThrowsAdviceAdapter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2021 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. @@ -25,8 +25,8 @@ import org.springframework.aop.ThrowsAdvice; /** - * Adapter to enable {@link org.springframework.aop.MethodBeforeAdvice} - * to be used in the Spring AOP framework. + * Adapter to enable {@link org.springframework.aop.ThrowsAdvice} to be used + * in the Spring AOP framework. * * @author Rod Johnson * @author Juergen Hoeller Index: 3rdParty_sources/spring/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java (.../AsyncExecutionAspectSupport.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java (.../AsyncExecutionAspectSupport.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -233,7 +233,8 @@ return beanFactory.getBean(TaskExecutor.class); } catch (NoUniqueBeanDefinitionException ex) { - logger.debug("Could not find unique TaskExecutor bean", ex); + logger.debug("Could not find unique TaskExecutor bean. " + + "Continuing search for an Executor bean named 'taskExecutor'", ex); try { return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class); } @@ -246,7 +247,8 @@ } } catch (NoSuchBeanDefinitionException ex) { - logger.debug("Could not find default TaskExecutor bean", ex); + logger.debug("Could not find default TaskExecutor bean. " + + "Continuing search for an Executor bean named 'taskExecutor'", ex); try { return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class); } Index: 3rdParty_sources/spring/org/springframework/aop/support/AopUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/support/AopUtils.java (.../AopUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/support/AopUtils.java (.../AopUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -183,8 +183,8 @@ * may be {@code DefaultFoo}. In this case, the method may be * {@code DefaultFoo.bar()}. This enables attributes on that method to be found. *

NOTE: In contrast to {@link org.springframework.util.ClassUtils#getMostSpecificMethod}, - * this method resolves Java 5 bridge methods in order to retrieve attributes - * from the original method definition. + * this method resolves bridge methods in order to retrieve attributes from + * the original method definition. * @param method the method to be invoked, which may come from an interface * @param targetClass the target class for the current invocation. * May be {@code null} or may not even implement the method. Index: 3rdParty_sources/spring/org/springframework/aop/support/annotation/AnnotationClassFilter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/support/annotation/AnnotationClassFilter.java (.../AnnotationClassFilter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/support/annotation/AnnotationClassFilter.java (.../AnnotationClassFilter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -24,8 +24,7 @@ import org.springframework.util.Assert; /** - * Simple ClassFilter that looks for a specific Java 5 annotation - * being present on a class. + * Simple ClassFilter that looks for a specific annotation being present on a class. * * @author Juergen Hoeller * @since 2.0 Index: 3rdParty_sources/spring/org/springframework/aop/support/annotation/AnnotationMatchingPointcut.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/support/annotation/AnnotationMatchingPointcut.java (.../AnnotationMatchingPointcut.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/support/annotation/AnnotationMatchingPointcut.java (.../AnnotationMatchingPointcut.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -26,9 +26,8 @@ import org.springframework.util.Assert; /** - * Simple Pointcut that looks for a specific Java 5 annotation - * being present on a {@link #forClassAnnotation class} or - * {@link #forMethodAnnotation method}. + * Simple {@link Pointcut} that looks for a specific annotation being present on a + * {@linkplain #forClassAnnotation class} or {@linkplain #forMethodAnnotation method}. * * @author Juergen Hoeller * @author Sam Brannen Index: 3rdParty_sources/spring/org/springframework/aop/support/annotation/AnnotationMethodMatcher.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/aop/support/annotation/AnnotationMethodMatcher.java (.../AnnotationMethodMatcher.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/aop/support/annotation/AnnotationMethodMatcher.java (.../AnnotationMethodMatcher.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,9 +27,10 @@ import org.springframework.util.Assert; /** - * Simple MethodMatcher that looks for a specific Java 5 annotation - * being present on a method (checking both the method on the invoked - * interface, if any, and the corresponding method on the target class). + * Simple {@link org.springframework.aop.MethodMatcher MethodMatcher} that looks + * for a specific annotation being present on a method (checking both the method + * on the invoked interface, if any, and the corresponding method on the target + * class). * * @author Juergen Hoeller * @author Sam Brannen Index: 3rdParty_sources/spring/org/springframework/asm/ClassReader.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/asm/ClassReader.java (.../ClassReader.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/asm/ClassReader.java (.../ClassReader.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -194,7 +194,7 @@ this.b = classFileBuffer; // Check the class' major_version. This field is after the magic and minor_version fields, which // use 4 and 2 bytes respectively. - if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V18) { + if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V19) { throw new IllegalArgumentException( "Unsupported class file major version " + readShort(classFileOffset + 6)); } @@ -313,7 +313,7 @@ if (inputStream == null) { throw new IOException("Class not found"); } - int bufferSize = calculateBufferSize(inputStream); + int bufferSize = computeBufferSize(inputStream); try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { byte[] data = new byte[bufferSize]; int bytesRead; @@ -336,13 +336,12 @@ } } - private static int calculateBufferSize(final InputStream inputStream) throws IOException { + private static int computeBufferSize(final InputStream inputStream) throws IOException { int expectedLength = inputStream.available(); /* - * Some implementations can return 0 while holding available data - * (e.g. new FileInputStream("/proc/a_file")) - * Also in some pathological cases a very small number might be returned, - * and in this case we use default size + * Some implementations can return 0 while holding available data (e.g. new + * FileInputStream("/proc/a_file")). Also in some pathological cases a very small number might + * be returned, and in this case we use a default size. */ if (expectedLength < 256) { return INPUT_STREAM_DATA_CHUNK_SIZE; @@ -861,7 +860,7 @@ currentOffset += 2; } - // Read the 'provides_count' and 'provides' fields. + // Read the 'provides_count' and 'provides' fields. int providesCount = readUnsignedShort(currentOffset); currentOffset += 2; while (providesCount-- > 0) { Index: 3rdParty_sources/spring/org/springframework/asm/ClassWriter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/asm/ClassWriter.java (.../ClassWriter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/asm/ClassWriter.java (.../ClassWriter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -65,6 +65,12 @@ */ public static final int COMPUTE_FRAMES = 2; + /** + * The flags passed to the constructor. Must be zero or more of {@link #COMPUTE_MAXS} and {@link + * #COMPUTE_FRAMES}. + */ + private final int flags; + // Note: fields are ordered as in the ClassFile structure, and those related to attributes are // ordered as in Section 4.7 of the JVMS. @@ -248,24 +254,40 @@ * @param classReader the {@link ClassReader} used to read the original class. It will be used to * copy the entire constant pool and bootstrap methods from the original class and also to * copy other fragments of original bytecode where applicable. - * @param flags option flags that can be used to modify the default behavior of this class.Must be - * zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}. These option flags do - * not affect methods that are copied as is in the new class. This means that neither the + * @param flags option flags that can be used to modify the default behavior of this class. Must + * be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}. These option flags + * do not affect methods that are copied as is in the new class. This means that neither the * maximum stack size nor the stack frames will be computed for these methods. */ public ClassWriter(final ClassReader classReader, final int flags) { super(/* latest api = */ Opcodes.ASM9); + this.flags = flags; symbolTable = classReader == null ? new SymbolTable(this) : new SymbolTable(this, classReader); if ((flags & COMPUTE_FRAMES) != 0) { - this.compute = MethodWriter.COMPUTE_ALL_FRAMES; + compute = MethodWriter.COMPUTE_ALL_FRAMES; } else if ((flags & COMPUTE_MAXS) != 0) { - this.compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL; + compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL; } else { - this.compute = MethodWriter.COMPUTE_NOTHING; + compute = MethodWriter.COMPUTE_NOTHING; } } // ----------------------------------------------------------------------------------------------- + // Accessors + // ----------------------------------------------------------------------------------------------- + + /** + * Returns true if all the given flags were passed to the constructor. + * + * @param flags some option flags. Must be zero or more of {@link #COMPUTE_MAXS} and {@link + * #COMPUTE_FRAMES}. + * @return true if all the given flags, or more, were passed to the constructor. + */ + public boolean hasFlags(final int flags) { + return (this.flags & flags) == flags; + } + + // ----------------------------------------------------------------------------------------------- // Implementation of the ClassVisitor abstract class // ----------------------------------------------------------------------------------------------- Index: 3rdParty_sources/spring/org/springframework/asm/Opcodes.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/asm/Opcodes.java (.../Opcodes.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/asm/Opcodes.java (.../Opcodes.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -283,6 +283,7 @@ int V16 = 0 << 16 | 60; int V17 = 0 << 16 | 61; int V18 = 0 << 16 | 62; + int V19 = 0 << 16 | 63; /** * Version flag indicating that the class is using 'preview' features. Index: 3rdParty_sources/spring/org/springframework/beans/BeanUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/BeanUtils.java (.../BeanUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/BeanUtils.java (.../BeanUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -691,7 +691,25 @@ * from each other, as long as the properties match. Any bean properties that the * source bean exposes but the target bean does not will silently be ignored. *

This is just a convenience method. For more complex transfer needs, - * consider using a full BeanWrapper. + * consider using a full {@link BeanWrapper}. + *

As of Spring Framework 5.3, this method honors generic type information + * when matching properties in the source and target objects. + *

The following table provides a non-exhaustive set of examples of source + * and target property types that can be copied as well as source and target + * property types that cannot be copied. + * + * + * + * + * + * + * + * + * + * + * + * + *
source property typetarget property typecopy supported
{@code Integer}{@code Integer}yes
{@code Integer}{@code Number}yes
{@code List}{@code List}yes
{@code List}{@code List}yes
{@code List}{@code List}yes
{@code List}{@code List}yes
{@code String}{@code Integer}no
{@code Number}{@code Integer}no
{@code List}{@code List}no
{@code List}{@code List}no
* @param source the source bean * @param target the target bean * @throws BeansException if the copying failed @@ -708,7 +726,10 @@ * from each other, as long as the properties match. Any bean properties that the * source bean exposes but the target bean does not will silently be ignored. *

This is just a convenience method. For more complex transfer needs, - * consider using a full BeanWrapper. + * consider using a full {@link BeanWrapper}. + *

As of Spring Framework 5.3, this method honors generic type information + * when matching properties in the source and target objects. See the + * documentation for {@link #copyProperties(Object, Object)} for details. * @param source the source bean * @param target the target bean * @param editable the class (or interface) to restrict property setting to @@ -726,7 +747,10 @@ * from each other, as long as the properties match. Any bean properties that the * source bean exposes but the target bean does not will silently be ignored. *

This is just a convenience method. For more complex transfer needs, - * consider using a full BeanWrapper. + * consider using a full {@link BeanWrapper}. + *

As of Spring Framework 5.3, this method honors generic type information + * when matching properties in the source and target objects. See the + * documentation for {@link #copyProperties(Object, Object)} for details. * @param source the source bean * @param target the target bean * @param ignoreProperties array of property names to ignore @@ -743,7 +767,8 @@ * from each other, as long as the properties match. Any bean properties that the * source bean exposes but the target bean does not will silently be ignored. *

As of Spring Framework 5.3, this method honors generic type information - * when matching properties in the source and target objects. + * when matching properties in the source and target objects. See the + * documentation for {@link #copyProperties(Object, Object)} for details. * @param source the source bean * @param target the target bean * @param editable the class (or interface) to restrict property setting to Index: 3rdParty_sources/spring/org/springframework/beans/CachedIntrospectionResults.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/CachedIntrospectionResults.java (.../CachedIntrospectionResults.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/CachedIntrospectionResults.java (.../CachedIntrospectionResults.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -22,6 +22,7 @@ import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.security.ProtectionDomain; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; @@ -286,11 +287,15 @@ // This call is slow so we do it once. PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { - if (Class.class == beanClass && - ("classLoader".equals(pd.getName()) || "protectionDomain".equals(pd.getName()))) { - // Ignore Class.getClassLoader() and getProtectionDomain() methods - nobody needs to bind to those + if (Class.class == beanClass && (!"name".equals(pd.getName()) && !pd.getName().endsWith("Name"))) { + // Only allow all name variants of Class properties continue; } + if (pd.getPropertyType() != null && (ClassLoader.class.isAssignableFrom(pd.getPropertyType()) + || ProtectionDomain.class.isAssignableFrom(pd.getPropertyType()))) { + // Ignore ClassLoader and ProtectionDomain types - nobody needs to bind to those + continue; + } if (logger.isTraceEnabled()) { logger.trace("Found bean property '" + pd.getName() + "'" + (pd.getPropertyType() != null ? " of type [" + pd.getPropertyType().getName() + "]" : "") + @@ -337,6 +342,11 @@ // GenericTypeAwarePropertyDescriptor leniently resolves a set* write method // against a declared read method, so we prefer read method descriptors here. pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd); + if (pd.getPropertyType() != null && (ClassLoader.class.isAssignableFrom(pd.getPropertyType()) + || ProtectionDomain.class.isAssignableFrom(pd.getPropertyType()))) { + // Ignore ClassLoader and ProtectionDomain types - nobody needs to bind to those + continue; + } this.propertyDescriptors.put(pd.getName(), pd); Method readMethod = pd.getReadMethod(); if (readMethod != null) { Index: 3rdParty_sources/spring/org/springframework/beans/annotation/package-info.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/annotation/package-info.java (.../package-info.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/annotation/package-info.java (.../package-info.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /** - * Support package for beans-style handling of Java 5 annotations. + * Support package for beans-style handling of annotations. */ @NonNullApi @NonNullFields Index: 3rdParty_sources/spring/org/springframework/beans/factory/BeanFactory.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/BeanFactory.java (.../BeanFactory.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/BeanFactory.java (.../BeanFactory.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -214,6 +214,7 @@ /** * Return a provider for the specified bean, allowing for lazy on-demand retrieval * of instances, including availability and uniqueness options. + *

For matching a generic type, consider {@link #getBeanProvider(ResolvableType)}. * @param requiredType type the bean must match; can be an interface or superclass * @return a corresponding provider handle * @since 5.1 @@ -223,13 +224,20 @@ /** * Return a provider for the specified bean, allowing for lazy on-demand retrieval - * of instances, including availability and uniqueness options. - * @param requiredType type the bean must match; can be a generic type declaration. - * Note that collection types are not supported here, in contrast to reflective + * of instances, including availability and uniqueness options. This variant allows + * for specifying a generic type to match, similar to reflective injection points + * with generic type declarations in method/constructor parameters. + *

Note that collections of beans are not supported here, in contrast to reflective * injection points. For programmatically retrieving a list of beans matching a * specific type, specify the actual bean type as an argument here and subsequently * use {@link ObjectProvider#orderedStream()} or its lazy streaming/iteration options. + *

Also, generics matching is strict here, as per the Java assignment rules. + * For lenient fallback matching with unchecked semantics (similar to the ´unchecked´ + * Java compiler warning), consider calling {@link #getBeanProvider(Class)} with the + * raw type as a second step if no full generic match is + * {@link ObjectProvider#getIfAvailable() available} with this variant. * @return a corresponding provider handle + * @param requiredType type the bean must match; can be a generic type declaration * @since 5.1 * @see ObjectProvider#iterator() * @see ObjectProvider#stream() Index: 3rdParty_sources/spring/org/springframework/beans/factory/ListableBeanFactory.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/ListableBeanFactory.java (.../ListableBeanFactory.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/ListableBeanFactory.java (.../ListableBeanFactory.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -353,9 +353,31 @@ * @since 3.0 * @see #getBeanNamesForAnnotation * @see #getBeansWithAnnotation + * @see #getType(String) */ @Nullable A findAnnotationOnBean(String beanName, Class annotationType) throws NoSuchBeanDefinitionException; + /** + * Find an {@link Annotation} of {@code annotationType} on the specified bean, + * traversing its interfaces and super classes if no annotation can be found on + * the given class itself, as well as checking the bean's factory method (if any). + * @param beanName the name of the bean to look for annotations on + * @param annotationType the type of annotation to look for + * (at class, interface or factory method level of the specified bean) + * @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized + * just for the purpose of determining its object type + * @return the annotation of the given type if found, or {@code null} otherwise + * @throws NoSuchBeanDefinitionException if there is no bean with the given name + * @since 5.3.14 + * @see #getBeanNamesForAnnotation + * @see #getBeansWithAnnotation + * @see #getType(String, boolean) + */ + @Nullable + A findAnnotationOnBean( + String beanName, Class annotationType, boolean allowFactoryBeanInit) + throws NoSuchBeanDefinitionException; + } Index: 3rdParty_sources/spring/org/springframework/beans/factory/ListableBeanFactoryExtensions.kt =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/ListableBeanFactoryExtensions.kt (.../ListableBeanFactoryExtensions.kt) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/ListableBeanFactoryExtensions.kt (.../ListableBeanFactoryExtensions.kt) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -64,6 +64,6 @@ * @author Sebastien Deleuze * @since 5.0 */ -inline fun ListableBeanFactory.findAnnotationOnBean(beanName:String): Annotation? = +inline fun ListableBeanFactory.findAnnotationOnBean(beanName:String): T? = findAnnotationOnBean(beanName, T::class.java) Index: 3rdParty_sources/spring/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java (.../AutowiredAnnotationBeanPostProcessor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java (.../AutowiredAnnotationBeanPostProcessor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -537,10 +537,10 @@ * @param ann the Autowired annotation * @return whether the annotation indicates that a dependency is required */ - @SuppressWarnings({"deprecation", "cast"}) + @SuppressWarnings("deprecation") protected boolean determineRequiredStatus(MergedAnnotation ann) { - return determineRequiredStatus( - ann.asMap(mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType()))); + return determineRequiredStatus(ann. asMap( + mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType()))); } /** Index: 3rdParty_sources/spring/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java (.../InitDestroyAnnotationBeanPostProcessor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java (.../InitDestroyAnnotationBeanPostProcessor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -302,7 +302,7 @@ beanDefinition.registerExternallyManagedInitMethod(methodIdentifier); checkedInitMethods.add(element); if (logger.isTraceEnabled()) { - logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + element); + logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + methodIdentifier); } } } @@ -313,7 +313,7 @@ beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier); checkedDestroyMethods.add(element); if (logger.isTraceEnabled()) { - logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + element); + logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + methodIdentifier); } } } Index: 3rdParty_sources/spring/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.java (.../RequiredAnnotationBeanPostProcessor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.java (.../RequiredAnnotationBeanPostProcessor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -44,7 +44,7 @@ /** * {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation * that enforces required JavaBean properties to have been configured. - * Required bean properties are detected through a Java 5 annotation: + * Required bean properties are detected through an annotation: * by default, Spring's {@link Required} annotation. * *

The motivation for the existence of this BeanPostProcessor is to allow Index: 3rdParty_sources/spring/org/springframework/beans/factory/config/BeanExpressionResolver.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/config/BeanExpressionResolver.java (.../BeanExpressionResolver.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/config/BeanExpressionResolver.java (.../BeanExpressionResolver.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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,8 +20,8 @@ import org.springframework.lang.Nullable; /** - * Strategy interface for resolving a value through evaluating it - * as an expression, if applicable. + * Strategy interface for resolving a value by evaluating it as an expression, + * if applicable. * *

A raw {@link org.springframework.beans.factory.BeanFactory} does not * contain a default implementation of this strategy. However, @@ -36,12 +36,13 @@ /** * Evaluate the given value as an expression, if applicable; * return the value as-is otherwise. - * @param value the value to check - * @param evalContext the evaluation context + * @param value the value to evaluate as an expression + * @param beanExpressionContext the bean expression context to use when + * evaluating the expression * @return the resolved value (potentially the given value as-is) * @throws BeansException if evaluation failed */ @Nullable - Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException; + Object evaluate(@Nullable String value, BeanExpressionContext beanExpressionContext) throws BeansException; } Index: 3rdParty_sources/spring/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.java (.../InstantiationAwareBeanPostProcessor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.java (.../InstantiationAwareBeanPostProcessor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -34,9 +34,7 @@ * *

NOTE: This interface is a special purpose interface, mainly for * internal use within the framework. It is recommended to implement the plain - * {@link BeanPostProcessor} interface as far as possible, or to derive from - * {@link InstantiationAwareBeanPostProcessorAdapter} in order to be shielded - * from extensions to this interface. + * {@link BeanPostProcessor} interface as far as possible. * * @author Juergen Hoeller * @author Rod Johnson Index: 3rdParty_sources/spring/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java (.../AbstractAutowireCapableBeanFactory.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java (.../AbstractAutowireCapableBeanFactory.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -1844,7 +1844,7 @@ throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); - if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { + if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } @@ -1868,7 +1868,7 @@ String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && - !mbd.isExternallyManagedInitMethod(initMethodName)) { + !mbd.hasAnyExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } } @@ -1908,7 +1908,7 @@ if (logger.isTraceEnabled()) { logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'"); } - Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod); + Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod, bean.getClass()); if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction) () -> { Index: 3rdParty_sources/spring/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java (.../AbstractBeanDefinitionReader.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java (.../AbstractBeanDefinitionReader.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -103,6 +103,14 @@ } + /** + * Return the bean factory to register the bean definitions with. + *

The factory is exposed through the BeanDefinitionRegistry interface, + * encapsulating the methods that are relevant for bean definition handling. + * @deprecated as of Spring Framework 5.3.15 in favor of {@link #getRegistry()}, + * to be removed in Spring Framework 6.0 + */ + @Deprecated public final BeanDefinitionRegistry getBeanFactory() { return this.registry; } Index: 3rdParty_sources/spring/org/springframework/beans/factory/support/BeanDefinitionReader.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/support/BeanDefinitionReader.java (.../BeanDefinitionReader.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/support/BeanDefinitionReader.java (.../BeanDefinitionReader.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2021 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. @@ -22,15 +22,15 @@ import org.springframework.lang.Nullable; /** - * Simple interface for bean definition readers. - * Specifies load methods with Resource and String location parameters. + * Simple interface for bean definition readers that specifies load methods with + * {@link Resource} and {@link String} location parameters. * *

Concrete bean definition readers can of course add additional * load and register methods for bean definitions, specific to * their bean definition format. * *

Note that a bean definition reader does not have to implement - * this interface. It only serves as suggestion for bean definition + * this interface. It only serves as a suggestion for bean definition * readers that want to follow standard naming conventions. * * @author Juergen Hoeller @@ -41,25 +41,25 @@ /** * Return the bean factory to register the bean definitions with. - *

The factory is exposed through the BeanDefinitionRegistry interface, + *

The factory is exposed through the {@link BeanDefinitionRegistry} interface, * encapsulating the methods that are relevant for bean definition handling. */ BeanDefinitionRegistry getRegistry(); /** - * Return the resource loader to use for resource locations. - * Can be checked for the ResourcePatternResolver interface and cast + * Return the {@link ResourceLoader} to use for resource locations. + *

Can be checked for the {@code ResourcePatternResolver} interface and cast * accordingly, for loading multiple resources for a given resource pattern. *

A {@code null} return value suggests that absolute resource loading * is not available for this bean definition reader. *

This is mainly meant to be used for importing further resources * from within a bean definition resource, for example via the "import" * tag in XML bean definitions. It is recommended, however, to apply * such imports relative to the defining resource; only explicit full - * resource locations will trigger absolute resource loading. + * resource locations will trigger absolute path based resource loading. *

There is also a {@code loadBeanDefinitions(String)} method available, * for loading bean definitions from a resource location (or location pattern). - * This is a convenience to avoid explicit ResourceLoader handling. + * This is a convenience to avoid explicit {@code ResourceLoader} handling. * @see #loadBeanDefinitions(String) * @see org.springframework.core.io.support.ResourcePatternResolver */ @@ -70,13 +70,13 @@ * Return the class loader to use for bean classes. *

{@code null} suggests to not load bean classes eagerly * but rather to just register bean definitions with class names, - * with the corresponding Classes to be resolved later (or never). + * with the corresponding classes to be resolved later (or never). */ @Nullable ClassLoader getBeanClassLoader(); /** - * Return the BeanNameGenerator to use for anonymous beans + * Return the {@link BeanNameGenerator} to use for anonymous beans * (without explicit bean name specified). */ BeanNameGenerator getBeanNameGenerator(); @@ -101,9 +101,10 @@ /** * Load bean definitions from the specified resource location. *

The location can also be a location pattern, provided that the - * ResourceLoader of this bean definition reader is a ResourcePatternResolver. - * @param location the resource location, to be loaded with the ResourceLoader - * (or ResourcePatternResolver) of this bean definition reader + * {@link ResourceLoader} of this bean definition reader is a + * {@code ResourcePatternResolver}. + * @param location the resource location, to be loaded with the {@code ResourceLoader} + * (or {@code ResourcePatternResolver}) of this bean definition reader * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors * @see #getResourceLoader() @@ -114,8 +115,8 @@ /** * Load bean definitions from the specified resource locations. - * @param locations the resource locations, to be loaded with the ResourceLoader - * (or ResourcePatternResolver) of this bean definition reader + * @param locations the resource locations, to be loaded with the {@code ResourceLoader} + * (or {@code ResourcePatternResolver}) of this bean definition reader * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors */ Index: 3rdParty_sources/spring/org/springframework/beans/factory/support/DefaultListableBeanFactory.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/support/DefaultListableBeanFactory.java (.../DefaultListableBeanFactory.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/support/DefaultListableBeanFactory.java (.../DefaultListableBeanFactory.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -730,14 +730,23 @@ public A findAnnotationOnBean(String beanName, Class annotationType) throws NoSuchBeanDefinitionException { - return findMergedAnnotationOnBean(beanName, annotationType) + return findAnnotationOnBean(beanName, annotationType, true); + } + + @Override + @Nullable + public A findAnnotationOnBean( + String beanName, Class annotationType, boolean allowFactoryBeanInit) + throws NoSuchBeanDefinitionException { + + return findMergedAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit) .synthesize(MergedAnnotation::isPresent).orElse(null); } private MergedAnnotation findMergedAnnotationOnBean( - String beanName, Class annotationType) { + String beanName, Class annotationType, boolean allowFactoryBeanInit) { - Class beanType = getType(beanName); + Class beanType = getType(beanName, allowFactoryBeanInit); if (beanType != null) { MergedAnnotation annotation = MergedAnnotations.from(beanType, SearchStrategy.TYPE_HIERARCHY).get(annotationType); Index: 3rdParty_sources/spring/org/springframework/beans/factory/support/DisposableBeanAdapter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/support/DisposableBeanAdapter.java (.../DisposableBeanAdapter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/support/DisposableBeanAdapter.java (.../DisposableBeanAdapter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -52,6 +52,7 @@ * @author Juergen Hoeller * @author Costin Leau * @author Stephane Nicoll + * @author Sam Brannen * @since 2.0 * @see AbstractBeanFactory * @see org.springframework.beans.factory.DisposableBean @@ -109,12 +110,12 @@ this.beanName = beanName; this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed(); this.invokeDisposableBean = (bean instanceof DisposableBean && - !beanDefinition.isExternallyManagedDestroyMethod(DESTROY_METHOD_NAME)); + !beanDefinition.hasAnyExternallyManagedDestroyMethod(DESTROY_METHOD_NAME)); String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition); if (destroyMethodName != null && !(this.invokeDisposableBean && DESTROY_METHOD_NAME.equals(destroyMethodName)) && - !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) { + !beanDefinition.hasAnyExternallyManagedDestroyMethod(destroyMethodName)) { this.invokeAutoCloseable = (bean instanceof AutoCloseable && CLOSE_METHOD_NAME.equals(destroyMethodName)); if (!this.invokeAutoCloseable) { @@ -138,7 +139,7 @@ beanName + "' has a non-boolean parameter - not supported as destroy method"); } } - destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod); + destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod, bean.getClass()); } this.destroyMethod = destroyMethod; } @@ -252,9 +253,9 @@ invokeCustomDestroyMethod(this.destroyMethod); } else if (this.destroyMethodName != null) { - Method methodToInvoke = determineDestroyMethod(this.destroyMethodName); - if (methodToInvoke != null) { - invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); + Method destroyMethod = determineDestroyMethod(this.destroyMethodName); + if (destroyMethod != null) { + invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(destroyMethod, this.bean.getClass())); } } } Index: 3rdParty_sources/spring/org/springframework/beans/factory/support/ManagedList.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/support/ManagedList.java (.../ManagedList.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/support/ManagedList.java (.../ManagedList.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -17,6 +17,7 @@ package org.springframework.beans.factory.support; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.springframework.beans.BeanMetadataElement; @@ -54,6 +55,20 @@ /** + * Return a new instance containing an arbitrary number of elements. + * @param elements the elements to be contained in the list + * @param the {@code List}'s element type + * @return a {@code List} containing the specified elements + * @since 5.3.16 + */ + @SuppressWarnings("unchecked") + public static ManagedList of(E... elements) { + ManagedList list = new ManagedList<>(); + list.addAll(Arrays.asList(elements)); + return list; + } + + /** * Set the configuration source {@code Object} for this metadata element. *

The exact type of the object will depend on the configuration mechanism used. */ Index: 3rdParty_sources/spring/org/springframework/beans/factory/support/ManagedMap.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/support/ManagedMap.java (.../ManagedMap.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/support/ManagedMap.java (.../ManagedMap.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -18,6 +18,7 @@ import java.util.LinkedHashMap; import java.util.Map; +import java.util.Map.Entry; import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.Mergeable; @@ -57,6 +58,26 @@ /** + * Return a new instance containing keys and values extracted from the + * given entries. The entries themselves are not stored in the map. + * @param entries {@code Map.Entry}s containing the keys and values + * from which the map is populated + * @param the {@code Map}'s key type + * @param the {@code Map}'s value type + * @return a {@code Map} containing the specified mappings + * @since 5.3.16 + */ + @SafeVarargs + @SuppressWarnings("unchecked") + public static ManagedMap ofEntries(Entry... entries) { + ManagedMap map = new ManagedMap<>(); + for (Entry entry : entries) { + map.put(entry.getKey(), entry.getValue()); + } + return map; + } + + /** * Set the configuration source {@code Object} for this metadata element. *

The exact type of the object will depend on the configuration mechanism used. */ Index: 3rdParty_sources/spring/org/springframework/beans/factory/support/ManagedSet.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/support/ManagedSet.java (.../ManagedSet.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/support/ManagedSet.java (.../ManagedSet.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -16,6 +16,7 @@ package org.springframework.beans.factory.support; +import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Set; @@ -53,6 +54,20 @@ /** + * Return a new instance containing an arbitrary number of elements. + * @param elements the elements to be contained in the set + * @param the {@code Set}'s element type + * @return a {@code Set} containing the specified elements + * @since 5.3.16 + */ + @SuppressWarnings("unchecked") + public static ManagedSet of(E... elements) { + ManagedSet set = new ManagedSet<>(); + set.addAll(Arrays.asList(elements)); + return set; + } + + /** * Set the configuration source {@code Object} for this metadata element. *

The exact type of the object will depend on the configuration mechanism used. */ Index: 3rdParty_sources/spring/org/springframework/beans/factory/support/RootBeanDefinition.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/support/RootBeanDefinition.java (.../RootBeanDefinition.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/support/RootBeanDefinition.java (.../RootBeanDefinition.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -49,6 +49,7 @@ * * @author Rod Johnson * @author Juergen Hoeller + * @author Sam Brannen * @see GenericBeanDefinition * @see ChildBeanDefinition */ @@ -436,7 +437,7 @@ } /** - * Check whether the given method or field is an externally managed configuration member. + * Determine if the given method or field is an externally managed configuration member. */ public boolean isExternallyManagedConfigMember(Member configMember) { synchronized (this.postProcessingLock) { @@ -446,7 +447,7 @@ } /** - * Return all externally managed configuration methods and fields (as an immutable Set). + * Get all externally managed configuration methods and fields (as an immutable Set). * @since 5.3.11 */ public Set getExternallyManagedConfigMembers() { @@ -458,7 +459,15 @@ } /** - * Register an externally managed configuration initialization method. + * Register an externally managed configuration initialization method — + * for example, a method annotated with JSR-250's + * {@link javax.annotation.PostConstruct} annotation. + *

The supplied {@code initMethod} may be the + * {@linkplain Method#getName() simple method name} for non-private methods or the + * {@linkplain org.springframework.util.ClassUtils#getQualifiedMethodName(Method) + * qualified method name} for {@code private} methods. A qualified name is + * necessary for {@code private} methods in order to disambiguate between + * multiple private methods with the same name within a class hierarchy. */ public void registerExternallyManagedInitMethod(String initMethod) { synchronized (this.postProcessingLock) { @@ -470,7 +479,10 @@ } /** - * Check whether the given method name indicates an externally managed initialization method. + * Determine if the given method name indicates an externally managed + * initialization method. + *

See {@link #registerExternallyManagedInitMethod} for details + * regarding the format for the supplied {@code initMethod}. */ public boolean isExternallyManagedInitMethod(String initMethod) { synchronized (this.postProcessingLock) { @@ -480,7 +492,39 @@ } /** + * Determine if the given method name indicates an externally managed + * initialization method, regardless of method visibility. + *

In contrast to {@link #isExternallyManagedInitMethod(String)}, this + * method also returns {@code true} if there is a {@code private} externally + * managed initialization method that has been + * {@linkplain #registerExternallyManagedInitMethod(String) registered} + * using a qualified method name instead of a simple method name. + * @since 5.3.17 + */ + boolean hasAnyExternallyManagedInitMethod(String initMethod) { + synchronized (this.postProcessingLock) { + if (isExternallyManagedInitMethod(initMethod)) { + return true; + } + if (this.externallyManagedInitMethods != null) { + for (String candidate : this.externallyManagedInitMethods) { + int indexOfDot = candidate.lastIndexOf('.'); + if (indexOfDot >= 0) { + String methodName = candidate.substring(indexOfDot + 1); + if (methodName.equals(initMethod)) { + return true; + } + } + } + } + return false; + } + } + + /** * Return all externally managed initialization methods (as an immutable Set). + *

See {@link #registerExternallyManagedInitMethod} for details + * regarding the format for the initialization methods in the returned set. * @since 5.3.11 */ public Set getExternallyManagedInitMethods() { @@ -492,7 +536,15 @@ } /** - * Register an externally managed configuration destruction method. + * Register an externally managed configuration destruction method — + * for example, a method annotated with JSR-250's + * {@link javax.annotation.PreDestroy} annotation. + *

The supplied {@code destroyMethod} may be the + * {@linkplain Method#getName() simple method name} for non-private methods or the + * {@linkplain org.springframework.util.ClassUtils#getQualifiedMethodName(Method) + * qualified method name} for {@code private} methods. A qualified name is + * necessary for {@code private} methods in order to disambiguate between + * multiple private methods with the same name within a class hierarchy. */ public void registerExternallyManagedDestroyMethod(String destroyMethod) { synchronized (this.postProcessingLock) { @@ -504,7 +556,10 @@ } /** - * Check whether the given method name indicates an externally managed destruction method. + * Determine if the given method name indicates an externally managed + * destruction method. + *

See {@link #registerExternallyManagedDestroyMethod} for details + * regarding the format for the supplied {@code destroyMethod}. */ public boolean isExternallyManagedDestroyMethod(String destroyMethod) { synchronized (this.postProcessingLock) { @@ -514,7 +569,39 @@ } /** - * Return all externally managed destruction methods (as an immutable Set). + * Determine if the given method name indicates an externally managed + * destruction method, regardless of method visibility. + *

In contrast to {@link #isExternallyManagedDestroyMethod(String)}, this + * method also returns {@code true} if there is a {@code private} externally + * managed destruction method that has been + * {@linkplain #registerExternallyManagedDestroyMethod(String) registered} + * using a qualified method name instead of a simple method name. + * @since 5.3.17 + */ + boolean hasAnyExternallyManagedDestroyMethod(String destroyMethod) { + synchronized (this.postProcessingLock) { + if (isExternallyManagedDestroyMethod(destroyMethod)) { + return true; + } + if (this.externallyManagedDestroyMethods != null) { + for (String candidate : this.externallyManagedDestroyMethods) { + int indexOfDot = candidate.lastIndexOf('.'); + if (indexOfDot >= 0) { + String methodName = candidate.substring(indexOfDot + 1); + if (methodName.equals(destroyMethod)) { + return true; + } + } + } + } + return false; + } + } + + /** + * Get all externally managed destruction methods (as an immutable Set). + *

See {@link #registerExternallyManagedDestroyMethod} for details + * regarding the format for the destruction methods in the returned set. * @since 5.3.11 */ public Set getExternallyManagedDestroyMethods() { Index: 3rdParty_sources/spring/org/springframework/beans/factory/support/StaticListableBeanFactory.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/beans/factory/support/StaticListableBeanFactory.java (.../StaticListableBeanFactory.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/beans/factory/support/StaticListableBeanFactory.java (.../StaticListableBeanFactory.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -459,7 +459,16 @@ public A findAnnotationOnBean(String beanName, Class annotationType) throws NoSuchBeanDefinitionException { - Class beanType = getType(beanName); + return findAnnotationOnBean(beanName, annotationType, true); + } + + @Override + @Nullable + public A findAnnotationOnBean( + String beanName, Class annotationType, boolean allowFactoryBeanInit) + throws NoSuchBeanDefinitionException { + + Class beanType = getType(beanName, allowFactoryBeanInit); return (beanType != null ? AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType) : null); } Index: 3rdParty_sources/spring/org/springframework/cache/annotation/AbstractCachingConfiguration.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/cache/annotation/AbstractCachingConfiguration.java (.../AbstractCachingConfiguration.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/cache/annotation/AbstractCachingConfiguration.java (.../AbstractCachingConfiguration.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -16,9 +16,12 @@ package org.springframework.cache.annotation; -import java.util.Collection; +import java.util.List; +import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collectors; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.CacheManager; import org.springframework.cache.interceptor.CacheErrorHandler; @@ -30,6 +33,7 @@ import org.springframework.core.type.AnnotationMetadata; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; +import org.springframework.util.function.SingletonSupplier; /** * Abstract base {@code @Configuration} class providing common structure @@ -63,36 +67,67 @@ @Override public void setImportMetadata(AnnotationMetadata importMetadata) { this.enableCaching = AnnotationAttributes.fromMap( - importMetadata.getAnnotationAttributes(EnableCaching.class.getName(), false)); + importMetadata.getAnnotationAttributes(EnableCaching.class.getName())); if (this.enableCaching == null) { throw new IllegalArgumentException( "@EnableCaching is not present on importing class " + importMetadata.getClassName()); } } - @Autowired(required = false) - void setConfigurers(Collection configurers) { - if (CollectionUtils.isEmpty(configurers)) { - return; - } - if (configurers.size() > 1) { - throw new IllegalStateException(configurers.size() + " implementations of " + - "CachingConfigurer were found when only 1 was expected. " + - "Refactor the configuration such that CachingConfigurer is " + - "implemented only once or not at all."); - } - CachingConfigurer configurer = configurers.iterator().next(); - useCachingConfigurer(configurer); + @Autowired + void setConfigurers(ObjectProvider configurers) { + Supplier configurer = () -> { + List candidates = configurers.stream().collect(Collectors.toList()); + if (CollectionUtils.isEmpty(candidates)) { + return null; + } + if (candidates.size() > 1) { + throw new IllegalStateException(candidates.size() + " implementations of " + + "CachingConfigurer were found when only 1 was expected. " + + "Refactor the configuration such that CachingConfigurer is " + + "implemented only once or not at all."); + } + return candidates.get(0); + }; + useCachingConfigurer(new CachingConfigurerSupplier(configurer)); } /** * Extract the configuration from the nominated {@link CachingConfigurer}. */ - protected void useCachingConfigurer(CachingConfigurer config) { - this.cacheManager = config::cacheManager; - this.cacheResolver = config::cacheResolver; - this.keyGenerator = config::keyGenerator; - this.errorHandler = config::errorHandler; + protected void useCachingConfigurer(CachingConfigurerSupplier cachingConfigurerSupplier) { + this.cacheManager = cachingConfigurerSupplier.adapt(CachingConfigurer::cacheManager); + this.cacheResolver = cachingConfigurerSupplier.adapt(CachingConfigurer::cacheResolver); + this.keyGenerator = cachingConfigurerSupplier.adapt(CachingConfigurer::keyGenerator); + this.errorHandler = cachingConfigurerSupplier.adapt(CachingConfigurer::errorHandler); } + + protected static class CachingConfigurerSupplier { + + private final Supplier supplier; + + public CachingConfigurerSupplier(Supplier supplier) { + this.supplier = SingletonSupplier.of(supplier); + } + + /** + * Adapt the {@link CachingConfigurer} supplier to another supplier + * provided by the specified mapping function. If the underlying + * {@link CachingConfigurer} is {@code null}, {@code null} is returned + * and the mapping function is not invoked. + * @param provider the provider to use to adapt the supplier + * @param the type of the supplier + * @return another supplier mapped by the specified function + */ + @Nullable + public Supplier adapt(Function provider) { + return () -> { + CachingConfigurer cachingConfigurer = this.supplier.get(); + return (cachingConfigurer != null ? provider.apply(cachingConfigurer) : null); + }; + } + + } + } Index: 3rdParty_sources/spring/org/springframework/cache/annotation/CachingConfigurer.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/cache/annotation/CachingConfigurer.java (.../CachingConfigurer.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/cache/annotation/CachingConfigurer.java (.../CachingConfigurer.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -26,8 +26,7 @@ * Interface to be implemented by @{@link org.springframework.context.annotation.Configuration * Configuration} classes annotated with @{@link EnableCaching} that wish or need to * specify explicitly how caches are resolved and how keys are generated for annotation-driven - * cache management. Consider extending {@link CachingConfigurerSupport}, which provides a - * stub implementation of all interface methods. + * cache management. * *

See @{@link EnableCaching} for general examples and context; see * {@link #cacheManager()}, {@link #cacheResolver()} and {@link #keyGenerator()} @@ -37,7 +36,6 @@ * @author Stephane Nicoll * @since 3.1 * @see EnableCaching - * @see CachingConfigurerSupport */ public interface CachingConfigurer { @@ -64,7 +62,9 @@ * See @{@link EnableCaching} for more complete examples. */ @Nullable - CacheManager cacheManager(); + default CacheManager cacheManager() { + return null; + } /** * Return the {@link CacheResolver} bean to use to resolve regular caches for @@ -89,7 +89,9 @@ * See {@link EnableCaching} for more complete examples. */ @Nullable - CacheResolver cacheResolver(); + default CacheResolver cacheResolver() { + return null; + } /** * Return the key generator bean to use for annotation-driven cache management. @@ -110,7 +112,9 @@ * See @{@link EnableCaching} for more complete examples. */ @Nullable - KeyGenerator keyGenerator(); + default KeyGenerator keyGenerator() { + return null; + } /** * Return the {@link CacheErrorHandler} to use to handle cache-related errors. @@ -133,6 +137,8 @@ * See @{@link EnableCaching} for more complete examples. */ @Nullable - CacheErrorHandler errorHandler(); + default CacheErrorHandler errorHandler() { + return null; + } } Index: 3rdParty_sources/spring/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java (.../AbstractFallbackCacheOperationSource.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java (.../AbstractFallbackCacheOperationSource.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -124,7 +124,7 @@ @Nullable private Collection computeCacheOperations(Method method, @Nullable Class targetClass) { - // Don't allow no-public methods as required. + // Don't allow non-public methods, as configured. if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } Index: 3rdParty_sources/spring/org/springframework/cache/interceptor/LoggingCacheErrorHandler.java =================================================================== diff -u --- 3rdParty_sources/spring/org/springframework/cache/interceptor/LoggingCacheErrorHandler.java (revision 0) +++ 3rdParty_sources/spring/org/springframework/cache/interceptor/LoggingCacheErrorHandler.java (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -0,0 +1,105 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.cache.interceptor; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.cache.Cache; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * A {@link CacheErrorHandler} implementation that logs error message. Can be + * used when underlying cache errors should be ignored. + * + * @author Adam Ostrožlík + * @author Stephane Nicoll + * @since 5.3.16 + */ +public class LoggingCacheErrorHandler implements CacheErrorHandler { + + private final Log logger; + + private final boolean logStacktrace; + + + /** + * Create an instance with the {@link Log logger} to use. + * @param logger the logger to use + * @param logStacktrace whether to log stack trace + */ + public LoggingCacheErrorHandler(Log logger, boolean logStacktrace) { + Assert.notNull(logger, "Logger must not be null"); + this.logger = logger; + this.logStacktrace = logStacktrace; + } + + /** + * Create an instance that does not log stack traces. + */ + public LoggingCacheErrorHandler() { + this(LogFactory.getLog(LoggingCacheErrorHandler.class), false); + } + + + @Override + public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) { + logCacheError(logger, + createMessage(cache, "failed to get entry with key '" + key + "'"), + exception); + } + + @Override + public void handleCachePutError(RuntimeException exception, Cache cache, Object key, @Nullable Object value) { + logCacheError(logger, + createMessage(cache, "failed to put entry with key '" + key + "'"), + exception); + } + + @Override + public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) { + logCacheError(logger, + createMessage(cache, "failed to evict entry with key '" + key + "'"), + exception); + } + + @Override + public void handleCacheClearError(RuntimeException exception, Cache cache) { + logCacheError(logger, createMessage(cache, "failed to clear entries"), exception); + } + + /** + * Log the specified message. + * @param logger the logger + * @param message the message + * @param ex the exception + */ + protected void logCacheError(Log logger, String message, RuntimeException ex) { + if (this.logStacktrace) { + logger.warn(message, ex); + } + else { + logger.warn(message); + } + } + + private String createMessage(Cache cache, String reason) { + return String.format("Cache '%s' %s", cache.getName(), reason); + } + +} Index: 3rdParty_sources/spring/org/springframework/cache/jcache/config/AbstractJCacheConfiguration.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/cache/jcache/config/AbstractJCacheConfiguration.java (.../AbstractJCacheConfiguration.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/cache/jcache/config/AbstractJCacheConfiguration.java (.../AbstractJCacheConfiguration.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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,7 +20,6 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.cache.annotation.AbstractCachingConfiguration; -import org.springframework.cache.annotation.CachingConfigurer; import org.springframework.cache.interceptor.CacheResolver; import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource; import org.springframework.cache.jcache.interceptor.JCacheOperationSource; @@ -46,11 +45,14 @@ @Override - protected void useCachingConfigurer(CachingConfigurer config) { - super.useCachingConfigurer(config); - if (config instanceof JCacheConfigurer) { - this.exceptionCacheResolver = ((JCacheConfigurer) config)::exceptionCacheResolver; - } + protected void useCachingConfigurer(CachingConfigurerSupplier cachingConfigurerSupplier) { + super.useCachingConfigurer(cachingConfigurerSupplier); + this.exceptionCacheResolver = cachingConfigurerSupplier.adapt(config -> { + if (config instanceof JCacheConfigurer) { + return ((JCacheConfigurer) config).exceptionCacheResolver(); + } + return null; + }); } @Bean(name = "jCacheOperationSource") Index: 3rdParty_sources/spring/org/springframework/cache/jcache/config/JCacheConfigurer.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/cache/jcache/config/JCacheConfigurer.java (.../JCacheConfigurer.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/cache/jcache/config/JCacheConfigurer.java (.../JCacheConfigurer.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -26,8 +26,7 @@ *

To be implemented by classes annotated with * {@link org.springframework.cache.annotation.EnableCaching} that wish * or need to specify explicitly how exception caches are resolved for - * annotation-driven cache management. Consider extending {@link JCacheConfigurerSupport}, - * which provides a stub implementation of all interface methods. + * annotation-driven cache management. * *

See {@link org.springframework.cache.annotation.EnableCaching} for * general examples and context; see {@link #exceptionCacheResolver()} for @@ -36,7 +35,6 @@ * @author Stephane Nicoll * @since 4.1 * @see CachingConfigurer - * @see JCacheConfigurerSupport * @see org.springframework.cache.annotation.EnableCaching */ public interface JCacheConfigurer extends CachingConfigurer { @@ -60,6 +58,8 @@ * See {@link org.springframework.cache.annotation.EnableCaching} for more complete examples. */ @Nullable - CacheResolver exceptionCacheResolver(); + default CacheResolver exceptionCacheResolver() { + return null; + } } Index: 3rdParty_sources/spring/org/springframework/cache/jcache/interceptor/AbstractFallbackJCacheOperationSource.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/cache/jcache/interceptor/AbstractFallbackJCacheOperationSource.java (.../AbstractFallbackJCacheOperationSource.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/cache/jcache/interceptor/AbstractFallbackJCacheOperationSource.java (.../AbstractFallbackJCacheOperationSource.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -79,7 +79,7 @@ @Nullable private JCacheOperation computeCacheOperation(Method method, @Nullable Class targetClass) { - // Don't allow no-public methods as required. + // Don't allow non-public methods, as configured. if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } Index: 3rdParty_sources/spring/org/springframework/cglib/beans/BeanMap.java =================================================================== diff -u --- 3rdParty_sources/spring/org/springframework/cglib/beans/BeanMap.java (revision 0) +++ 3rdParty_sources/spring/org/springframework/cglib/beans/BeanMap.java (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -0,0 +1,331 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 + * + * https://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.cglib.beans; + +import java.security.ProtectionDomain; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.springframework.asm.ClassVisitor; +import org.springframework.cglib.core.AbstractClassGenerator; +import org.springframework.cglib.core.KeyFactory; +import org.springframework.cglib.core.ReflectUtils; + +/** + * A Map-based view of a JavaBean. The default set of keys is the + * union of all property names (getters or setters). An attempt to set + * a read-only property will be ignored, and write-only properties will + * be returned as null. Removal of objects is not a + * supported (the key set is fixed). + * @author Chris Nokleberg + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +abstract public class BeanMap implements Map { + /** + * Limit the properties reflected in the key set of the map + * to readable properties. + * @see BeanMap.Generator#setRequire + */ + public static final int REQUIRE_GETTER = 1; + + /** + * Limit the properties reflected in the key set of the map + * to writable properties. + * @see BeanMap.Generator#setRequire + */ + public static final int REQUIRE_SETTER = 2; + + /** + * Helper method to create a new BeanMap. For finer + * control over the generated instance, use a new instance of + * BeanMap.Generator instead of this static method. + * @param bean the JavaBean underlying the map + * @return a new BeanMap instance + */ + public static BeanMap create(Object bean) { + Generator gen = new Generator(); + gen.setBean(bean); + return gen.create(); + } + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(BeanMap.class.getName()); + + private static final BeanMapKey KEY_FACTORY = + (BeanMapKey)KeyFactory.create(BeanMapKey.class, KeyFactory.CLASS_BY_NAME); + + interface BeanMapKey { + public Object newInstance(Class type, int require); + } + + private Object bean; + private Class beanClass; + private int require; + + public Generator() { + super(SOURCE); + } + + /** + * Set the bean that the generated map should reflect. The bean may be swapped + * out for another bean of the same type using {@link #setBean}. + * Calling this method overrides any value previously set using {@link #setBeanClass}. + * You must call either this method or {@link #setBeanClass} before {@link #create}. + * @param bean the initial bean + */ + public void setBean(Object bean) { + this.bean = bean; + if (bean != null) { + beanClass = bean.getClass(); + setContextClass(beanClass); + } + } + + /** + * Set the class of the bean that the generated map should support. + * You must call either this method or {@link #setBeanClass} before {@link #create}. + * @param beanClass the class of the bean + */ + public void setBeanClass(Class beanClass) { + this.beanClass = beanClass; + } + + /** + * Limit the properties reflected by the generated map. + * @param require any combination of {@link #REQUIRE_GETTER} and + * {@link #REQUIRE_SETTER}; default is zero (any property allowed) + */ + public void setRequire(int require) { + this.require = require; + } + + protected ClassLoader getDefaultClassLoader() { + return beanClass.getClassLoader(); + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(beanClass); + } + + /** + * Create a new instance of the BeanMap. An existing + * generated class will be reused if possible. + */ + public BeanMap create() { + if (beanClass == null) + throw new IllegalArgumentException("Class of bean unknown"); + setNamePrefix(beanClass.getName()); + return (BeanMap)super.create(KEY_FACTORY.newInstance(beanClass, require)); + } + + public void generateClass(ClassVisitor v) throws Exception { + new BeanMapEmitter(v, getClassName(), beanClass, require); + } + + protected Object firstInstance(Class type) { + return ((BeanMap)ReflectUtils.newInstance(type)).newInstance(bean); + } + + protected Object nextInstance(Object instance) { + return ((BeanMap)instance).newInstance(bean); + } + } + + /** + * Create a new BeanMap instance using the specified bean. + * This is faster than using the {@link #create} static method. + * @param bean the JavaBean underlying the map + * @return a new BeanMap instance + */ + abstract public BeanMap newInstance(Object bean); + + /** + * Get the type of a property. + * @param name the name of the JavaBean property + * @return the type of the property, or null if the property does not exist + */ + abstract public Class getPropertyType(String name); + + protected Object bean; + + protected BeanMap() { + } + + protected BeanMap(Object bean) { + setBean(bean); + } + + public Object get(Object key) { + return get(bean, key); + } + + public Object put(Object key, Object value) { + return put(bean, key, value); + } + + /** + * Get the property of a bean. This allows a BeanMap + * to be used statically for multiple beans--the bean instance tied to the + * map is ignored and the bean passed to this method is used instead. + * @param bean the bean to query; must be compatible with the type of + * this BeanMap + * @param key must be a String + * @return the current value, or null if there is no matching property + */ + abstract public Object get(Object bean, Object key); + + /** + * Set the property of a bean. This allows a BeanMap + * to be used statically for multiple beans--the bean instance tied to the + * map is ignored and the bean passed to this method is used instead. + * @param key must be a String + * @return the old value, if there was one, or null + */ + abstract public Object put(Object bean, Object key, Object value); + + /** + * Change the underlying bean this map should use. + * @param bean the new JavaBean + * @see #getBean + */ + public void setBean(Object bean) { + this.bean = bean; + } + + /** + * Return the bean currently in use by this map. + * @return the current JavaBean + * @see #setBean + */ + public Object getBean() { + return bean; + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public boolean containsKey(Object key) { + return keySet().contains(key); + } + + public boolean containsValue(Object value) { + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object v = get(it.next()); + if (((value == null) && (v == null)) || (value != null && value.equals(v))) + return true; + } + return false; + } + + public int size() { + return keySet().size(); + } + + public boolean isEmpty() { + return size() == 0; + } + + public Object remove(Object key) { + throw new UnsupportedOperationException(); + } + + public void putAll(Map t) { + for (Iterator it = t.keySet().iterator(); it.hasNext();) { + Object key = it.next(); + put(key, t.get(key)); + } + } + + public boolean equals(Object o) { + if (o == null || !(o instanceof Map)) { + return false; + } + Map other = (Map)o; + if (size() != other.size()) { + return false; + } + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object key = it.next(); + if (!other.containsKey(key)) { + return false; + } + Object v1 = get(key); + Object v2 = other.get(key); + if (!((v1 == null) ? v2 == null : v1.equals(v2))) { + return false; + } + } + return true; + } + + public int hashCode() { + int code = 0; + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object key = it.next(); + Object value = get(key); + code += ((key == null) ? 0 : key.hashCode()) ^ + ((value == null) ? 0 : value.hashCode()); + } + return code; + } + + // TODO: optimize + public Set entrySet() { + HashMap copy = new HashMap(); + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object key = it.next(); + copy.put(key, get(key)); + } + return Collections.unmodifiableMap(copy).entrySet(); + } + + public Collection values() { + Set keys = keySet(); + List values = new ArrayList(keys.size()); + for (Iterator it = keys.iterator(); it.hasNext();) { + values.add(get(it.next())); + } + return Collections.unmodifiableCollection(values); + } + + /* + * @see java.util.AbstractMap#toString + */ + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append('{'); + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object key = it.next(); + sb.append(key); + sb.append('='); + sb.append(get(key)); + if (it.hasNext()) { + sb.append(", "); + } + } + sb.append('}'); + return sb.toString(); + } +} Index: 3rdParty_sources/spring/org/springframework/cglib/beans/package-info.java =================================================================== diff -u --- 3rdParty_sources/spring/org/springframework/cglib/beans/package-info.java (revision 0) +++ 3rdParty_sources/spring/org/springframework/cglib/beans/package-info.java (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -0,0 +1,10 @@ +/** + * Spring's repackaging of the + * CGLIB beans package + * (for internal use only). + * + *

As this repackaging happens at the class file level, sources + * and javadocs are not available here... except for a few files + * that have been patched for Spring's purposes on JDK 9-17. + */ +package org.springframework.cglib.beans; Index: 3rdParty_sources/spring/org/springframework/cglib/core/package-info.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/cglib/core/package-info.java (.../package-info.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/cglib/core/package-info.java (.../package-info.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -5,6 +5,6 @@ * *

As this repackaging happens at the class file level, sources * and javadocs are not available here... except for a few files - * that have been patched for Spring's purposes on JDK 9/10/11. + * that have been patched for Spring's purposes on JDK 9-17. */ package org.springframework.cglib.core; Index: 3rdParty_sources/spring/org/springframework/cglib/proxy/package-info.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/cglib/proxy/package-info.java (.../package-info.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/cglib/proxy/package-info.java (.../package-info.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -5,6 +5,6 @@ * *

As this repackaging happens at the class file level, sources * and javadocs are not available here... except for a few files - * that have been patched for Spring's purposes on JDK 9/10/11. + * that have been patched for Spring's purposes on JDK 9-17. */ package org.springframework.cglib.proxy; Index: 3rdParty_sources/spring/org/springframework/context/annotation/AnnotationBeanNameGenerator.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/context/annotation/AnnotationBeanNameGenerator.java (.../AnnotationBeanNameGenerator.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/context/annotation/AnnotationBeanNameGenerator.java (.../AnnotationBeanNameGenerator.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -47,9 +47,10 @@ * *

If the annotation's value doesn't indicate a bean name, an appropriate * name will be built based on the short name of the class (with the first - * letter lower-cased). For example: + * letter lower-cased), unless the two first letters are uppercase. For example: * *

com.xyz.FooServiceImpl -> fooServiceImpl
+ *
com.xyz.URLFooServiceImpl -> URLFooServiceImpl
* * @author Juergen Hoeller * @author Mark Fisher Index: 3rdParty_sources/spring/org/springframework/context/annotation/AnnotationConfigUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/context/annotation/AnnotationConfigUtils.java (.../AnnotationConfigUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/context/annotation/AnnotationConfigUtils.java (.../AnnotationConfigUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -282,7 +282,7 @@ @Nullable static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annotationClassName) { - return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false)); + return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName)); } static Set attributesForRepeatable(AnnotationMetadata metadata, @@ -298,10 +298,10 @@ Set result = new LinkedHashSet<>(); // Direct annotation present? - addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false)); + addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName)); // Container annotation present? - Map container = metadata.getAnnotationAttributes(containerClassName, false); + Map container = metadata.getAnnotationAttributes(containerClassName); if (container != null && container.containsKey("value")) { for (Map containedAttributes : (Map[]) container.get("value")) { addAttributesIfNotNull(result, containedAttributes); Index: 3rdParty_sources/spring/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java (.../CommonAnnotationBeanPostProcessor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java (.../CommonAnnotationBeanPostProcessor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -105,7 +105,7 @@ * *

The common annotations supported by this post-processor are available in * Java 6 (JDK 1.6) as well as in Java EE 5/6 (which provides a standalone jar for - * its common annotations as well, allowing for use in any Java 5 based application). + * its common annotations as well, allowing for use in any based application). * *

For default usage, resolving resource names as Spring bean names, * simply define the following in your application context: Index: 3rdParty_sources/spring/org/springframework/context/expression/StandardBeanExpressionResolver.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/context/expression/StandardBeanExpressionResolver.java (.../StandardBeanExpressionResolver.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/context/expression/StandardBeanExpressionResolver.java (.../StandardBeanExpressionResolver.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -138,7 +138,7 @@ @Override @Nullable - public Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException { + public Object evaluate(@Nullable String value, BeanExpressionContext beanExpressionContext) throws BeansException { if (!StringUtils.hasLength(value)) { return value; } @@ -148,21 +148,21 @@ expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext); this.expressionCache.put(value, expr); } - StandardEvaluationContext sec = this.evaluationCache.get(evalContext); + StandardEvaluationContext sec = this.evaluationCache.get(beanExpressionContext); if (sec == null) { - sec = new StandardEvaluationContext(evalContext); + sec = new StandardEvaluationContext(beanExpressionContext); sec.addPropertyAccessor(new BeanExpressionContextAccessor()); sec.addPropertyAccessor(new BeanFactoryAccessor()); sec.addPropertyAccessor(new MapAccessor()); sec.addPropertyAccessor(new EnvironmentAccessor()); - sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory())); - sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader())); + sec.setBeanResolver(new BeanFactoryResolver(beanExpressionContext.getBeanFactory())); + sec.setTypeLocator(new StandardTypeLocator(beanExpressionContext.getBeanFactory().getBeanClassLoader())); sec.setTypeConverter(new StandardTypeConverter(() -> { - ConversionService cs = evalContext.getBeanFactory().getConversionService(); + ConversionService cs = beanExpressionContext.getBeanFactory().getConversionService(); return (cs != null ? cs : DefaultConversionService.getSharedInstance()); })); customizeEvaluationContext(sec); - this.evaluationCache.put(evalContext, sec); + this.evaluationCache.put(beanExpressionContext, sec); } return expr.getValue(sec); } Index: 3rdParty_sources/spring/org/springframework/context/support/AbstractApplicationContext.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/context/support/AbstractApplicationContext.java (.../AbstractApplicationContext.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/context/support/AbstractApplicationContext.java (.../AbstractApplicationContext.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1331,7 +1331,17 @@ return getBeanFactory().findAnnotationOnBean(beanName, annotationType); } + @Override + @Nullable + public A findAnnotationOnBean( + String beanName, Class annotationType, boolean allowFactoryBeanInit) + throws NoSuchBeanDefinitionException { + assertBeanFactoryActive(); + return getBeanFactory().findAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit); + } + + //--------------------------------------------------------------------- // Implementation of HierarchicalBeanFactory interface //--------------------------------------------------------------------- Index: 3rdParty_sources/spring/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java (.../PropertySourcesPlaceholderConfigurer.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java (.../PropertySourcesPlaceholderConfigurer.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -24,10 +24,12 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.PlaceholderConfigurerSupport; import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurablePropertyResolver; import org.springframework.core.env.Environment; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertiesPropertySource; +import org.springframework.core.env.PropertyResolver; import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySources; import org.springframework.core.env.PropertySourcesPropertyResolver; @@ -57,6 +59,7 @@ * * @author Chris Beams * @author Juergen Hoeller + * @author Sam Brannen * @since 3.1 * @see org.springframework.core.env.ConfigurableEnvironment * @see org.springframework.beans.factory.config.PlaceholderConfigurerSupport @@ -129,12 +132,25 @@ if (this.propertySources == null) { this.propertySources = new MutablePropertySources(); if (this.environment != null) { + PropertyResolver propertyResolver = this.environment; + // If the ignoreUnresolvablePlaceholders flag is set to true, we have to create a + // local PropertyResolver to enforce that setting, since the Environment is most + // likely not configured with ignoreUnresolvablePlaceholders set to true. + // See https://github.com/spring-projects/spring-framework/issues/27947 + if (this.ignoreUnresolvablePlaceholders && (this.environment instanceof ConfigurableEnvironment)) { + ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) this.environment; + PropertySourcesPropertyResolver resolver = + new PropertySourcesPropertyResolver(configurableEnvironment.getPropertySources()); + resolver.setIgnoreUnresolvableNestedPlaceholders(true); + propertyResolver = resolver; + } + PropertyResolver propertyResolverToUse = propertyResolver; this.propertySources.addLast( new PropertySource(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) { @Override @Nullable public String getProperty(String key) { - return this.source.getProperty(key); + return propertyResolverToUse.getProperty(key); } } ); Index: 3rdParty_sources/spring/org/springframework/core/CoroutinesUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/CoroutinesUtils.java (.../CoroutinesUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/CoroutinesUtils.java (.../CoroutinesUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -25,6 +25,7 @@ import kotlin.reflect.KClassifier; import kotlin.reflect.KFunction; import kotlin.reflect.full.KCallables; +import kotlin.reflect.jvm.KCallablesJvm; import kotlin.reflect.jvm.ReflectJvmMapping; import kotlinx.coroutines.BuildersKt; import kotlinx.coroutines.CoroutineStart; @@ -70,6 +71,9 @@ */ public static Publisher invokeSuspendingFunction(Method method, Object target, Object... args) { KFunction function = Objects.requireNonNull(ReflectJvmMapping.getKotlinFunction(method)); + if (method.isAccessible() && !KCallablesJvm.isAccessible(function)) { + KCallablesJvm.setAccessible(function, true); + } KClassifier classifier = function.getReturnType().getClassifier(); Mono mono = MonoKt.mono(Dispatchers.getUnconfined(), (scope, continuation) -> KCallables.callSuspend(function, getSuspendedFunctionArgs(target, args), continuation)) Index: 3rdParty_sources/spring/org/springframework/core/LocalVariableTableParameterNameDiscoverer.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/LocalVariableTableParameterNameDiscoverer.java (.../LocalVariableTableParameterNameDiscoverer.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/LocalVariableTableParameterNameDiscoverer.java (.../LocalVariableTableParameterNameDiscoverer.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -101,6 +101,8 @@ } return NO_DEBUG_INFO_MAP; } + // We cannot use try-with-resources here for the InputStream, since we have + // custom handling of the close() method in a finally-block. try { ClassReader classReader = new ClassReader(is); Map map = new ConcurrentHashMap<>(32); Index: 3rdParty_sources/spring/org/springframework/core/NestedIOException.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/NestedIOException.java (.../NestedIOException.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/NestedIOException.java (.../NestedIOException.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -24,8 +24,9 @@ * Subclass of {@link IOException} that properly handles a root cause, * exposing the root cause just like NestedChecked/RuntimeException does. * - *

Proper root cause handling has not been added to standard IOException before - * Java 6, which is why we need to do it ourselves for Java 5 compatibility purposes. + *

Proper root cause handling was added to the standard {@code IOException} in + * Java 6, which is why Spring originally introduced {@code NestedIOException} + * for compatibility with versions prior to Java 6. * *

The similarity between this class and the NestedChecked/RuntimeException * class is unavoidable, as this class needs to derive from IOException. Index: 3rdParty_sources/spring/org/springframework/core/ResolvableType.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/ResolvableType.java (.../ResolvableType.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/ResolvableType.java (.../ResolvableType.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -48,11 +48,11 @@ * {@link #getGeneric(int...) generic parameters} along with the ability to ultimately * {@link #resolve() resolve} to a {@link java.lang.Class}. * - *

{@code ResolvableTypes} may be obtained from {@link #forField(Field) fields}, - * {@link #forMethodParameter(Method, int) method parameters}, - * {@link #forMethodReturnType(Method) method returns} or - * {@link #forClass(Class) classes}. Most methods on this class will themselves return - * {@link ResolvableType ResolvableTypes}, allowing easy navigation. For example: + *

A {@code ResolvableType} may be obtained from a {@linkplain #forField(Field) field}, + * a {@linkplain #forMethodParameter(Method, int) method parameter}, + * a {@linkplain #forMethodReturnType(Method) method return type}, or a + * {@linkplain #forClass(Class) class}. Most methods on this class will themselves return + * a {@code ResolvableType}, allowing for easy navigation. For example: *

  * private HashMap<Integer, List<String>> myMap;
  *
@@ -182,7 +182,7 @@
 
 	/**
 	 * Private constructor used to create a new {@link ResolvableType} on a {@link Class} basis.
-	 * Avoids all {@code instanceof} checks in order to create a straight {@link Class} wrapper.
+	 * 

Avoids all {@code instanceof} checks in order to create a straight {@link Class} wrapper. * @since 4.2 */ private ResolvableType(@Nullable Class clazz) { @@ -406,7 +406,7 @@ /** * Convenience method to return this type as a resolvable {@link Collection} type. - * Returns {@link #NONE} if this type does not implement or extend + *

Returns {@link #NONE} if this type does not implement or extend * {@link Collection}. * @see #as(Class) * @see #asMap() @@ -417,7 +417,7 @@ /** * Convenience method to return this type as a resolvable {@link Map} type. - * Returns {@link #NONE} if this type does not implement or extend + *

Returns {@link #NONE} if this type does not implement or extend * {@link Map}. * @see #as(Class) * @see #asCollection() @@ -458,7 +458,7 @@ /** * Return a {@link ResolvableType} representing the direct supertype of this type. - * If no supertype is available this method returns {@link #NONE}. + *

If no supertype is available this method returns {@link #NONE}. *

Note: The resulting {@link ResolvableType} instance may not be {@link Serializable}. * @see #getInterfaces() */ @@ -608,7 +608,7 @@ /** * Return a {@link ResolvableType} for the specified nesting level. - * See {@link #getNested(int, Map)} for details. + *

See {@link #getNested(int, Map)} for details. * @param nestingLevel the nesting level * @return the {@link ResolvableType} type, or {@code #NONE} */ @@ -999,7 +999,7 @@ /** * Return a {@link ResolvableType} for the specified {@link Class}, * using the full generic type information for assignability checks. - * For example: {@code ResolvableType.forClass(MyArrayList.class)}. + *

For example: {@code ResolvableType.forClass(MyArrayList.class)}. * @param clazz the class to introspect ({@code null} is semantically * equivalent to {@code Object.class} for typical use cases here) * @return a {@link ResolvableType} for the specified class @@ -1014,7 +1014,7 @@ * Return a {@link ResolvableType} for the specified {@link Class}, * doing assignability checks against the raw class only (analogous to * {@link Class#isAssignableFrom}, which this serves as a wrapper for. - * For example: {@code ResolvableType.forRawClass(List.class)}. + *

For example: {@code ResolvableType.forRawClass(List.class)}. * @param clazz the class to introspect ({@code null} is semantically * equivalent to {@code Object.class} for typical use cases here) * @return a {@link ResolvableType} for the specified class @@ -1043,7 +1043,7 @@ /** * Return a {@link ResolvableType} for the specified base type * (interface or base class) with a given implementation class. - * For example: {@code ResolvableType.forClass(List.class, MyArrayList.class)}. + *

For example: {@code ResolvableType.forClass(List.class, MyArrayList.class)}. * @param baseType the base type (must not be {@code null}) * @param implementationClass the implementation class * @return a {@link ResolvableType} for the specified base type backed by the @@ -1085,7 +1085,7 @@ 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"); + 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++) { @@ -1238,7 +1238,7 @@ /** * Return a {@link ResolvableType} for the specified {@link Method} return type. - * Use this variant when the class that declares the method includes generic + *

Use this variant when the class that declares the method includes generic * parameter variables that are satisfied by the implementation class. * @param method the source for the method return type * @param implementationClass the implementation class Index: 3rdParty_sources/spring/org/springframework/core/SimpleAliasRegistry.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/SimpleAliasRegistry.java (.../SimpleAliasRegistry.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/SimpleAliasRegistry.java (.../SimpleAliasRegistry.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -32,6 +32,7 @@ /** * Simple implementation of the {@link AliasRegistry} interface. + * *

Serves as base class for * {@link org.springframework.beans.factory.support.BeanDefinitionRegistry} * implementations. @@ -101,8 +102,8 @@ */ public boolean hasAlias(String name, String alias) { String registeredName = this.aliasMap.get(alias); - return ObjectUtils.nullSafeEquals(registeredName, name) || (registeredName != null - && hasAlias(name, registeredName)); + return ObjectUtils.nullSafeEquals(registeredName, name) || + (registeredName != null && hasAlias(name, registeredName)); } @Override Index: 3rdParty_sources/spring/org/springframework/core/annotation/AnnotationTypeMapping.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/annotation/AnnotationTypeMapping.java (.../AnnotationTypeMapping.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/annotation/AnnotationTypeMapping.java (.../AnnotationTypeMapping.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -82,8 +82,8 @@ private final Set claimedAliases = new HashSet<>(); - AnnotationTypeMapping(@Nullable AnnotationTypeMapping source, - Class annotationType, @Nullable Annotation annotation) { + AnnotationTypeMapping(@Nullable AnnotationTypeMapping source, Class annotationType, + @Nullable Annotation annotation, Set> visitedAnnotationTypes) { this.source = source; this.root = (source != null ? source.getRoot() : this); @@ -103,7 +103,7 @@ processAliases(); addConventionMappings(); addConventionAnnotationValues(); - this.synthesizable = computeSynthesizableFlag(); + this.synthesizable = computeSynthesizableFlag(visitedAnnotationTypes); } @@ -311,7 +311,10 @@ } @SuppressWarnings("unchecked") - private boolean computeSynthesizableFlag() { + private boolean computeSynthesizableFlag(Set> visitedAnnotationTypes) { + // Track that we have visited the current annotation type. + visitedAnnotationTypes.add(this.annotationType); + // Uses @AliasFor for local aliases? for (int index : this.aliasMappings) { if (index != -1) { @@ -340,9 +343,15 @@ if (type.isAnnotation() || (type.isArray() && type.getComponentType().isAnnotation())) { Class annotationType = (Class) (type.isAnnotation() ? type : type.getComponentType()); - AnnotationTypeMapping mapping = AnnotationTypeMappings.forAnnotationType(annotationType).get(0); - if (mapping.isSynthesizable()) { - return true; + // Ensure we have not yet visited the current nested annotation type, in order + // to avoid infinite recursion for JVM languages other than Java that support + // recursive annotation definitions. + if (visitedAnnotationTypes.add(annotationType)) { + AnnotationTypeMapping mapping = + AnnotationTypeMappings.forAnnotationType(annotationType, visitedAnnotationTypes).get(0); + if (mapping.isSynthesizable()) { + return true; + } } } } Index: 3rdParty_sources/spring/org/springframework/core/annotation/AnnotationTypeMappings.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/annotation/AnnotationTypeMappings.java (.../AnnotationTypeMappings.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/annotation/AnnotationTypeMappings.java (.../AnnotationTypeMappings.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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,8 +20,10 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.springframework.lang.Nullable; import org.springframework.util.ConcurrentReferenceHashMap; @@ -40,6 +42,7 @@ * be searched once, regardless of how many times they are actually used. * * @author Phillip Webb + * @author Sam Brannen * @since 5.2 * @see AnnotationTypeMapping */ @@ -60,19 +63,22 @@ private AnnotationTypeMappings(RepeatableContainers repeatableContainers, - AnnotationFilter filter, Class annotationType) { + AnnotationFilter filter, Class annotationType, + Set> visitedAnnotationTypes) { this.repeatableContainers = repeatableContainers; this.filter = filter; this.mappings = new ArrayList<>(); - addAllMappings(annotationType); + addAllMappings(annotationType, visitedAnnotationTypes); this.mappings.forEach(AnnotationTypeMapping::afterAllMappingsSet); } - private void addAllMappings(Class annotationType) { + private void addAllMappings(Class annotationType, + Set> visitedAnnotationTypes) { + Deque queue = new ArrayDeque<>(); - addIfPossible(queue, null, annotationType, null); + addIfPossible(queue, null, annotationType, null, visitedAnnotationTypes); while (!queue.isEmpty()) { AnnotationTypeMapping mapping = queue.removeFirst(); this.mappings.add(mapping); @@ -102,14 +108,15 @@ } private void addIfPossible(Deque queue, AnnotationTypeMapping source, Annotation ann) { - addIfPossible(queue, source, ann.annotationType(), ann); + addIfPossible(queue, source, ann.annotationType(), ann, new HashSet<>()); } private void addIfPossible(Deque queue, @Nullable AnnotationTypeMapping source, - Class annotationType, @Nullable Annotation ann) { + Class annotationType, @Nullable Annotation ann, + Set> visitedAnnotationTypes) { try { - queue.addLast(new AnnotationTypeMapping(source, annotationType, ann)); + queue.addLast(new AnnotationTypeMapping(source, annotationType, ann, visitedAnnotationTypes)); } catch (Exception ex) { AnnotationUtils.rethrowAnnotationConfigurationException(ex); @@ -166,20 +173,22 @@ * @return type mappings for the annotation type */ static AnnotationTypeMappings forAnnotationType(Class annotationType) { - return forAnnotationType(annotationType, AnnotationFilter.PLAIN); + return forAnnotationType(annotationType, new HashSet<>()); } /** * Create {@link AnnotationTypeMappings} for the specified annotation type. * @param annotationType the source annotation type - * @param annotationFilter the annotation filter used to limit which - * annotations are considered + * @param visitedAnnotationTypes the set of annotations that we have already + * visited; used to avoid infinite recursion for recursive annotations which + * some JVM languages support (such as Kotlin) * @return type mappings for the annotation type */ - static AnnotationTypeMappings forAnnotationType( - Class annotationType, AnnotationFilter annotationFilter) { + static AnnotationTypeMappings forAnnotationType(Class annotationType, + Set> visitedAnnotationTypes) { - return forAnnotationType(annotationType, RepeatableContainers.standardRepeatables(), annotationFilter); + return forAnnotationType(annotationType, RepeatableContainers.standardRepeatables(), + AnnotationFilter.PLAIN, visitedAnnotationTypes); } /** @@ -194,15 +203,34 @@ static AnnotationTypeMappings forAnnotationType(Class annotationType, RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) { + return forAnnotationType(annotationType, repeatableContainers, annotationFilter, new HashSet<>()); + } + + /** + * Create {@link AnnotationTypeMappings} for the specified annotation type. + * @param annotationType the source annotation type + * @param repeatableContainers the repeatable containers that may be used by + * the meta-annotations + * @param annotationFilter the annotation filter used to limit which + * annotations are considered + * @param visitedAnnotationTypes the set of annotations that we have already + * visited; used to avoid infinite recursion for recursive annotations which + * some JVM languages support (such as Kotlin) + * @return type mappings for the annotation type + */ + private static AnnotationTypeMappings forAnnotationType(Class annotationType, + RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter, + Set> visitedAnnotationTypes) { + if (repeatableContainers == RepeatableContainers.standardRepeatables()) { return standardRepeatablesCache.computeIfAbsent(annotationFilter, - key -> new Cache(repeatableContainers, key)).get(annotationType); + key -> new Cache(repeatableContainers, key)).get(annotationType, visitedAnnotationTypes); } if (repeatableContainers == RepeatableContainers.none()) { return noRepeatablesCache.computeIfAbsent(annotationFilter, - key -> new Cache(repeatableContainers, key)).get(annotationType); + key -> new Cache(repeatableContainers, key)).get(annotationType, visitedAnnotationTypes); } - return new AnnotationTypeMappings(repeatableContainers, annotationFilter, annotationType); + return new AnnotationTypeMappings(repeatableContainers, annotationFilter, annotationType, visitedAnnotationTypes); } static void clearCache() { @@ -235,14 +263,21 @@ /** * Get or create {@link AnnotationTypeMappings} for the specified annotation type. * @param annotationType the annotation type + * @param visitedAnnotationTypes the set of annotations that we have already + * visited; used to avoid infinite recursion for recursive annotations which + * some JVM languages support (such as Kotlin) * @return a new or existing {@link AnnotationTypeMappings} instance */ - AnnotationTypeMappings get(Class annotationType) { - return this.mappings.computeIfAbsent(annotationType, this::createMappings); + AnnotationTypeMappings get(Class annotationType, + Set> visitedAnnotationTypes) { + + return this.mappings.computeIfAbsent(annotationType, key -> createMappings(key, visitedAnnotationTypes)); } - AnnotationTypeMappings createMappings(Class annotationType) { - return new AnnotationTypeMappings(this.repeatableContainers, this.filter, annotationType); + private AnnotationTypeMappings createMappings(Class annotationType, + Set> visitedAnnotationTypes) { + + return new AnnotationTypeMappings(this.repeatableContainers, this.filter, annotationType, visitedAnnotationTypes); } } Index: 3rdParty_sources/spring/org/springframework/core/annotation/AttributeMethods.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/annotation/AttributeMethods.java (.../AttributeMethods.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/annotation/AttributeMethods.java (.../AttributeMethods.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -32,6 +32,7 @@ * with consistent ordering as well as a few useful utility methods. * * @author Phillip Webb + * @author Sam Brannen * @since 5.2 */ final class AttributeMethods { @@ -71,10 +72,10 @@ for (int i = 0; i < attributeMethods.length; i++) { Method method = this.attributeMethods[i]; Class type = method.getReturnType(); - if (method.getDefaultValue() != null) { + if (!foundDefaultValueMethod && (method.getDefaultValue() != null)) { foundDefaultValueMethod = true; } - if (type.isAnnotation() || (type.isArray() && type.getComponentType().isAnnotation())) { + if (!foundNestedAnnotation && (type.isAnnotation() || (type.isArray() && type.getComponentType().isAnnotation()))) { foundNestedAnnotation = true; } ReflectionUtils.makeAccessible(method); Index: 3rdParty_sources/spring/org/springframework/core/annotation/MergedAnnotations.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/annotation/MergedAnnotations.java (.../MergedAnnotations.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/annotation/MergedAnnotations.java (.../MergedAnnotations.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -85,7 +85,7 @@ * * * - *

{@link MergedAnnotations} can be obtained {@linkplain #from(AnnotatedElement) + *

{@code MergedAnnotations} can be obtained {@linkplain #from(AnnotatedElement) * from} any Java {@link AnnotatedElement}. They may also be used for sources that * don't use reflection (such as those that directly parse bytecode). * @@ -94,7 +94,7 @@ * example, {@link SearchStrategy#TYPE_HIERARCHY} will search both superclasses and * implemented interfaces. * - *

From a {@link MergedAnnotations} instance you can either + *

From a {@code MergedAnnotations} instance you can either * {@linkplain #get(String) get} a single annotation, or {@linkplain #stream() * stream all annotations} or just those that match {@linkplain #stream(String) * a specific type}. You can also quickly tell if an annotation @@ -138,7 +138,7 @@ public interface MergedAnnotations extends Iterable> { /** - * Determine if the specified annotation is either directly present or + * Determine if the specified annotation type is either directly present or * meta-present. *

Equivalent to calling {@code get(annotationType).isPresent()}. * @param annotationType the annotation type to check @@ -147,7 +147,7 @@ boolean isPresent(Class annotationType); /** - * Determine if the specified annotation is either directly present or + * Determine if the specified annotation type is either directly present or * meta-present. *

Equivalent to calling {@code get(annotationType).isPresent()}. * @param annotationType the fully qualified class name of the annotation type @@ -157,15 +157,15 @@ boolean isPresent(String annotationType); /** - * Determine if the specified annotation is directly present. + * Determine if the specified annotation type is directly present. *

Equivalent to calling {@code get(annotationType).isDirectlyPresent()}. * @param annotationType the annotation type to check * @return {@code true} if the annotation is directly present */ boolean isDirectlyPresent(Class annotationType); /** - * Determine if the specified annotation is directly present. + * Determine if the specified annotation type is directly present. *

Equivalent to calling {@code get(annotationType).isDirectlyPresent()}. * @param annotationType the fully qualified class name of the annotation type * to check @@ -256,17 +256,17 @@ /** * Stream all annotations and meta-annotations that match the specified - * type. The resulting stream follows the same ordering rules as - * {@link #stream()}. + * type. + *

The resulting stream follows the same ordering rules as {@link #stream()}. * @param annotationType the annotation type to match * @return a stream of matching annotations */ Stream> stream(Class annotationType); /** * Stream all annotations and meta-annotations that match the specified - * type. The resulting stream follows the same ordering rules as - * {@link #stream()}. + * type. + *

The resulting stream follows the same ordering rules as {@link #stream()}. * @param annotationType the fully qualified class name of the annotation type * to match * @return a stream of matching annotations @@ -275,7 +275,7 @@ /** * Stream all annotations and meta-annotations contained in this collection. - * The resulting stream is ordered first by the + *

The resulting stream is ordered first by the * {@linkplain MergedAnnotation#getAggregateIndex() aggregate index} and then * by the annotation distance (with the closest annotations first). This ordering * means that, for most use-cases, the most suitable annotations appear @@ -287,13 +287,13 @@ /** * Create a new {@link MergedAnnotations} instance containing all - * annotations and meta-annotations from the specified element. The - * resulting instance will not include any inherited annotations. If you - * want to include those as well you should use + * annotations and meta-annotations from the specified element. + *

The resulting instance will not include any inherited annotations. If + * you want to include those as well you should use * {@link #from(AnnotatedElement, SearchStrategy)} with an appropriate * {@link SearchStrategy}. * @param element the source element - * @return a {@link MergedAnnotations} instance containing the element's + * @return a {@code MergedAnnotations} instance containing the element's * annotations */ static MergedAnnotations from(AnnotatedElement element) { @@ -306,7 +306,7 @@ * depending on the {@link SearchStrategy}, related inherited elements. * @param element the source element * @param searchStrategy the search strategy to use - * @return a {@link MergedAnnotations} instance containing the merged + * @return a {@code MergedAnnotations} instance containing the merged * element annotations */ static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy) { @@ -321,7 +321,7 @@ * @param searchStrategy the search strategy to use * @param repeatableContainers the repeatable containers that may be used by * the element annotations or the meta-annotations - * @return a {@link MergedAnnotations} instance containing the merged + * @return a {@code MergedAnnotations} instance containing the merged * element annotations */ static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy, @@ -340,7 +340,7 @@ * the element annotations or the meta-annotations * @param annotationFilter an annotation filter used to restrict the * annotations considered - * @return a {@link MergedAnnotations} instance containing the merged + * @return a {@code MergedAnnotations} instance containing the merged * annotations for the supplied element */ static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy, @@ -355,7 +355,7 @@ * Create a new {@link MergedAnnotations} instance from the specified * annotations. * @param annotations the annotations to include - * @return a {@link MergedAnnotations} instance containing the annotations + * @return a {@code MergedAnnotations} instance containing the annotations * @see #from(Object, Annotation...) */ static MergedAnnotations from(Annotation... annotations) { @@ -369,7 +369,7 @@ * for information and logging. It does not need to actually * contain the specified annotations, and it will not be searched. * @param annotations the annotations to include - * @return a {@link MergedAnnotations} instance containing the annotations + * @return a {@code MergedAnnotations} instance containing the annotations * @see #from(Annotation...) * @see #from(AnnotatedElement) */ @@ -386,7 +386,7 @@ * @param annotations the annotations to include * @param repeatableContainers the repeatable containers that may be used by * meta-annotations - * @return a {@link MergedAnnotations} instance containing the annotations + * @return a {@code MergedAnnotations} instance containing the annotations */ static MergedAnnotations from(Object source, Annotation[] annotations, RepeatableContainers repeatableContainers) { return from(source, annotations, repeatableContainers, AnnotationFilter.PLAIN); @@ -403,7 +403,7 @@ * meta-annotations * @param annotationFilter an annotation filter used to restrict the * annotations considered - * @return a {@link MergedAnnotations} instance containing the annotations + * @return a {@code MergedAnnotations} instance containing the annotations */ static MergedAnnotations from(Object source, Annotation[] annotations, RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) { @@ -416,16 +416,16 @@ /** * Create a new {@link MergedAnnotations} instance from the specified * collection of directly present annotations. This method allows a - * {@link MergedAnnotations} instance to be created from annotations that + * {@code MergedAnnotations} instance to be created from annotations that * are not necessarily loaded using reflection. The provided annotations * must all be {@link MergedAnnotation#isDirectlyPresent() directly present} * and must have an {@link MergedAnnotation#getAggregateIndex() aggregate * index} of {@code 0}. - *

The resulting {@link MergedAnnotations} instance will contain both the - * specified annotations, and any meta-annotations that can be read using + *

The resulting {@code MergedAnnotations} instance will contain both the + * specified annotations and any meta-annotations that can be read using * reflection. * @param annotations the annotations to include - * @return a {@link MergedAnnotations} instance containing the annotations + * @return a {@code MergedAnnotations} instance containing the annotations * @see MergedAnnotation#of(ClassLoader, Object, Class, java.util.Map) */ static MergedAnnotations of(Collection> annotations) { @@ -435,7 +435,8 @@ /** * Search strategies supported by - * {@link MergedAnnotations#from(AnnotatedElement, SearchStrategy)}. + * {@link MergedAnnotations#from(AnnotatedElement, SearchStrategy)} and + * variants of that method. * *

Each strategy creates a different set of aggregates that will be * combined to create the final {@link MergedAnnotations}. @@ -451,39 +452,49 @@ /** * Find all directly declared annotations as well as any - * {@link Inherited @Inherited} superclass annotations. This strategy - * is only really useful when used with {@link Class} types since the - * {@link Inherited @Inherited} annotation is ignored for all other - * {@linkplain AnnotatedElement annotated elements}. This strategy does - * not search implemented interfaces. + * {@link Inherited @Inherited} superclass annotations. + *

This strategy is only really useful when used with {@link Class} + * types since the {@link Inherited @Inherited} annotation is ignored for + * all other {@linkplain AnnotatedElement annotated elements}. + *

This strategy does not search implemented interfaces. */ INHERITED_ANNOTATIONS, /** - * Find all directly declared and superclass annotations. This strategy - * is similar to {@link #INHERITED_ANNOTATIONS} except the annotations - * do not need to be meta-annotated with {@link Inherited @Inherited}. - * This strategy does not search implemented interfaces. + * Find all directly declared and superclass annotations. + *

This strategy is similar to {@link #INHERITED_ANNOTATIONS} except + * the annotations do not need to be meta-annotated with + * {@link Inherited @Inherited}. + *

This strategy does not search implemented interfaces. */ SUPERCLASS, /** * Perform a full search of the entire type hierarchy, including - * superclasses and implemented interfaces. Superclass annotations do - * not need to be meta-annotated with {@link Inherited @Inherited}. + * superclasses and implemented interfaces. + *

Superclass annotations do not need to be meta-annotated with + * {@link Inherited @Inherited}. */ TYPE_HIERARCHY, /** * Perform a full search of the entire type hierarchy on the source - * and any enclosing classes. This strategy is similar to - * {@link #TYPE_HIERARCHY} except that {@linkplain Class#getEnclosingClass() - * enclosing classes} are also searched. Superclass annotations do not - * need to be meta-annotated with {@link Inherited @Inherited}. When - * searching a {@link Method} source, this strategy is identical to - * {@link #TYPE_HIERARCHY}. + * and any enclosing classes. + *

This strategy is similar to {@link #TYPE_HIERARCHY} except that + * {@linkplain Class#getEnclosingClass() enclosing classes} are also + * searched. + *

Superclass and enclosing class annotations do not need to be + * meta-annotated with {@link Inherited @Inherited}. + *

When searching a {@link Method} source, this strategy is identical + * to {@link #TYPE_HIERARCHY}. + *

WARNING: This strategy searches recursively for + * annotations on the enclosing class for any source type, regardless + * whether the source type is an inner class, a {@code static} + * nested class, or a nested interface. Thus, it may find more annotations + * than you would expect. */ TYPE_HIERARCHY_AND_ENCLOSING_CLASSES + } } Index: 3rdParty_sources/spring/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java (.../SynthesizedMergedAnnotationInvocationHandler.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java (.../SynthesizedMergedAnnotationInvocationHandler.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -177,7 +177,7 @@ private String annotationToString() { String string = this.string; if (string == null) { - StringBuilder builder = new StringBuilder("@").append(this.type.getName()).append('('); + StringBuilder builder = new StringBuilder("@").append(getName(this.type)).append('('); for (int i = 0; i < this.attributes.size(); i++) { Method attribute = this.attributes.get(i); if (i > 0) { @@ -194,19 +194,53 @@ return string; } + /** + * This method currently does not address the following issues which we may + * choose to address at a later point in time. + * + *

+ * @param value the attribute value to format + * @return the formatted string representation + */ private String toString(Object value) { + if (value instanceof String) { + return '"' + value.toString() + '"'; + } + if (value instanceof Character) { + return '\'' + value.toString() + '\''; + } + if (value instanceof Byte) { + return String.format("(byte) 0x%02X", value); + } + if (value instanceof Long) { + return Long.toString(((Long) value)) + 'L'; + } + if (value instanceof Float) { + return Float.toString(((Float) value)) + 'f'; + } + if (value instanceof Double) { + return Double.toString(((Double) value)) + 'd'; + } + if (value instanceof Enum) { + return ((Enum) value).name(); + } if (value instanceof Class) { - return ((Class) value).getName(); + return getName((Class) value) + ".class"; } if (value.getClass().isArray()) { - StringBuilder builder = new StringBuilder("["); + StringBuilder builder = new StringBuilder("{"); for (int i = 0; i < Array.getLength(value); i++) { if (i > 0) { builder.append(", "); } builder.append(toString(Array.get(value, i))); } - builder.append(']'); + builder.append('}'); return builder.toString(); } return String.valueOf(value); @@ -271,7 +305,12 @@ return (A) Proxy.newProxyInstance(classLoader, interfaces, handler); } + private static String getName(Class clazz) { + String canonicalName = clazz.getCanonicalName(); + return (canonicalName != null ? canonicalName : clazz.getName()); + } + private static boolean isVisible(ClassLoader classLoader, Class interfaceClass) { if (classLoader == interfaceClass.getClassLoader()) { return true; Index: 3rdParty_sources/spring/org/springframework/core/env/Environment.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/env/Environment.java (.../Environment.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/env/Environment.java (.../Environment.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -34,9 +34,9 @@ *

Properties play an important role in almost all applications, and may * originate from a variety of sources: properties files, JVM system properties, system * environment variables, JNDI, servlet context parameters, ad-hoc Properties objects, - * Maps, and so on. The role of the environment object with relation to properties is to - * provide the user with a convenient service interface for configuring property sources - * and resolving properties from them. + * Maps, and so on. The role of the {@code Environment} object with relation to properties + * is to provide the user with a convenient service interface for configuring property + * sources and resolving properties from them. * *

Beans managed within an {@code ApplicationContext} may register to be {@link * org.springframework.context.EnvironmentAware EnvironmentAware} or {@code @Inject} the @@ -50,7 +50,7 @@ * as of Spring 3.1 is registered by default when using * {@code }. * - *

Configuration of the environment object must be done through the + *

Configuration of the {@code Environment} object must be done through the * {@code ConfigurableEnvironment} interface, returned from all * {@code AbstractApplicationContext} subclass {@code getEnvironment()} methods. See * {@link ConfigurableEnvironment} Javadoc for usage examples demonstrating manipulation Index: 3rdParty_sources/spring/org/springframework/core/log/LogFormatUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/log/LogFormatUtils.java (.../LogFormatUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/log/LogFormatUtils.java (.../LogFormatUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -17,10 +17,12 @@ package org.springframework.core.log; import java.util.function.Function; +import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; /** * Utility methods for formatting and logging messages. @@ -35,10 +37,15 @@ */ public abstract class LogFormatUtils { + private static final Pattern NEWLINE_PATTERN = Pattern.compile("[\n\r]"); + + private static final Pattern CONTROL_CHARACTER_PATTERN = Pattern.compile("\\p{Cc}"); + + /** * Convenience variant of {@link #formatValue(Object, int, boolean)} that * limits the length of a log message to 100 characters and also replaces - * newline characters if {@code limitLength} is set to "true". + * newline and control characters if {@code limitLength} is set to "true". * @param value the value to format * @param limitLength whether to truncate the value at a length of 100 * @return the formatted value @@ -53,25 +60,29 @@ * compacting it into a single line when {@code replaceNewLines} is set. * @param value the value to be formatted * @param maxLength the max length, after which to truncate, or -1 for unlimited - * @param replaceNewlines whether to replace newline characters with placeholders + * @param replaceNewlinesAndControlCharacters whether to replace newline and + * control characters with placeholders * @return the formatted value */ - public static String formatValue(@Nullable Object value, int maxLength, boolean replaceNewlines) { + public static String formatValue( + @Nullable Object value, int maxLength, boolean replaceNewlinesAndControlCharacters) { + if (value == null) { return ""; } String result; try { - result = value.toString(); + result = ObjectUtils.nullSafeToString(value); } catch (Throwable ex) { - result = ex.toString(); + result = ObjectUtils.nullSafeToString(ex); } if (maxLength != -1) { result = (result.length() > maxLength ? result.substring(0, maxLength) + " (truncated)..." : result); } - if (replaceNewlines) { - result = result.replace("\n", "").replace("\r", ""); + if (replaceNewlinesAndControlCharacters) { + result = NEWLINE_PATTERN.matcher(result).replaceAll(""); + result = CONTROL_CHARACTER_PATTERN.matcher(result).replaceAll("?"); } if (value instanceof CharSequence) { result = "\"" + result + "\""; Index: 3rdParty_sources/spring/org/springframework/core/metrics/jfr/FlightRecorderStartupStep.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/metrics/jfr/FlightRecorderStartupStep.java (.../FlightRecorderStartupStep.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/metrics/jfr/FlightRecorderStartupStep.java (.../FlightRecorderStartupStep.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -20,9 +20,8 @@ import java.util.function.Consumer; import java.util.function.Supplier; -import org.jetbrains.annotations.NotNull; - import org.springframework.core.metrics.StartupStep; +import org.springframework.lang.NonNull; /** * {@link StartupStep} implementation for the Java Flight Recorder. @@ -115,7 +114,7 @@ add(key, value.get()); } - @NotNull + @NonNull @Override public Iterator iterator() { return new TagsIterator(); Index: 3rdParty_sources/spring/org/springframework/core/task/AsyncTaskExecutor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/task/AsyncTaskExecutor.java (.../AsyncTaskExecutor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/task/AsyncTaskExecutor.java (.../AsyncTaskExecutor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -21,8 +21,7 @@ /** * Extended interface for asynchronous {@link TaskExecutor} implementations, - * offering an overloaded {@link #execute(Runnable, long)} variant with a start - * timeout parameter as well support for {@link java.util.concurrent.Callable}. + * offering support for {@link java.util.concurrent.Callable}. * *

Note: The {@link java.util.concurrent.Executors} class includes a set of * methods that can convert some other common closure-like objects, for example, @@ -41,10 +40,18 @@ */ public interface AsyncTaskExecutor extends TaskExecutor { - /** Constant that indicates immediate execution. */ + /** + * Constant that indicates immediate execution. + * @deprecated as of 5.3.16 along with {@link #execute(Runnable, long)} + */ + @Deprecated long TIMEOUT_IMMEDIATE = 0; - /** Constant that indicates no time limit. */ + /** + * Constant that indicates no time limit. + * @deprecated as of 5.3.16 along with {@link #execute(Runnable, long)} + */ + @Deprecated long TIMEOUT_INDEFINITE = Long.MAX_VALUE; @@ -58,7 +65,10 @@ * @throws TaskTimeoutException in case of the task being rejected because * of the timeout (i.e. it cannot be started in time) * @throws TaskRejectedException if the given task was not accepted + * @see #execute(Runnable) + * @deprecated as of 5.3.16 since the common executors do not support start timeouts */ + @Deprecated void execute(Runnable task, long startTimeout); /** Index: 3rdParty_sources/spring/org/springframework/core/task/SimpleAsyncTaskExecutor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/task/SimpleAsyncTaskExecutor.java (.../SimpleAsyncTaskExecutor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/task/SimpleAsyncTaskExecutor.java (.../SimpleAsyncTaskExecutor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -174,6 +174,7 @@ * if configured (through the superclass's settings). * @see #doExecute(Runnable) */ + @SuppressWarnings("deprecation") @Override public void execute(Runnable task) { execute(task, TIMEOUT_INDEFINITE); @@ -188,6 +189,7 @@ * @see #TIMEOUT_IMMEDIATE * @see #doExecute(Runnable) */ + @Deprecated @Override public void execute(Runnable task, long startTimeout) { Assert.notNull(task, "Runnable must not be null"); @@ -201,27 +203,31 @@ } } + @SuppressWarnings("deprecation") @Override public Future submit(Runnable task) { FutureTask future = new FutureTask<>(task, null); execute(future, TIMEOUT_INDEFINITE); return future; } + @SuppressWarnings("deprecation") @Override public Future submit(Callable task) { FutureTask future = new FutureTask<>(task); execute(future, TIMEOUT_INDEFINITE); return future; } + @SuppressWarnings("deprecation") @Override public ListenableFuture submitListenable(Runnable task) { ListenableFutureTask future = new ListenableFutureTask<>(task, null); execute(future, TIMEOUT_INDEFINITE); return future; } + @SuppressWarnings("deprecation") @Override public ListenableFuture submitListenable(Callable task) { ListenableFutureTask future = new ListenableFutureTask<>(task); Index: 3rdParty_sources/spring/org/springframework/core/task/TaskRejectedException.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/task/TaskRejectedException.java (.../TaskRejectedException.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/task/TaskRejectedException.java (.../TaskRejectedException.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2022 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. @@ -25,7 +25,6 @@ * @author Juergen Hoeller * @since 2.0.1 * @see TaskExecutor#execute(Runnable) - * @see TaskTimeoutException */ @SuppressWarnings("serial") public class TaskRejectedException extends RejectedExecutionException { Index: 3rdParty_sources/spring/org/springframework/core/task/TaskTimeoutException.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/task/TaskTimeoutException.java (.../TaskTimeoutException.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/task/TaskTimeoutException.java (.../TaskTimeoutException.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2022 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. @@ -23,8 +23,9 @@ * @author Juergen Hoeller * @since 2.0.3 * @see AsyncTaskExecutor#execute(Runnable, long) - * @see TaskRejectedException + * @deprecated as of 5.3.16 since the common executors do not support start timeouts */ +@Deprecated @SuppressWarnings("serial") public class TaskTimeoutException extends TaskRejectedException { Index: 3rdParty_sources/spring/org/springframework/core/task/support/TaskExecutorAdapter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/task/support/TaskExecutorAdapter.java (.../TaskExecutorAdapter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/task/support/TaskExecutorAdapter.java (.../TaskExecutorAdapter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -97,6 +97,7 @@ } } + @Deprecated @Override public void execute(Runnable task, long startTimeout) { execute(task); Index: 3rdParty_sources/spring/org/springframework/core/type/StandardAnnotationMetadata.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/type/StandardAnnotationMetadata.java (.../StandardAnnotationMetadata.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/type/StandardAnnotationMetadata.java (.../StandardAnnotationMetadata.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -162,7 +162,7 @@ throw new IllegalStateException("Failed to introspect annotated methods on " + getIntrospectedClass(), ex); } } - return annotatedMethods != null ? annotatedMethods : Collections.emptySet(); + return (annotatedMethods != null ? annotatedMethods : Collections.emptySet()); } Index: 3rdParty_sources/spring/org/springframework/core/type/classreading/SimpleAnnotationMetadata.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/type/classreading/SimpleAnnotationMetadata.java (.../SimpleAnnotationMetadata.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/type/classreading/SimpleAnnotationMetadata.java (.../SimpleAnnotationMetadata.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -128,6 +128,11 @@ } @Override + public MergedAnnotations getAnnotations() { + return this.annotations; + } + + @Override public Set getAnnotationTypes() { Set annotationTypes = this.annotationTypes; if (annotationTypes == null) { @@ -149,13 +154,9 @@ annotatedMethods.add(annotatedMethod); } } - return annotatedMethods != null ? annotatedMethods : Collections.emptySet(); + return (annotatedMethods != null ? annotatedMethods : Collections.emptySet()); } - @Override - public MergedAnnotations getAnnotations() { - return this.annotations; - } @Override public boolean equals(@Nullable Object obj) { Index: 3rdParty_sources/spring/org/springframework/core/type/classreading/SimpleAnnotationMetadataReadingVisitor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/core/type/classreading/SimpleAnnotationMetadataReadingVisitor.java (.../SimpleAnnotationMetadataReadingVisitor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/core/type/classreading/SimpleAnnotationMetadataReadingVisitor.java (.../SimpleAnnotationMetadataReadingVisitor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -99,8 +99,7 @@ } @Override - public void visitInnerClass(String name, @Nullable String outerName, String innerName, - int access) { + public void visitInnerClass(String name, @Nullable String outerName, String innerName, int access) { if (outerName != null) { String className = toClassName(name); String outerClassName = toClassName(outerName); Index: 3rdParty_sources/spring/org/springframework/expression/MethodResolver.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/expression/MethodResolver.java (.../MethodResolver.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/expression/MethodResolver.java (.../MethodResolver.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2021 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. @@ -22,8 +22,8 @@ import org.springframework.lang.Nullable; /** - * A method resolver attempts locate a method and returns a command executor that can be - * used to invoke that method. The command executor will be cached but if it 'goes stale' + * A method resolver attempts to locate a method and returns a command executor that can be + * used to invoke that method. The command executor will be cached, but if it 'goes stale' * the resolvers will be called again. * * @author Andy Clement Index: 3rdParty_sources/spring/org/springframework/expression/spel/SpelMessage.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/expression/spel/SpelMessage.java (.../SpelMessage.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/expression/spel/SpelMessage.java (.../SpelMessage.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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,10 +27,11 @@ *

When a message is formatted, it will have this kind of form, capturing the prefix * and the error kind: * - *

EL1004E: Type cannot be found 'String'
+ *
EL1005E: Type cannot be found 'String'
* * @author Andy Clement * @author Juergen Hoeller + * @author Sam Brannen * @since 3.0 */ public enum SpelMessage { @@ -255,9 +256,17 @@ /** @since 4.3.17 */ FLAWED_PATTERN(Kind.ERROR, 1073, - "Failed to efficiently evaluate pattern ''{0}'': consider redesigning it"); + "Failed to efficiently evaluate pattern ''{0}'': consider redesigning it"), + /** @since 5.3.17 */ + EXCEPTION_COMPILING_EXPRESSION(Kind.ERROR, 1074, + "An exception occurred while compiling an expression"), + /** @since 5.3.17 */ + MAX_ARRAY_ELEMENTS_THRESHOLD_EXCEEDED(Kind.ERROR, 1075, + "Array declares too many elements, exceeding the threshold of ''{0}''"); + + private final Kind kind; private final int code; Index: 3rdParty_sources/spring/org/springframework/expression/spel/ast/ConstructorReference.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/expression/spel/ast/ConstructorReference.java (.../ConstructorReference.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/expression/spel/ast/ConstructorReference.java (.../ConstructorReference.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -53,10 +53,18 @@ * * @author Andy Clement * @author Juergen Hoeller + * @author Sam Brannen * @since 3.0 */ public class ConstructorReference extends SpelNodeImpl { + /** + * Maximum number of elements permitted in an array declaration, applying + * to one-dimensional as well as multi-dimensional arrays. + * @since 5.3.17 + */ + private static final int MAX_ARRAY_ELEMENTS = 256 * 1024; // 256K + private final boolean isArrayConstructor; @Nullable @@ -259,14 +267,19 @@ // Shortcut for 1-dimensional TypedValue o = this.dimensions[0].getTypedValue(state); int arraySize = ExpressionUtils.toInt(typeConverter, o); + checkNumElements(arraySize); newArray = Array.newInstance(componentType, arraySize); } else { // Multi-dimensional - hold onto your hat! int[] dims = new int[this.dimensions.length]; + long numElements = 1; for (int d = 0; d < this.dimensions.length; d++) { TypedValue o = this.dimensions[d].getTypedValue(state); - dims[d] = ExpressionUtils.toInt(typeConverter, o); + int arraySize = ExpressionUtils.toInt(typeConverter, o); + dims[d] = arraySize; + numElements *= arraySize; + checkNumElements(numElements); } newArray = Array.newInstance(componentType, dims); } @@ -327,6 +340,13 @@ return new TypedValue(newArray); } + private void checkNumElements(long numElements) { + if (numElements >= MAX_ARRAY_ELEMENTS) { + throw new SpelEvaluationException(getStartPosition(), + SpelMessage.MAX_ARRAY_ELEMENTS_THRESHOLD_EXCEEDED, MAX_ARRAY_ELEMENTS); + } + } + private void populateReferenceTypeArray(ExpressionState state, Object newArray, TypeConverter typeConverter, InlineList initializer, Class componentType) { Index: 3rdParty_sources/spring/org/springframework/expression/spel/ast/MethodReference.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/expression/spel/ast/MethodReference.java (.../MethodReference.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/expression/spel/ast/MethodReference.java (.../MethodReference.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -200,8 +200,7 @@ EvaluationContext evaluationContext) throws SpelEvaluationException { AccessException accessException = null; - List methodResolvers = evaluationContext.getMethodResolvers(); - for (MethodResolver methodResolver : methodResolvers) { + for (MethodResolver methodResolver : evaluationContext.getMethodResolvers()) { try { MethodExecutor methodExecutor = methodResolver.resolve( evaluationContext, targetObject, this.name, argumentTypes); Index: 3rdParty_sources/spring/org/springframework/expression/spel/standard/SpelCompiler.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/expression/spel/standard/SpelCompiler.java (.../SpelCompiler.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/expression/spel/standard/SpelCompiler.java (.../SpelCompiler.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -110,7 +110,8 @@ return ReflectionUtils.accessibleConstructor(clazz).newInstance(); } catch (Throwable ex) { - throw new IllegalStateException("Failed to instantiate CompiledExpression", ex); + throw new IllegalStateException("Failed to instantiate CompiledExpression for expression: " + + expression.toStringAST(), ex); } } } Index: 3rdParty_sources/spring/org/springframework/expression/spel/standard/SpelExpression.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/expression/spel/standard/SpelExpression.java (.../SpelExpression.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/expression/spel/standard/SpelExpression.java (.../SpelExpression.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -44,6 +44,7 @@ * * @author Andy Clement * @author Juergen Hoeller + * @author Sam Brannen * @since 3.0 */ public class SpelExpression implements Expression { @@ -522,17 +523,34 @@ // Compiled by another thread before this thread got into the sync block return true; } - SpelCompiler compiler = SpelCompiler.getCompiler(this.configuration.getCompilerClassLoader()); - compiledAst = compiler.compile(this.ast); - if (compiledAst != null) { - // Successfully compiled - this.compiledAst = compiledAst; - return true; + try { + SpelCompiler compiler = SpelCompiler.getCompiler(this.configuration.getCompilerClassLoader()); + compiledAst = compiler.compile(this.ast); + if (compiledAst != null) { + // Successfully compiled + this.compiledAst = compiledAst; + return true; + } + else { + // Failed to compile + this.failedAttempts.incrementAndGet(); + return false; + } } - else { + catch (Exception ex) { // Failed to compile this.failedAttempts.incrementAndGet(); - return false; + + // If running in mixed mode, revert to interpreted + if (this.configuration.getCompilerMode() == SpelCompilerMode.MIXED) { + this.compiledAst = null; + this.interpretedCount.set(0); + return false; + } + else { + // Running in SpelCompilerMode.immediate mode - propagate exception to caller + throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_COMPILING_EXPRESSION); + } } } } Index: 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectionHelper.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectionHelper.java (.../ReflectionHelper.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectionHelper.java (.../ReflectionHelper.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -20,6 +20,7 @@ import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.util.List; +import java.util.Optional; import org.springframework.core.MethodParameter; import org.springframework.core.convert.TypeDescriptor; @@ -290,20 +291,29 @@ Object argument = arguments[varargsPosition]; TypeDescriptor targetType = new TypeDescriptor(methodParam); TypeDescriptor sourceType = TypeDescriptor.forObject(argument); - // If the argument type is equal to the varargs element type, there is no need - // to convert it or wrap it in an array. For example, using StringToArrayConverter - // to convert a String containing a comma would result in the String being split - // and repackaged in an array when it should be used as-is. - if (!sourceType.equals(targetType.getElementTypeDescriptor())) { + if (argument == null) { + // Perform the equivalent of GenericConversionService.convertNullSource() for a single argument. + if (targetType.getElementTypeDescriptor().getObjectType() == Optional.class) { + arguments[varargsPosition] = Optional.empty(); + conversionOccurred = true; + } + } + // If the argument type is equal to the varargs element type, there is no need to + // convert it or wrap it in an array. For example, using StringToArrayConverter to + // convert a String containing a comma would result in the String being split and + // repackaged in an array when it should be used as-is. + else if (!sourceType.equals(targetType.getElementTypeDescriptor())) { arguments[varargsPosition] = converter.convertValue(argument, sourceType, targetType); } - // Three outcomes of the above if-block: - // 1) the input argument was correct type but not wrapped in an array, and nothing was done. - // 2) the input argument was already compatible (i.e., array of valid type), and nothing was done. - // 3) the input argument was the wrong type and got converted and wrapped in an array. + // Possible outcomes of the above if-else block: + // 1) the input argument was null, and nothing was done. + // 2) the input argument was null; the varargs element type is Optional; and the argument was converted to Optional.empty(). + // 3) the input argument was correct type but not wrapped in an array, and nothing was done. + // 4) the input argument was already compatible (i.e., array of valid type), and nothing was done. + // 5) the input argument was the wrong type and got converted and wrapped in an array. if (argument != arguments[varargsPosition] && !isFirstEntryInArray(argument, arguments[varargsPosition])) { - conversionOccurred = true; // case 3 + conversionOccurred = true; // case 5 } } // Otherwise, convert remaining arguments to the varargs element type. Index: 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectiveMethodExecutor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectiveMethodExecutor.java (.../ReflectiveMethodExecutor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectiveMethodExecutor.java (.../ReflectiveMethodExecutor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -58,8 +58,18 @@ * @param method the method to invoke */ public ReflectiveMethodExecutor(Method method) { + this(method, null); + } + + /** + * Create a new executor for the given method. + * @param method the method to invoke + * @param targetClass the target class to invoke the method on + * @since 5.3.16 + */ + public ReflectiveMethodExecutor(Method method, @Nullable Class targetClass) { this.originalMethod = method; - this.methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(method); + this.methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(method, targetClass); if (method.isVarArgs()) { this.varargsPosition = method.getParameterCount() - 1; } Index: 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectiveMethodResolver.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectiveMethodResolver.java (.../ReflectiveMethodResolver.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectiveMethodResolver.java (.../ReflectiveMethodResolver.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -176,7 +176,7 @@ } if (matchInfo != null) { if (matchInfo.isExactMatch()) { - return new ReflectiveMethodExecutor(method); + return new ReflectiveMethodExecutor(method, type); } else if (matchInfo.isCloseMatch()) { if (this.useDistance) { @@ -204,13 +204,13 @@ } } if (closeMatch != null) { - return new ReflectiveMethodExecutor(closeMatch); + return new ReflectiveMethodExecutor(closeMatch, type); } else if (matchRequiringConversion != null) { if (multipleOptions) { throw new SpelEvaluationException(SpelMessage.MULTIPLE_POSSIBLE_METHODS, name); } - return new ReflectiveMethodExecutor(matchRequiringConversion); + return new ReflectiveMethodExecutor(matchRequiringConversion, type); } else { return null; Index: 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java (.../ReflectivePropertyAccessor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java (.../ReflectivePropertyAccessor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -139,7 +139,7 @@ // The readerCache will only contain gettable properties (let's not worry about setters for now). Property property = new Property(type, method, null); TypeDescriptor typeDescriptor = new TypeDescriptor(property); - method = ClassUtils.getInterfaceMethodIfPossible(method); + method = ClassUtils.getInterfaceMethodIfPossible(method, type); this.readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor)); this.typeDescriptorCache.put(cacheKey, typeDescriptor); return true; @@ -182,7 +182,7 @@ // The readerCache will only contain gettable properties (let's not worry about setters for now). Property property = new Property(type, method, null); TypeDescriptor typeDescriptor = new TypeDescriptor(property); - method = ClassUtils.getInterfaceMethodIfPossible(method); + method = ClassUtils.getInterfaceMethodIfPossible(method, type); invoker = new InvokerPair(method, typeDescriptor); this.lastReadInvokerPair = invoker; this.readerCache.put(cacheKey, invoker); @@ -242,7 +242,7 @@ // Treat it like a property Property property = new Property(type, null, method); TypeDescriptor typeDescriptor = new TypeDescriptor(property); - method = ClassUtils.getInterfaceMethodIfPossible(method); + method = ClassUtils.getInterfaceMethodIfPossible(method, type); this.writerCache.put(cacheKey, method); this.typeDescriptorCache.put(cacheKey, typeDescriptor); return true; @@ -291,7 +291,7 @@ if (method == null) { method = findSetterForProperty(name, type, target); if (method != null) { - method = ClassUtils.getInterfaceMethodIfPossible(method); + method = ClassUtils.getInterfaceMethodIfPossible(method, type); cachedMember = method; this.writerCache.put(cacheKey, cachedMember); } @@ -533,21 +533,21 @@ if (target == null) { return this; } - Class clazz = (target instanceof Class ? (Class) target : target.getClass()); - if (clazz.isArray()) { + Class type = (target instanceof Class ? (Class) target : target.getClass()); + if (type.isArray()) { return this; } - PropertyCacheKey cacheKey = new PropertyCacheKey(clazz, name, target instanceof Class); + PropertyCacheKey cacheKey = new PropertyCacheKey(type, name, target instanceof Class); InvokerPair invocationTarget = this.readerCache.get(cacheKey); if (invocationTarget == null || invocationTarget.member instanceof Method) { Method method = (Method) (invocationTarget != null ? invocationTarget.member : null); if (method == null) { - method = findGetterForProperty(name, clazz, target); + method = findGetterForProperty(name, type, target); if (method != null) { TypeDescriptor typeDescriptor = new TypeDescriptor(new MethodParameter(method, -1)); - method = ClassUtils.getInterfaceMethodIfPossible(method); + method = ClassUtils.getInterfaceMethodIfPossible(method, type); invocationTarget = new InvokerPair(method, typeDescriptor); ReflectionUtils.makeAccessible(method); this.readerCache.put(cacheKey, invocationTarget); @@ -561,7 +561,7 @@ if (invocationTarget == null || invocationTarget.member instanceof Field) { Field field = (invocationTarget != null ? (Field) invocationTarget.member : null); if (field == null) { - field = findField(name, clazz, target instanceof Class); + field = findField(name, type, target instanceof Class); if (field != null) { invocationTarget = new InvokerPair(field, new TypeDescriptor(field)); ReflectionUtils.makeAccessible(field); @@ -600,7 +600,7 @@ private final String property; - private boolean targetIsClass; + private final boolean targetIsClass; public PropertyCacheKey(Class clazz, String name, boolean targetIsClass) { this.clazz = clazz; Index: 3rdParty_sources/spring/org/springframework/http/HttpMethod.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/HttpMethod.java (.../HttpMethod.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/HttpMethod.java (.../HttpMethod.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -22,7 +22,7 @@ import org.springframework.lang.Nullable; /** - * Java 5 enumeration of HTTP request methods. Intended for use + * Enumeration of HTTP request methods. Intended for use * with {@link org.springframework.http.client.ClientHttpRequest} * and {@link org.springframework.web.client.RestTemplate}. * Index: 3rdParty_sources/spring/org/springframework/http/client/reactive/AbstractClientHttpRequest.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/client/reactive/AbstractClientHttpRequest.java (.../AbstractClientHttpRequest.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/client/reactive/AbstractClientHttpRequest.java (.../AbstractClientHttpRequest.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -81,14 +81,24 @@ return this.readOnlyHeaders; } else if (State.COMMITTED.equals(this.state.get())) { - this.readOnlyHeaders = HttpHeaders.readOnlyHttpHeaders(this.headers); + this.readOnlyHeaders = initReadOnlyHeaders(); return this.readOnlyHeaders; } else { return this.headers; } } + /** + * Initialize the read-only headers after the request is committed. + *

By default, this method simply applies a read-only wrapper. + * Subclasses can do the same for headers from the native request. + * @since 5.3.15 + */ + protected HttpHeaders initReadOnlyHeaders() { + return HttpHeaders.readOnlyHttpHeaders(this.headers); + } + @Override public MultiValueMap getCookies() { if (State.COMMITTED.equals(this.state.get())) { Index: 3rdParty_sources/spring/org/springframework/http/client/reactive/HttpComponentsClientHttpRequest.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/client/reactive/HttpComponentsClientHttpRequest.java (.../HttpComponentsClientHttpRequest.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/client/reactive/HttpComponentsClientHttpRequest.java (.../HttpComponentsClientHttpRequest.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -62,7 +62,9 @@ @Nullable private Flux byteBufferFlux; + private transient long contentLength = -1; + public HttpComponentsClientHttpRequest(HttpMethod method, URI uri, HttpClientContext context, DataBufferFactory dataBufferFactory) { @@ -130,6 +132,8 @@ if (!this.httpRequest.containsHeader(HttpHeaders.ACCEPT)) { this.httpRequest.addHeader(HttpHeaders.ACCEPT, ALL_VALUE); } + + this.contentLength = headers.getContentLength(); } @Override @@ -151,6 +155,11 @@ }); } + @Override + protected HttpHeaders initReadOnlyHeaders() { + return HttpHeaders.readOnlyHttpHeaders(new HttpComponentsHeadersAdapter(this.httpRequest)); + } + public AsyncRequestProducer toRequestProducer() { ReactiveEntityProducer reactiveEntityProducer = null; @@ -160,8 +169,8 @@ if (getHeaders().getContentType() != null) { contentType = ContentType.parse(getHeaders().getContentType().toString()); } - reactiveEntityProducer = new ReactiveEntityProducer(this.byteBufferFlux, getHeaders().getContentLength(), - contentType, contentEncoding); + reactiveEntityProducer = new ReactiveEntityProducer( + this.byteBufferFlux, this.contentLength, contentType, contentEncoding); } return new BasicRequestProducer(this.httpRequest, reactiveEntityProducer); Index: 3rdParty_sources/spring/org/springframework/http/client/reactive/HttpComponentsHeadersAdapter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/client/reactive/HttpComponentsHeadersAdapter.java (.../HttpComponentsHeadersAdapter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/client/reactive/HttpComponentsHeadersAdapter.java (.../HttpComponentsHeadersAdapter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -28,7 +28,7 @@ import java.util.Set; import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.HttpMessage; import org.springframework.http.HttpHeaders; import org.springframework.lang.Nullable; @@ -44,23 +44,23 @@ */ class HttpComponentsHeadersAdapter implements MultiValueMap { - private final HttpResponse response; + private final HttpMessage message; - HttpComponentsHeadersAdapter(HttpResponse response) { - this.response = response; + HttpComponentsHeadersAdapter(HttpMessage message) { + this.message = message; } @Override public String getFirst(String key) { - Header header = this.response.getFirstHeader(key); + Header header = this.message.getFirstHeader(key); return (header != null ? header.getValue() : null); } @Override public void add(String key, @Nullable String value) { - this.response.addHeader(key, value); + this.message.addHeader(key, value); } @Override @@ -75,7 +75,7 @@ @Override public void set(String key, @Nullable String value) { - this.response.setHeader(key, value); + this.message.setHeader(key, value); } @Override @@ -86,37 +86,37 @@ @Override public Map toSingleValueMap() { Map map = CollectionUtils.newLinkedHashMap(size()); - this.response.headerIterator().forEachRemaining(h -> map.putIfAbsent(h.getName(), h.getValue())); + this.message.headerIterator().forEachRemaining(h -> map.putIfAbsent(h.getName(), h.getValue())); return map; } @Override public int size() { - return this.response.getHeaders().length; + return this.message.getHeaders().length; } @Override public boolean isEmpty() { - return (this.response.getHeaders().length == 0); + return (this.message.getHeaders().length == 0); } @Override public boolean containsKey(Object key) { - return (key instanceof String && this.response.containsHeader((String) key)); + return (key instanceof String && this.message.containsHeader((String) key)); } @Override public boolean containsValue(Object value) { return (value instanceof String && - Arrays.stream(this.response.getHeaders()).anyMatch(h -> h.getValue().equals(value))); + Arrays.stream(this.message.getHeaders()).anyMatch(h -> h.getValue().equals(value))); } @Nullable @Override public List get(Object key) { List values = null; if (containsKey(key)) { - Header[] headers = this.response.getHeaders((String) key); + Header[] headers = this.message.getHeaders((String) key); values = new ArrayList<>(headers.length); for (Header header : headers) { values.add(header.getValue()); @@ -138,7 +138,7 @@ public List remove(Object key) { if (key instanceof String) { List oldValues = get(key); - this.response.removeHeaders((String) key); + this.message.removeHeaders((String) key); return oldValues; } return null; @@ -151,13 +151,13 @@ @Override public void clear() { - this.response.setHeaders(); + this.message.setHeaders(); } @Override public Set keySet() { Set keys = new LinkedHashSet<>(size()); - for (Header header : this.response.getHeaders()) { + for (Header header : this.message.getHeaders()) { keys.add(header.getName()); } return keys; @@ -166,7 +166,7 @@ @Override public Collection> values() { Collection> values = new ArrayList<>(size()); - for (Header header : this.response.getHeaders()) { + for (Header header : this.message.getHeaders()) { values.add(get(header.getName())); } return values; @@ -196,7 +196,7 @@ private class EntryIterator implements Iterator>> { - private Iterator

iterator = response.headerIterator(); + private final Iterator
iterator = message.headerIterator(); @Override public boolean hasNext() { Index: 3rdParty_sources/spring/org/springframework/http/client/reactive/JettyClientHttpRequest.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/client/reactive/JettyClientHttpRequest.java (.../JettyClientHttpRequest.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/client/reactive/JettyClientHttpRequest.java (.../JettyClientHttpRequest.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -126,7 +126,6 @@ }); } - @Override protected void applyCookies() { getCookies().values().stream().flatMap(Collection::stream) @@ -143,9 +142,13 @@ } } + @Override + protected HttpHeaders initReadOnlyHeaders() { + return HttpHeaders.readOnlyHttpHeaders(new JettyHeadersAdapter(this.jettyRequest.getHeaders())); + } + public ReactiveRequest toReactiveRequest() { return this.builder.build(); } - } Index: 3rdParty_sources/spring/org/springframework/http/client/reactive/NettyHeadersAdapter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/client/reactive/NettyHeadersAdapter.java (.../NettyHeadersAdapter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/client/reactive/NettyHeadersAdapter.java (.../NettyHeadersAdapter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -147,7 +147,7 @@ @Override public void putAll(Map> map) { - map.forEach(this.headers::add); + map.forEach(this.headers::set); } @Override Index: 3rdParty_sources/spring/org/springframework/http/client/reactive/ReactorClientHttpConnector.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/client/reactive/ReactorClientHttpConnector.java (.../ReactorClientHttpConnector.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/client/reactive/ReactorClientHttpConnector.java (.../ReactorClientHttpConnector.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -73,18 +73,21 @@ * @since 5.1 */ public ReactorClientHttpConnector(ReactorResourceFactory factory, Function mapper) { - this.httpClient = defaultInitializer.andThen(mapper).apply(initHttpClient(factory)); + ConnectionProvider provider = factory.getConnectionProvider(); + Assert.notNull(provider, "No ConnectionProvider: is ReactorResourceFactory not initialized yet?"); + this.httpClient = defaultInitializer.andThen(mapper).andThen(applyLoopResources(factory)) + .apply(HttpClient.create(provider)); } - @SuppressWarnings("deprecation") - private static HttpClient initHttpClient(ReactorResourceFactory resourceFactory) { - ConnectionProvider provider = resourceFactory.getConnectionProvider(); - LoopResources resources = resourceFactory.getLoopResources(); - Assert.notNull(provider, "No ConnectionProvider: is ReactorResourceFactory not initialized yet?"); - Assert.notNull(resources, "No LoopResources: is ReactorResourceFactory not initialized yet?"); - return HttpClient.create(provider).tcpConfiguration(tcpClient -> tcpClient.runOn(resources)); + private static Function applyLoopResources(ReactorResourceFactory factory) { + return httpClient -> { + LoopResources resources = factory.getLoopResources(); + Assert.notNull(resources, "No LoopResources: is ReactorResourceFactory not initialized yet?"); + return httpClient.runOn(resources); + }; } + /** * Constructor with a pre-configured {@code HttpClient} instance. * @param httpClient the client to use Index: 3rdParty_sources/spring/org/springframework/http/client/reactive/ReactorClientHttpRequest.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/client/reactive/ReactorClientHttpRequest.java (.../ReactorClientHttpRequest.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/client/reactive/ReactorClientHttpRequest.java (.../ReactorClientHttpRequest.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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,6 +31,7 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.NettyDataBufferFactory; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ZeroCopyHttpOutputMessage; @@ -133,4 +134,9 @@ .forEach(this.request::addCookie); } + @Override + protected HttpHeaders initReadOnlyHeaders() { + return HttpHeaders.readOnlyHttpHeaders(new NettyHeadersAdapter(this.request.requestHeaders())); + } + } Index: 3rdParty_sources/spring/org/springframework/http/codec/ServerSentEventHttpMessageReader.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/codec/ServerSentEventHttpMessageReader.java (.../ServerSentEventHttpMessageReader.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/codec/ServerSentEventHttpMessageReader.java (.../ServerSentEventHttpMessageReader.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -42,6 +42,7 @@ * * @author Sebastien Deleuze * @author Rossen Stoyanchev + * @author Juergen Hoeller * @since 5.0 */ public class ServerSentEventHttpMessageReader implements HttpMessageReader { @@ -140,22 +141,23 @@ private Object buildEvent(List lines, ResolvableType valueType, boolean shouldWrap, Map hints) { - ServerSentEvent.Builder sseBuilder = shouldWrap ? ServerSentEvent.builder() : null; + ServerSentEvent.Builder sseBuilder = (shouldWrap ? ServerSentEvent.builder() : null); StringBuilder data = null; StringBuilder comment = null; for (String line : lines) { if (line.startsWith("data:")) { - data = (data != null ? data : new StringBuilder()); - if (line.charAt(5) != ' ') { - data.append(line, 5, line.length()); + int length = line.length(); + if (length > 5) { + int index = (line.charAt(5) != ' ' ? 5 : 6); + if (length > index) { + data = (data != null ? data : new StringBuilder()); + data.append(line, index, line.length()); + data.append('\n'); + } } - else { - data.append(line, 6, line.length()); - } - data.append('\n'); } - if (shouldWrap) { + else if (shouldWrap) { if (line.startsWith("id:")) { sseBuilder.id(line.substring(3).trim()); } Index: 3rdParty_sources/spring/org/springframework/http/codec/json/AbstractJackson2Encoder.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/codec/json/AbstractJackson2Encoder.java (.../AbstractJackson2Encoder.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/codec/json/AbstractJackson2Encoder.java (.../AbstractJackson2Encoder.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -196,22 +196,26 @@ public DataBuffer encodeValue(Object value, DataBufferFactory bufferFactory, ResolvableType valueType, @Nullable MimeType mimeType, @Nullable Map hints) { - ObjectMapper mapper = selectObjectMapper(valueType, mimeType); - if (mapper == null) { - throw new IllegalStateException("No ObjectMapper for " + valueType); - } Class jsonView = null; FilterProvider filters = null; if (value instanceof MappingJacksonValue) { MappingJacksonValue container = (MappingJacksonValue) value; value = container.getValue(); + valueType = ResolvableType.forInstance(value); jsonView = container.getSerializationView(); filters = container.getFilters(); } + + ObjectMapper mapper = selectObjectMapper(valueType, mimeType); + if (mapper == null) { + throw new IllegalStateException("No ObjectMapper for " + valueType); + } + ObjectWriter writer = createObjectWriter(mapper, valueType, mimeType, jsonView, hints); if (filters != null) { writer = writer.with(filters); } + ByteArrayBuilder byteBuilder = new ByteArrayBuilder(writer.getFactory()._getBufferRecycler()); try { JsonEncoding encoding = getJsonEncoding(mimeType); Index: 3rdParty_sources/spring/org/springframework/http/codec/multipart/MultipartParser.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/codec/multipart/MultipartParser.java (.../MultipartParser.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/codec/multipart/MultipartParser.java (.../MultipartParser.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -17,8 +17,12 @@ package org.springframework.http.codec.multipart; import java.nio.charset.Charset; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; +import java.util.Iterator; import java.util.List; +import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -477,11 +481,14 @@ private final DataBufferUtils.Matcher boundary; - private final AtomicReference previous = new AtomicReference<>(); + private final int boundaryLength; + private final Deque queue = new ConcurrentLinkedDeque<>(); + public BodyState() { - this.boundary = DataBufferUtils.matcher( - MultipartUtils.concat(CR_LF, TWO_HYPHENS, MultipartParser.this.boundary)); + byte[] delimiter = MultipartUtils.concat(CR_LF, TWO_HYPHENS, MultipartParser.this.boundary); + this.boundary = DataBufferUtils.matcher(delimiter); + this.boundaryLength = delimiter.length; } /** @@ -499,31 +506,38 @@ if (logger.isTraceEnabled()) { logger.trace("Boundary found @" + endIdx + " in " + buffer); } - int len = endIdx - buffer.readPosition() - this.boundary.delimiter().length + 1; + int len = endIdx - buffer.readPosition() - this.boundaryLength + 1; if (len > 0) { - // buffer contains complete delimiter, let's slice it and flush it + // whole boundary in buffer. + // slice off the body part, and flush DataBuffer body = buffer.retainedSlice(buffer.readPosition(), len); enqueue(body); - enqueue(null); + flush(); } else if (len < 0) { - // buffer starts with the end of the delimiter, let's slice the previous buffer and flush it - DataBuffer previous = this.previous.get(); - int prevLen = previous.readableByteCount() + len; - if (prevLen > 0) { - DataBuffer body = previous.retainedSlice(previous.readPosition(), prevLen); - DataBufferUtils.release(previous); - this.previous.set(body); - enqueue(null); + // boundary spans multiple buffers, and we've just found the end + // iterate over buffers in reverse order + DataBuffer prev; + while ((prev = this.queue.pollLast()) != null) { + int prevLen = prev.readableByteCount() + len; + if (prevLen > 0) { + // slice body part of previous buffer, and flush it + DataBuffer body = prev.retainedSlice(prev.readPosition(), prevLen); + DataBufferUtils.release(prev); + enqueue(body); + flush(); + break; + } + else { + // previous buffer only contains boundary bytes + DataBufferUtils.release(prev); + len += prev.readableByteCount(); + } } - else { - DataBufferUtils.release(previous); - this.previous.set(null); - } } - else /* if (sliceLength == 0) */ { - // buffer starts with complete delimiter, flush out the previous buffer - enqueue(null); + else /* if (len == 0) */ { + // buffer starts with complete delimiter, flush out the previous buffers + flush(); } DataBuffer remainder = MultipartUtils.sliceFrom(buffer, endIdx); @@ -538,15 +552,34 @@ } /** - * Stores the given buffer and sends out the previous buffer. + * Store the given buffer. Emit buffers that cannot contain boundary bytes, + * by iterating over the queue in reverse order, and summing buffer sizes. + * The first buffer that passes the boundary length and subsequent buffers + * are emitted (in the correct, non-reverse order). */ - private void enqueue(@Nullable DataBuffer buf) { - DataBuffer previous = this.previous.getAndSet(buf); - if (previous != null) { - emitBody(previous); + private void enqueue(DataBuffer buf) { + this.queue.add(buf); + + int len = 0; + Deque emit = new ArrayDeque<>(); + for (Iterator iterator = this.queue.descendingIterator(); iterator.hasNext(); ) { + DataBuffer previous = iterator.next(); + if (len > this.boundaryLength) { + // addFirst to negate iterating in reverse order + emit.addFirst(previous); + iterator.remove(); + } + len += previous.readableByteCount(); } + + emit.forEach(MultipartParser.this::emitBody); } + private void flush() { + this.queue.forEach(MultipartParser.this::emitBody); + this.queue.clear(); + } + @Override public void onComplete() { if (changeState(this, DisposedState.INSTANCE, null)) { @@ -556,10 +589,8 @@ @Override public void dispose() { - DataBuffer previous = this.previous.getAndSet(null); - if (previous != null) { - DataBufferUtils.release(previous); - } + this.queue.forEach(DataBufferUtils::release); + this.queue.clear(); } @Override Index: 3rdParty_sources/spring/org/springframework/http/converter/BufferedImageHttpMessageConverter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/converter/BufferedImageHttpMessageConverter.java (.../BufferedImageHttpMessageConverter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/converter/BufferedImageHttpMessageConverter.java (.../BufferedImageHttpMessageConverter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -45,6 +45,7 @@ import org.springframework.http.StreamingHttpOutputMessage; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.StreamUtils; import org.springframework.util.StringUtils; /** @@ -169,6 +170,8 @@ ImageInputStream imageInputStream = null; ImageReader imageReader = null; + // We cannot use try-with-resources here for the ImageInputStream, since we have + // custom handling of the close() method in a finally-block. try { imageInputStream = createImageInputStream(inputMessage.getBody()); MediaType contentType = inputMessage.getHeaders().getContentType(); @@ -205,6 +208,7 @@ } private ImageInputStream createImageInputStream(InputStream is) throws IOException { + is = StreamUtils.nonClosing(is); if (this.cacheDir != null) { return new FileCacheImageInputStream(is, this.cacheDir); } Index: 3rdParty_sources/spring/org/springframework/http/converter/ResourceHttpMessageConverter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/converter/ResourceHttpMessageConverter.java (.../ResourceHttpMessageConverter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/converter/ResourceHttpMessageConverter.java (.../ResourceHttpMessageConverter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -131,6 +131,8 @@ protected void writeContent(Resource resource, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { + // We cannot use try-with-resources here for the InputStream, since we have + // custom handling of the close() method in a finally-block. try { InputStream in = resource.getInputStream(); try { Index: 3rdParty_sources/spring/org/springframework/http/converter/ResourceRegionHttpMessageConverter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/converter/ResourceRegionHttpMessageConverter.java (.../ResourceRegionHttpMessageConverter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/converter/ResourceRegionHttpMessageConverter.java (.../ResourceRegionHttpMessageConverter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -155,6 +155,8 @@ responseHeaders.setContentLength(rangeLength); InputStream in = region.getResource().getInputStream(); + // We cannot use try-with-resources here for the InputStream, since we have + // custom handling of the close() method in a finally-block. try { StreamUtils.copyRange(in, outputMessage.getBody(), start, end); } Index: 3rdParty_sources/spring/org/springframework/http/converter/feed/AbstractWireFeedHttpMessageConverter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/converter/feed/AbstractWireFeedHttpMessageConverter.java (.../AbstractWireFeedHttpMessageConverter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/converter/feed/AbstractWireFeedHttpMessageConverter.java (.../AbstractWireFeedHttpMessageConverter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -17,6 +17,7 @@ package org.springframework.http.converter.feed; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; @@ -35,6 +36,7 @@ import org.springframework.http.converter.AbstractHttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.util.StreamUtils; import org.springframework.util.StringUtils; /** @@ -74,7 +76,8 @@ Charset charset = (contentType != null && contentType.getCharset() != null ? contentType.getCharset() : DEFAULT_CHARSET); try { - Reader reader = new InputStreamReader(inputMessage.getBody(), charset); + InputStream inputStream = StreamUtils.nonClosing(inputMessage.getBody()); + Reader reader = new InputStreamReader(inputStream, charset); return (T) feedInput.build(reader); } catch (FeedException ex) { Index: 3rdParty_sources/spring/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java (.../AbstractJackson2HttpMessageConverter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java (.../AbstractJackson2HttpMessageConverter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -17,6 +17,7 @@ package org.springframework.http.converter.json; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; @@ -361,24 +362,25 @@ "UTF-16".equals(charset.name()) || "UTF-32".equals(charset.name()); try { + InputStream inputStream = StreamUtils.nonClosing(inputMessage.getBody()); if (inputMessage instanceof MappingJacksonInputMessage) { Class deserializationView = ((MappingJacksonInputMessage) inputMessage).getDeserializationView(); if (deserializationView != null) { ObjectReader objectReader = objectMapper.readerWithView(deserializationView).forType(javaType); if (isUnicode) { - return objectReader.readValue(inputMessage.getBody()); + return objectReader.readValue(inputStream); } else { - Reader reader = new InputStreamReader(inputMessage.getBody(), charset); + Reader reader = new InputStreamReader(inputStream, charset); return objectReader.readValue(reader); } } } if (isUnicode) { - return objectMapper.readValue(inputMessage.getBody(), javaType); + return objectMapper.readValue(inputStream, javaType); } else { - Reader reader = new InputStreamReader(inputMessage.getBody(), charset); + Reader reader = new InputStreamReader(inputStream, charset); return objectMapper.readValue(reader, javaType); } } Index: 3rdParty_sources/spring/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java (.../AbstractXmlHttpMessageConverter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java (.../AbstractXmlHttpMessageConverter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -17,6 +17,7 @@ package org.springframework.http.converter.xml; import java.io.IOException; +import java.io.InputStream; import javax.xml.transform.Result; import javax.xml.transform.Source; @@ -33,6 +34,7 @@ import org.springframework.http.converter.HttpMessageConversionException; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.util.StreamUtils; /** * Abstract base class for {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters} @@ -66,7 +68,8 @@ throws IOException, HttpMessageNotReadableException { try { - return readFromSource(clazz, inputMessage.getHeaders(), new StreamSource(inputMessage.getBody())); + InputStream inputStream = StreamUtils.nonClosing(inputMessage.getBody()); + return readFromSource(clazz, inputMessage.getHeaders(), new StreamSource(inputStream)); } catch (IOException | HttpMessageConversionException ex) { throw ex; Index: 3rdParty_sources/spring/org/springframework/http/converter/xml/SourceHttpMessageConverter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/converter/xml/SourceHttpMessageConverter.java (.../SourceHttpMessageConverter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/converter/xml/SourceHttpMessageConverter.java (.../SourceHttpMessageConverter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -146,7 +146,7 @@ protected T readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - InputStream body = inputMessage.getBody(); + InputStream body = StreamUtils.nonClosing(inputMessage.getBody()); if (DOMSource.class == clazz) { return (T) readDOMSource(body, inputMessage); } Index: 3rdParty_sources/spring/org/springframework/http/server/ServletServerHttpRequest.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/server/ServletServerHttpRequest.java (.../ServletServerHttpRequest.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/server/ServletServerHttpRequest.java (.../ServletServerHttpRequest.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -158,7 +158,9 @@ String requestContentType = this.servletRequest.getContentType(); if (StringUtils.hasLength(requestContentType)) { contentType = MediaType.parseMediaType(requestContentType); - this.headers.setContentType(contentType); + if (contentType.isConcrete()) { + this.headers.setContentType(contentType); + } } } if (contentType != null && contentType.getCharset() == null) { Index: 3rdParty_sources/spring/org/springframework/http/server/reactive/AbstractListenerWriteProcessor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/server/reactive/AbstractListenerWriteProcessor.java (.../AbstractListenerWriteProcessor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/server/reactive/AbstractListenerWriteProcessor.java (.../AbstractListenerWriteProcessor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -254,7 +254,7 @@ * the next item from the upstream, write Publisher. *

The default implementation is a no-op. * @deprecated originally introduced for Undertow to stop write notifications - * when no data is available, but deprecated as of as of 5.0.6 since constant + * when no data is available, but deprecated as of 5.0.6 since constant * switching on every requested item causes a significant slowdown. */ @Deprecated Index: 3rdParty_sources/spring/org/springframework/http/server/reactive/AbstractServerHttpRequest.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/server/reactive/AbstractServerHttpRequest.java (.../AbstractServerHttpRequest.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/server/reactive/AbstractServerHttpRequest.java (.../AbstractServerHttpRequest.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -218,9 +218,18 @@ */ String getLogPrefix() { if (this.logPrefix == null) { - this.logPrefix = "[" + getId() + "] "; + this.logPrefix = "[" + initLogPrefix() + "] "; } return this.logPrefix; } + /** + * Subclasses can override this to provide the prefix to use for log messages. + *

By default, this is {@link #getId()}. + * @since 5.3.15 + */ + protected String initLogPrefix() { + return getId(); + } + } Index: 3rdParty_sources/spring/org/springframework/http/server/reactive/NettyHeadersAdapter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/server/reactive/NettyHeadersAdapter.java (.../NettyHeadersAdapter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/server/reactive/NettyHeadersAdapter.java (.../NettyHeadersAdapter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -147,7 +147,7 @@ @Override public void putAll(Map> map) { - map.forEach(this.headers::add); + map.forEach(this.headers::set); } @Override Index: 3rdParty_sources/spring/org/springframework/http/server/reactive/ReactorServerHttpRequest.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/server/reactive/ReactorServerHttpRequest.java (.../ReactorServerHttpRequest.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/server/reactive/ReactorServerHttpRequest.java (.../ReactorServerHttpRequest.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -77,7 +77,7 @@ private static URI initUri(HttpServerRequest request) throws URISyntaxException { Assert.notNull(request, "HttpServerRequest must not be null"); - return new URI(resolveBaseUrl(request).toString() + resolveRequestUri(request)); + return new URI(resolveBaseUrl(request) + resolveRequestUri(request)); } private static URI resolveBaseUrl(HttpServerRequest request) throws URISyntaxException { @@ -197,14 +197,26 @@ @Override @Nullable protected String initId() { + if (this.request instanceof Connection) { + return ((Connection) this.request).channel().id().asShortText() + + "-" + logPrefixIndex.incrementAndGet(); + } + return null; + } + + @Override + protected String initLogPrefix() { if (reactorNettyRequestChannelOperationsIdPresent) { - return (ChannelOperationsIdHelper.getId(this.request)); + String id = (ChannelOperationsIdHelper.getId(this.request)); + if (id != null) { + return id; + } } if (this.request instanceof Connection) { return ((Connection) this.request).channel().id().asShortText() + "-" + logPrefixIndex.incrementAndGet(); } - return null; + return getId(); } Index: 3rdParty_sources/spring/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java (.../ServerHttpResponseDecorator.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java (.../ServerHttpResponseDecorator.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -66,6 +66,16 @@ } @Override + public boolean setRawStatusCode(@Nullable Integer value) { + return getDelegate().setRawStatusCode(value); + } + + @Override + public Integer getRawStatusCode() { + return getDelegate().getRawStatusCode(); + } + + @Override public HttpHeaders getHeaders() { return getDelegate().getHeaders(); } Index: 3rdParty_sources/spring/org/springframework/jca/work/SimpleTaskWorkManager.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jca/work/SimpleTaskWorkManager.java (.../SimpleTaskWorkManager.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jca/work/SimpleTaskWorkManager.java (.../SimpleTaskWorkManager.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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,7 +31,6 @@ import org.springframework.core.task.SyncTaskExecutor; import org.springframework.core.task.TaskExecutor; import org.springframework.core.task.TaskRejectedException; -import org.springframework.core.task.TaskTimeoutException; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -143,6 +142,7 @@ * (or -1 if not applicable or not known) * @throws WorkException if the TaskExecutor did not accept the Work */ + @SuppressWarnings("deprecation") protected long executeWork(TaskExecutor taskExecutor, Work work, long startTimeout, boolean blockUntilStarted, @Nullable ExecutionContext executionContext, @Nullable WorkListener workListener) throws WorkException { @@ -164,7 +164,7 @@ taskExecutor.execute(workHandle); } } - catch (TaskTimeoutException ex) { + catch (org.springframework.core.task.TaskTimeoutException ex) { WorkException wex = new WorkRejectedException("TaskExecutor rejected Work because of timeout: " + work, ex); wex.setErrorCode(WorkException.START_TIMED_OUT); workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex)); Index: 3rdParty_sources/spring/org/springframework/jca/work/WorkManagerTaskExecutor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jca/work/WorkManagerTaskExecutor.java (.../WorkManagerTaskExecutor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jca/work/WorkManagerTaskExecutor.java (.../WorkManagerTaskExecutor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -33,7 +33,6 @@ import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.core.task.TaskDecorator; import org.springframework.core.task.TaskRejectedException; -import org.springframework.core.task.TaskTimeoutException; import org.springframework.jca.context.BootstrapContextAware; import org.springframework.jndi.JndiLocatorSupport; import org.springframework.lang.Nullable; @@ -218,11 +217,13 @@ // Implementation of the Spring SchedulingTaskExecutor interface //------------------------------------------------------------------------- + @SuppressWarnings("deprecation") @Override public void execute(Runnable task) { execute(task, TIMEOUT_INDEFINITE); } + @Deprecated @Override public void execute(Runnable task, long startTimeout) { Work work = new DelegatingWork(this.taskDecorator != null ? this.taskDecorator.decorate(task) : task); @@ -254,7 +255,8 @@ } catch (WorkRejectedException ex) { if (WorkException.START_TIMED_OUT.equals(ex.getErrorCode())) { - throw new TaskTimeoutException("JCA WorkManager rejected task because of timeout: " + task, ex); + throw new org.springframework.core.task.TaskTimeoutException( + "JCA WorkManager rejected task because of timeout: " + task, ex); } else { throw new TaskRejectedException("JCA WorkManager rejected task: " + task, ex); @@ -265,27 +267,31 @@ } } + @SuppressWarnings("deprecation") @Override public Future submit(Runnable task) { FutureTask future = new FutureTask<>(task, null); execute(future, TIMEOUT_INDEFINITE); return future; } + @SuppressWarnings("deprecation") @Override public Future submit(Callable task) { FutureTask future = new FutureTask<>(task); execute(future, TIMEOUT_INDEFINITE); return future; } + @SuppressWarnings("deprecation") @Override public ListenableFuture submitListenable(Runnable task) { ListenableFutureTask future = new ListenableFutureTask<>(task, null); execute(future, TIMEOUT_INDEFINITE); return future; } + @SuppressWarnings("deprecation") @Override public ListenableFuture submitListenable(Callable task) { ListenableFutureTask future = new ListenableFutureTask<>(task); Index: 3rdParty_sources/spring/org/springframework/jdbc/core/BeanPropertyRowMapper.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jdbc/core/BeanPropertyRowMapper.java (.../BeanPropertyRowMapper.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jdbc/core/BeanPropertyRowMapper.java (.../BeanPropertyRowMapper.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -273,7 +273,8 @@ } StringBuilder result = new StringBuilder(); - for (int i = 0; i < name.length(); i++) { + result.append(Character.toLowerCase(name.charAt(0))); + for (int i = 1; i < name.length(); i++) { char c = name.charAt(i); if (Character.isUpperCase(c)) { result.append('_').append(Character.toLowerCase(c)); @@ -340,12 +341,6 @@ "Unable to map column '" + column + "' to property '" + pd.getName() + "'", ex); } } - else { - // No PropertyDescriptor found - if (rowNumber == 0 && logger.isDebugEnabled()) { - logger.debug("No property found for column '" + column + "' mapped to field '" + field + "'"); - } - } } if (populatedProperties != null && !populatedProperties.equals(this.mappedProperties)) { Index: 3rdParty_sources/spring/org/springframework/jdbc/datasource/init/DatabasePopulator.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jdbc/datasource/init/DatabasePopulator.java (.../DatabasePopulator.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jdbc/datasource/init/DatabasePopulator.java (.../DatabasePopulator.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2022 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. @@ -35,15 +35,17 @@ /** * Populate, initialize, or clean up the database using the provided JDBC * connection. + *

Warning: Concrete implementations should not close + * the provided {@link Connection}. *

Concrete implementations may throw an {@link SQLException} if * an error is encountered but are strongly encouraged to throw a * specific {@link ScriptException} instead. For example, Spring's * {@link ResourceDatabasePopulator} and {@link DatabasePopulatorUtils} wrap * all {@code SQLExceptions} in {@code ScriptExceptions}. - * @param connection the JDBC connection to use to populate the db; already - * configured and ready to use; never {@code null} + * @param connection the JDBC connection to use; already configured and + * ready to use; never {@code null} * @throws SQLException if an unrecoverable data access exception occurs - * during database population + * while interacting with the database * @throws ScriptException in all other error cases * @see DatabasePopulatorUtils#execute */ Index: 3rdParty_sources/spring/org/springframework/jdbc/object/StoredProcedure.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jdbc/object/StoredProcedure.java (.../StoredProcedure.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jdbc/object/StoredProcedure.java (.../StoredProcedure.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -87,6 +87,8 @@ * they appear in the database's stored procedure parameter list. *

Names are purely used to help mapping. * @param param the parameter object + * @throws InvalidDataAccessApiUsageException if the parameter has no name, or if the + * operation is already compiled, and hence cannot be configured further */ @Override public void declareParameter(SqlParameter param) throws InvalidDataAccessApiUsageException { Index: 3rdParty_sources/spring/org/springframework/jdbc/support/incrementer/H2SequenceMaxValueIncrementer.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jdbc/support/incrementer/H2SequenceMaxValueIncrementer.java (.../H2SequenceMaxValueIncrementer.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jdbc/support/incrementer/H2SequenceMaxValueIncrementer.java (.../H2SequenceMaxValueIncrementer.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -23,6 +23,7 @@ * of a given H2 sequence. * * @author Thomas Risberg + * @author Henning Pöttker * @since 2.5 */ public class H2SequenceMaxValueIncrementer extends AbstractSequenceMaxValueIncrementer { @@ -47,7 +48,7 @@ @Override protected String getSequenceQuery() { - return "select " + getIncrementerName() + ".nextval from dual"; + return "values next value for " + getIncrementerName(); } } Index: 3rdParty_sources/spring/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java (.../AnnotationJmxAttributeSource.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java (.../AnnotationJmxAttributeSource.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -46,7 +46,7 @@ import org.springframework.util.StringValueResolver; /** - * Implementation of the {@code JmxAttributeSource} interface that + * Implementation of the {@link JmxAttributeSource} interface that * reads annotations and exposes the corresponding attributes. * * @author Rob Harrop Index: 3rdParty_sources/spring/org/springframework/jmx/export/annotation/AnnotationMBeanExporter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/annotation/AnnotationMBeanExporter.java (.../AnnotationMBeanExporter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/annotation/AnnotationMBeanExporter.java (.../AnnotationMBeanExporter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2022 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. @@ -23,7 +23,7 @@ /** * Convenient subclass of Spring's standard {@link MBeanExporter}, - * activating Java 5 annotation usage for JMX exposure of Spring beans: + * activating annotation usage for JMX exposure of Spring beans: * {@link ManagedResource}, {@link ManagedAttribute}, {@link ManagedOperation}, etc. * *

Sets a {@link MetadataNamingStrategy} and a {@link MetadataMBeanInfoAssembler} Index: 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedMetric.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedMetric.java (.../ManagedMetric.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedMetric.java (.../ManagedMetric.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -27,8 +27,9 @@ /** * Method-level annotation that indicates to expose a given bean property as a * JMX attribute, with added descriptor properties to indicate that it is a metric. - * Only valid when used on a JavaBean getter. * + *

Only valid when used on a JavaBean getter. + * * @author Jennifer Hickey * @since 3.0 * @see org.springframework.jmx.export.metadata.ManagedMetric Index: 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedNotification.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedNotification.java (.../ManagedNotification.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedNotification.java (.../ManagedNotification.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2022 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,10 +27,12 @@ /** * Type-level annotation that indicates a JMX notification emitted by a bean. * - *

As of Spring Framework 4.2.4, this annotation is declared as repeatable. + *

This annotation is a {@linkplain java.lang.annotation.Repeatable repeatable} + * annotation. * * @author Rob Harrop * @since 2.0 + * @see ManagedNotifications * @see org.springframework.jmx.export.metadata.ManagedNotification */ @Target(ElementType.TYPE) Index: 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedNotifications.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedNotifications.java (.../ManagedNotifications.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedNotifications.java (.../ManagedNotifications.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2022 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. @@ -24,9 +24,13 @@ import java.lang.annotation.Target; /** - * Type-level annotation that indicates JMX notifications emitted by a bean, - * containing multiple {@link ManagedNotification ManagedNotifications}. + * Type-level annotation used as a container for one or more + * {@code @ManagedNotification} declarations. * + *

Note, however, that use of the {@code @ManagedNotifications} container + * is completely optional since {@code @ManagedNotification} is a + * {@linkplain java.lang.annotation.Repeatable repeatable} annotation. + * * @author Rob Harrop * @since 2.0 */ Index: 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedOperation.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedOperation.java (.../ManagedOperation.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedOperation.java (.../ManagedOperation.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2022 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. @@ -23,10 +23,12 @@ import java.lang.annotation.Target; /** - * Method-level annotation that indicates to expose a given method as a - * JMX operation, corresponding to the {@code ManagedOperation} attribute. - * Only valid when used on a method that is not a JavaBean getter or setter. + * Method-level annotation that indicates to expose a given method as a JMX operation, + * corresponding to the {@link org.springframework.jmx.export.metadata.ManagedOperation} + * attribute. * + *

Only valid when used on a method that is not a JavaBean getter or setter. + * * @author Rob Harrop * @since 1.2 * @see org.springframework.jmx.export.metadata.ManagedOperation Index: 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedOperationParameter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedOperationParameter.java (.../ManagedOperationParameter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedOperationParameter.java (.../ManagedOperationParameter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2022 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. @@ -24,15 +24,15 @@ import java.lang.annotation.Target; /** - * Method-level annotation used to provide metadata about operation parameters, - * corresponding to a {@code ManagedOperationParameter} attribute. - * Used as part of a {@link ManagedOperationParameters} annotation. + * Method-level annotation used to provide metadata about operation parameters, corresponding + * to a {@link org.springframework.jmx.export.metadata.ManagedOperationParameter} attribute. * - *

As of Spring Framework 4.2.4, this annotation is declared as repeatable. + *

This annotation is a {@linkplain java.lang.annotation.Repeatable repeatable} + * annotation. * * @author Rob Harrop * @since 1.2 - * @see ManagedOperationParameters#value + * @see ManagedOperationParameters * @see org.springframework.jmx.export.metadata.ManagedOperationParameter */ @Target(ElementType.METHOD) Index: 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedOperationParameters.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedOperationParameters.java (.../ManagedOperationParameters.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedOperationParameters.java (.../ManagedOperationParameters.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2022 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. @@ -23,9 +23,13 @@ import java.lang.annotation.Target; /** - * Method-level annotation used to provide metadata about operation parameters, - * corresponding to an array of {@code ManagedOperationParameter} attributes. + * Method-level annotation used as a container for one or more + * {@code @ManagedOperationParameter} declarations. * + *

Note, however, that use of the {@code @ManagedOperationParameters} container + * is completely optional since {@code @ManagedOperationParameter} is a + * {@linkplain java.lang.annotation.Repeatable repeatable} annotation. + * * @author Rob Harrop * @since 1.2 * @see org.springframework.jmx.export.metadata.ManagedOperationParameter Index: 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedResource.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedResource.java (.../ManagedResource.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/annotation/ManagedResource.java (.../ManagedResource.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2022 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. @@ -26,8 +26,8 @@ import org.springframework.core.annotation.AliasFor; /** - * Class-level annotation that indicates to register instances of a class - * with a JMX server, corresponding to the {@code ManagedResource} attribute. + * Class-level annotation that indicates to register instances of a class with a JMX server, + * corresponding to the {@link org.springframework.jmx.export.metadata.ManagedResource} attribute. * *

Note: This annotation is marked as inherited, allowing for generic * management-aware base classes. In such a scenario, it is recommended to Index: 3rdParty_sources/spring/org/springframework/jmx/export/annotation/package-info.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/annotation/package-info.java (.../package-info.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/annotation/package-info.java (.../package-info.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,7 +1,8 @@ /** - * Java 5 annotations for MBean exposure. - * Hooked into Spring's JMX export infrastructure - * via a special JmxAttributeSource implementation. + * Annotations for MBean exposure. + * + *

Hooked into Spring's JMX export infrastructure via a special + * {@link org.springframework.jmx.export.metadata.JmxAttributeSource} implementation. */ @NonNullApi @NonNullFields Index: 3rdParty_sources/spring/org/springframework/jmx/export/naming/MetadataNamingStrategy.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/jmx/export/naming/MetadataNamingStrategy.java (.../MetadataNamingStrategy.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/jmx/export/naming/MetadataNamingStrategy.java (.../MetadataNamingStrategy.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -40,7 +40,7 @@ *

Uses the {@link JmxAttributeSource} strategy interface, so that * metadata can be read using any supported implementation. Out of the box, * {@link org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource} - * introspects a well-defined set of Java 5 annotations that come with Spring. + * introspects a well-defined set of annotations that come with Spring. * * @author Rob Harrop * @author Juergen Hoeller Index: 3rdParty_sources/spring/org/springframework/orm/hibernate5/SessionFactoryUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/orm/hibernate5/SessionFactoryUtils.java (.../SessionFactoryUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/orm/hibernate5/SessionFactoryUtils.java (.../SessionFactoryUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -133,7 +133,9 @@ public static void closeSession(@Nullable Session session) { if (session != null) { try { - session.close(); + if (session.isOpen()) { + session.close(); + } } catch (Throwable ex) { logger.error("Failed to release Hibernate Session", ex); Index: 3rdParty_sources/spring/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java (.../HibernateJpaDialect.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java (.../HibernateJpaDialect.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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,7 +80,7 @@ * @author Costin Leau * @since 2.0 * @see HibernateJpaVendorAdapter - * @see org.hibernate.Session#setFlushMode + * @see org.hibernate.Session#setHibernateFlushMode * @see org.hibernate.Transaction#setTimeout */ @SuppressWarnings("serial") @@ -360,10 +360,9 @@ this.readOnly = readOnly; } - @SuppressWarnings("deprecation") public void resetSessionState() { if (this.previousFlushMode != null) { - this.session.setFlushMode(this.previousFlushMode); + this.session.setHibernateFlushMode(this.previousFlushMode); } if (this.needsConnectionReset && this.session.getJdbcCoordinator().getLogicalConnection().isPhysicallyConnected()) { Index: 3rdParty_sources/spring/org/springframework/scheduling/annotation/AbstractAsyncConfiguration.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/annotation/AbstractAsyncConfiguration.java (.../AbstractAsyncConfiguration.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/annotation/AbstractAsyncConfiguration.java (.../AbstractAsyncConfiguration.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -16,18 +16,22 @@ package org.springframework.scheduling.annotation; -import java.util.Collection; +import java.util.List; import java.util.concurrent.Executor; +import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collectors; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportAware; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; +import org.springframework.util.function.SingletonSupplier; /** * Abstract base {@code Configuration} class providing common structure for enabling @@ -55,7 +59,7 @@ @Override public void setImportMetadata(AnnotationMetadata importMetadata) { this.enableAsync = AnnotationAttributes.fromMap( - importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false)); + importMetadata.getAnnotationAttributes(EnableAsync.class.getName())); if (this.enableAsync == null) { throw new IllegalArgumentException( "@EnableAsync is not present on importing class " + importMetadata.getClassName()); @@ -65,17 +69,27 @@ /** * Collect any {@link AsyncConfigurer} beans through autowiring. */ - @Autowired(required = false) - void setConfigurers(Collection configurers) { - if (CollectionUtils.isEmpty(configurers)) { - return; - } - if (configurers.size() > 1) { - throw new IllegalStateException("Only one AsyncConfigurer may exist"); - } - AsyncConfigurer configurer = configurers.iterator().next(); - this.executor = configurer::getAsyncExecutor; - this.exceptionHandler = configurer::getAsyncUncaughtExceptionHandler; + @Autowired + void setConfigurers(ObjectProvider configurers) { + Supplier configurer = SingletonSupplier.of(() -> { + List candidates = configurers.stream().collect(Collectors.toList()); + if (CollectionUtils.isEmpty(candidates)) { + return null; + } + if (candidates.size() > 1) { + throw new IllegalStateException("Only one AsyncConfigurer may exist"); + } + return candidates.get(0); + }); + this.executor = adapt(configurer, AsyncConfigurer::getAsyncExecutor); + this.exceptionHandler = adapt(configurer, AsyncConfigurer::getAsyncUncaughtExceptionHandler); } + private Supplier adapt(Supplier supplier, Function provider) { + return () -> { + AsyncConfigurer configurer = supplier.get(); + return (configurer != null ? provider.apply(configurer) : null); + }; + } + } Index: 3rdParty_sources/spring/org/springframework/scheduling/annotation/AsyncConfigurer.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/annotation/AsyncConfigurer.java (.../AsyncConfigurer.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/annotation/AsyncConfigurer.java (.../AsyncConfigurer.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2021 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. @@ -28,19 +28,13 @@ * {@link AsyncUncaughtExceptionHandler} instance used to process exception thrown from * async method with {@code void} return type. * - *

Consider using {@link AsyncConfigurerSupport} providing default implementations for - * both methods if only one element needs to be customized. Furthermore, backward compatibility - * of this interface will be insured in case new customization options are introduced - * in the future. - * *

See @{@link EnableAsync} for usage examples. * * @author Chris Beams * @author Stephane Nicoll * @since 3.1 * @see AbstractAsyncConfiguration * @see EnableAsync - * @see AsyncConfigurerSupport */ public interface AsyncConfigurer { Index: 3rdParty_sources/spring/org/springframework/scheduling/annotation/package-info.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/annotation/package-info.java (.../package-info.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/annotation/package-info.java (.../package-info.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /** - * Java 5 annotation for asynchronous method execution. + * Annotation support for asynchronous method execution. */ @NonNullApi @NonNullFields Index: 3rdParty_sources/spring/org/springframework/scheduling/commonj/WorkManagerTaskExecutor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/commonj/WorkManagerTaskExecutor.java (.../WorkManagerTaskExecutor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/commonj/WorkManagerTaskExecutor.java (.../WorkManagerTaskExecutor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -171,6 +171,7 @@ } } + @Deprecated @Override public void execute(Runnable task, long startTimeout) { execute(task); Index: 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ConcurrentTaskExecutor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ConcurrentTaskExecutor.java (.../ConcurrentTaskExecutor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ConcurrentTaskExecutor.java (.../ConcurrentTaskExecutor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -147,6 +147,7 @@ this.adaptedExecutor.execute(task); } + @Deprecated @Override public void execute(Runnable task, long startTimeout) { this.adaptedExecutor.execute(task, startTimeout); Index: 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBean.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBean.java (.../ThreadPoolExecutorFactoryBean.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ThreadPoolExecutorFactoryBean.java (.../ThreadPoolExecutorFactoryBean.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -26,9 +26,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; import org.springframework.lang.Nullable; /** @@ -65,7 +63,7 @@ */ @SuppressWarnings("serial") public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport - implements FactoryBean, InitializingBean, DisposableBean { + implements FactoryBean { private int corePoolSize = 1; @@ -75,6 +73,8 @@ private boolean allowCoreThreadTimeOut = false; + private boolean prestartAllCoreThreads = false; + private int queueCapacity = Integer.MAX_VALUE; private boolean exposeUnconfigurableExecutor = false; @@ -119,6 +119,16 @@ } /** + * Specify whether to start all core threads, causing them to idly wait for work. + *

Default is "false". + * @since 5.3.14 + * @see java.util.concurrent.ThreadPoolExecutor#prestartAllCoreThreads + */ + public void setPrestartAllCoreThreads(boolean prestartAllCoreThreads) { + this.prestartAllCoreThreads = prestartAllCoreThreads; + } + + /** * Set the capacity for the ThreadPoolExecutor's BlockingQueue. * Default is {@code Integer.MAX_VALUE}. *

Any positive value will lead to a LinkedBlockingQueue instance; @@ -153,6 +163,9 @@ if (this.allowCoreThreadTimeOut) { executor.allowCoreThreadTimeOut(true); } + if (this.prestartAllCoreThreads) { + executor.prestartAllCoreThreads(); + } // Wrap executor with an unconfigurable decorator. this.exposedExecutor = (this.exposeUnconfigurableExecutor ? Index: 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java (.../ThreadPoolTaskExecutor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java (.../ThreadPoolTaskExecutor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -94,6 +94,8 @@ private boolean allowCoreThreadTimeOut = false; + private boolean prestartAllCoreThreads = false; + @Nullable private TaskDecorator taskDecorator; @@ -198,6 +200,16 @@ } /** + * Specify whether to start all core threads, causing them to idly wait for work. + *

Default is "false". + * @since 5.3.14 + * @see java.util.concurrent.ThreadPoolExecutor#prestartAllCoreThreads + */ + public void setPrestartAllCoreThreads(boolean prestartAllCoreThreads) { + this.prestartAllCoreThreads = prestartAllCoreThreads; + } + + /** * Specify a custom {@link TaskDecorator} to be applied to any {@link Runnable} * about to be executed. *

Note that such a decorator is not necessarily being applied to the @@ -256,6 +268,9 @@ if (this.allowCoreThreadTimeOut) { executor.allowCoreThreadTimeOut(true); } + if (this.prestartAllCoreThreads) { + executor.prestartAllCoreThreads(); + } this.threadPoolExecutor = executor; return executor; @@ -325,6 +340,7 @@ } } + @Deprecated @Override public void execute(Runnable task, long startTimeout) { execute(task); Index: 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java (.../ThreadPoolTaskScheduler.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java (.../ThreadPoolTaskScheduler.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -282,6 +282,7 @@ } } + @Deprecated @Override public void execute(Runnable task, long startTimeout) { execute(task); Index: 3rdParty_sources/spring/org/springframework/scheduling/config/ScheduledTask.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/config/ScheduledTask.java (.../ScheduledTask.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/config/ScheduledTask.java (.../ScheduledTask.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -29,6 +29,7 @@ * @see ScheduledTaskRegistrar#scheduleCronTask(CronTask) * @see ScheduledTaskRegistrar#scheduleFixedRateTask(FixedRateTask) * @see ScheduledTaskRegistrar#scheduleFixedDelayTask(FixedDelayTask) + * @see ScheduledFuture */ public final class ScheduledTask { @@ -54,11 +55,24 @@ /** * Trigger cancellation of this scheduled task. + *

This variant will force interruption of the task if still running. + * @see #cancel(boolean) */ public void cancel() { + cancel(true); + } + + /** + * Trigger cancellation of this scheduled task. + * @param mayInterruptIfRunning whether to force interruption of the task + * if still running (specify {@code false} to allow the task to complete) + * @since 5.3.18 + * @see ScheduledFuture#cancel(boolean) + */ + public void cancel(boolean mayInterruptIfRunning) { ScheduledFuture future = this.future; if (future != null) { - future.cancel(true); + future.cancel(mayInterruptIfRunning); } } Index: 3rdParty_sources/spring/org/springframework/scheduling/quartz/LocalDataSourceJobStore.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/quartz/LocalDataSourceJobStore.java (.../LocalDataSourceJobStore.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/quartz/LocalDataSourceJobStore.java (.../LocalDataSourceJobStore.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -39,6 +39,8 @@ * Subclass of Quartz's {@link JobStoreCMT} class that delegates to a Spring-managed * {@link DataSource} instead of using a Quartz-managed JDBC connection pool. * This JobStore will be used if SchedulerFactoryBean's "dataSource" property is set. + * You may also configure it explicitly, possibly as a custom subclass of this + * {@code LocalDataSourceJobStore} or as an equivalent {@code JobStoreCMT} variant. * *

Supports both transactional and non-transactional DataSource access. * With a non-XA DataSource and local Spring transactions, a single DataSource @@ -58,6 +60,8 @@ * @since 1.1 * @see SchedulerFactoryBean#setDataSource * @see SchedulerFactoryBean#setNonTransactionalDataSource + * @see SchedulerFactoryBean#getConfigTimeDataSource() + * @see SchedulerFactoryBean#getConfigTimeNonTransactionalDataSource() * @see org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection * @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection */ Index: 3rdParty_sources/spring/org/springframework/scheduling/quartz/SchedulerFactoryBean.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/quartz/SchedulerFactoryBean.java (.../SchedulerFactoryBean.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/quartz/SchedulerFactoryBean.java (.../SchedulerFactoryBean.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -310,9 +310,11 @@ /** * Set the default {@link DataSource} to be used by the Scheduler. - * If set, this will override corresponding settings in Quartz properties. *

Note: If this is set, the Quartz settings should not define * a job store "dataSource" to avoid meaningless double configuration. + * Also, do not define a "org.quartz.jobStore.class" property at all. + * (You may explicitly define Spring's {@link LocalDataSourceJobStore} + * but that's the default when using this method anyway.) *

A Spring-specific subclass of Quartz' JobStoreCMT will be used. * It is therefore strongly recommended to perform all operations on * the Scheduler within Spring-managed (or plain JTA) transactions. Index: 3rdParty_sources/spring/org/springframework/scheduling/quartz/SimpleThreadPoolTaskExecutor.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/quartz/SimpleThreadPoolTaskExecutor.java (.../SimpleThreadPoolTaskExecutor.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/quartz/SimpleThreadPoolTaskExecutor.java (.../SimpleThreadPoolTaskExecutor.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -76,6 +76,7 @@ } } + @Deprecated @Override public void execute(Runnable task, long startTimeout) { execute(task); Index: 3rdParty_sources/spring/org/springframework/scheduling/support/CronField.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/support/CronField.java (.../CronField.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/support/CronField.java (.../CronField.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -18,6 +18,7 @@ import java.time.DateTimeException; import java.time.temporal.ChronoField; +import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal; import java.time.temporal.ValueRange; import java.util.function.BiFunction; @@ -168,22 +169,25 @@ * day-of-month, month, day-of-week. */ protected enum Type { - NANO(ChronoField.NANO_OF_SECOND), - SECOND(ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND), - MINUTE(ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND), - HOUR(ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND), - DAY_OF_MONTH(ChronoField.DAY_OF_MONTH, ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND), - MONTH(ChronoField.MONTH_OF_YEAR, ChronoField.DAY_OF_MONTH, ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND), - DAY_OF_WEEK(ChronoField.DAY_OF_WEEK, ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND); + NANO(ChronoField.NANO_OF_SECOND, ChronoUnit.SECONDS), + SECOND(ChronoField.SECOND_OF_MINUTE, ChronoUnit.MINUTES, ChronoField.NANO_OF_SECOND), + MINUTE(ChronoField.MINUTE_OF_HOUR, ChronoUnit.HOURS, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND), + HOUR(ChronoField.HOUR_OF_DAY, ChronoUnit.DAYS, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND), + DAY_OF_MONTH(ChronoField.DAY_OF_MONTH, ChronoUnit.MONTHS, ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND), + MONTH(ChronoField.MONTH_OF_YEAR, ChronoUnit.YEARS, ChronoField.DAY_OF_MONTH, ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND), + DAY_OF_WEEK(ChronoField.DAY_OF_WEEK, ChronoUnit.WEEKS, ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND); private final ChronoField field; + private final ChronoUnit higherOrder; + private final ChronoField[] lowerOrders; - Type(ChronoField field, ChronoField... lowerOrders) { + Type(ChronoField field, ChronoUnit higherOrder, ChronoField... lowerOrders) { this.field = field; + this.higherOrder = higherOrder; this.lowerOrders = lowerOrders; } @@ -266,10 +270,9 @@ * @return the rolled forward temporal */ public > T rollForward(T temporal) { - int current = get(temporal); - ValueRange range = temporal.range(this.field); - long amount = range.getMaximum() - current + 1; - return this.field.getBaseUnit().addTo(temporal, amount); + T result = this.higherOrder.addTo(temporal, 1); + ValueRange range = result.range(this.field); + return this.field.adjustInto(result, range.getMinimum()); } /** Index: 3rdParty_sources/spring/org/springframework/scheduling/support/QuartzCronField.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/scheduling/support/QuartzCronField.java (.../QuartzCronField.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/scheduling/support/QuartzCronField.java (.../QuartzCronField.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -251,43 +251,46 @@ private static TemporalAdjuster weekdayNearestTo(int dayOfMonth) { return temporal -> { int current = Type.DAY_OF_MONTH.get(temporal); - int dayOfWeek = temporal.get(ChronoField.DAY_OF_WEEK); + DayOfWeek dayOfWeek = DayOfWeek.from(temporal); - if ((current == dayOfMonth && dayOfWeek < 6) || // dayOfMonth is a weekday - (dayOfWeek == 5 && current == dayOfMonth - 1) || // dayOfMonth is a Saturday, so Friday before - (dayOfWeek == 1 && current == dayOfMonth + 1) || // dayOfMonth is a Sunday, so Monday after - (dayOfWeek == 1 && dayOfMonth == 1 && current == 3)) { // dayOfMonth is the 1st, so Monday 3rd + if ((current == dayOfMonth && isWeekday(dayOfWeek)) || // dayOfMonth is a weekday + (dayOfWeek == DayOfWeek.FRIDAY && current == dayOfMonth - 1) || // dayOfMonth is a Saturday, so Friday before + (dayOfWeek == DayOfWeek.MONDAY && current == dayOfMonth + 1) || // dayOfMonth is a Sunday, so Monday after + (dayOfWeek == DayOfWeek.MONDAY && dayOfMonth == 1 && current == 3)) { // dayOfMonth is Saturday 1st, so Monday 3rd return temporal; } int count = 0; while (count++ < CronExpression.MAX_ATTEMPTS) { - temporal = Type.DAY_OF_MONTH.elapseUntil(cast(temporal), dayOfMonth); - temporal = atMidnight().adjustInto(temporal); - current = Type.DAY_OF_MONTH.get(temporal); if (current == dayOfMonth) { - dayOfWeek = temporal.get(ChronoField.DAY_OF_WEEK); + dayOfWeek = DayOfWeek.from(temporal); - if (dayOfWeek == 6) { // Saturday + if (dayOfWeek == DayOfWeek.SATURDAY) { if (dayOfMonth != 1) { - return temporal.minus(1, ChronoUnit.DAYS); + temporal = temporal.minus(1, ChronoUnit.DAYS); } else { - // exception for "1W" fields: execute on nearest Monday - return temporal.plus(2, ChronoUnit.DAYS); + // exception for "1W" fields: execute on next Monday + temporal = temporal.plus(2, ChronoUnit.DAYS); } } - else if (dayOfWeek == 7) { // Sunday - return temporal.plus(1, ChronoUnit.DAYS); + else if (dayOfWeek == DayOfWeek.SUNDAY) { + temporal = temporal.plus(1, ChronoUnit.DAYS); } - else { - return temporal; - } + return atMidnight().adjustInto(temporal); } + else { + temporal = Type.DAY_OF_MONTH.elapseUntil(cast(temporal), dayOfMonth); + current = Type.DAY_OF_MONTH.get(temporal); + } } return null; }; } + private static boolean isWeekday(DayOfWeek dayOfWeek) { + return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY; + } + /** * Return a temporal adjuster that finds the last of the given doy-of-week * in a month. Index: 3rdParty_sources/spring/org/springframework/stereotype/Controller.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/stereotype/Controller.java (.../Controller.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/stereotype/Controller.java (.../Controller.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -39,7 +39,7 @@ * @see org.springframework.web.bind.annotation.RequestMapping * @see org.springframework.context.annotation.ClassPathBeanDefinitionScanner */ -@Target({ElementType.TYPE}) +@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component Index: 3rdParty_sources/spring/org/springframework/stereotype/Repository.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/stereotype/Repository.java (.../Repository.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/stereotype/Repository.java (.../Repository.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -55,7 +55,7 @@ * @see org.springframework.dao.DataAccessException * @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor */ -@Target({ElementType.TYPE}) +@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component Index: 3rdParty_sources/spring/org/springframework/stereotype/Service.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/stereotype/Service.java (.../Service.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/stereotype/Service.java (.../Service.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -41,7 +41,7 @@ * @see Component * @see Repository */ -@Target({ElementType.TYPE}) +@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component Index: 3rdParty_sources/spring/org/springframework/transaction/annotation/AbstractTransactionManagementConfiguration.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/transaction/annotation/AbstractTransactionManagementConfiguration.java (.../AbstractTransactionManagementConfiguration.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/transaction/annotation/AbstractTransactionManagementConfiguration.java (.../AbstractTransactionManagementConfiguration.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -57,7 +57,7 @@ @Override public void setImportMetadata(AnnotationMetadata importMetadata) { this.enableTx = AnnotationAttributes.fromMap( - importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false)); + importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName())); if (this.enableTx == null) { throw new IllegalArgumentException( "@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName()); Index: 3rdParty_sources/spring/org/springframework/transaction/annotation/Transactional.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/transaction/annotation/Transactional.java (.../Transactional.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/transaction/annotation/Transactional.java (.../Transactional.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -37,18 +37,58 @@ * Transaction Management * section of the reference manual. * - *

This annotation type is generally directly comparable to Spring's + *

This annotation is generally directly comparable to Spring's * {@link org.springframework.transaction.interceptor.RuleBasedTransactionAttribute} * class, and in fact {@link AnnotationTransactionAttributeSource} will directly - * convert the data to the latter class, so that Spring's transaction support code - * does not have to know about annotations. If no custom rollback rules apply, - * the transaction will roll back on {@link RuntimeException} and {@link Error} - * but not on checked exceptions. + * convert this annotation's attributes to properties in {@code RuleBasedTransactionAttribute}, + * so that Spring's transaction support code does not have to know about annotations. * - *

For specific information about the semantics of this annotation's attributes, - * consult the {@link org.springframework.transaction.TransactionDefinition} and - * {@link org.springframework.transaction.interceptor.TransactionAttribute} javadocs. + *

Attribute Semantics

* + *

If no custom rollback rules are configured in this annotation, the transaction + * will roll back on {@link RuntimeException} and {@link Error} but not on checked + * exceptions. + * + *

Rollback rules determine if a transaction should be rolled back when a given + * exception is thrown, and the rules are based on patterns. A pattern can be a + * fully qualified class name or a substring of a fully qualified class name for + * an exception type (which must be a subclass of {@code Throwable}), with no + * wildcard support at present. For example, a value of + * {@code "javax.servlet.ServletException"} or {@code "ServletException"} will + * match {@code javax.servlet.ServletException} and its subclasses. + * + *

Rollback rules may be configured via {@link #rollbackFor}/{@link #noRollbackFor} + * and {@link #rollbackForClassName}/{@link #noRollbackForClassName}, which allow + * patterns to be specified as {@link Class} references or {@linkplain String + * strings}, respectively. When an exception type is specified as a class reference + * its fully qualified name will be used as the pattern. Consequently, + * {@code @Transactional(rollbackFor = example.CustomException.class)} is equivalent + * to {@code @Transactional(rollbackForClassName = "example.CustomException")}. + * + *

WARNING: You must carefully consider how specific the pattern + * is and whether to include package information (which isn't mandatory). For example, + * {@code "Exception"} will match nearly anything and will probably hide other + * rules. {@code "java.lang.Exception"} would be correct if {@code "Exception"} + * were meant to define a rule for all checked exceptions. With more unique + * exception names such as {@code "BaseBusinessException"} there is likely no + * need to use the fully qualified class name for the exception pattern. Furthermore, + * rollback rules may result in unintentional matches for similarly named exceptions + * and nested classes. This is due to the fact that a thrown exception is considered + * to be a match for a given rollback rule if the name of thrown exception contains + * the exception pattern configured for the rollback rule. For example, given a + * rule configured to match on {@code com.example.CustomException}, that rule + * would match against an exception named + * {@code com.example.CustomExceptionV2} (an exception in the same package as + * {@code CustomException} but with an additional suffix) or an exception named + * {@code com.example.CustomException$AnotherException} + * (an exception declared as a nested class in {@code CustomException}). + * + *

For specific information about the semantics of other attributes in this + * annotation, consult the {@link org.springframework.transaction.TransactionDefinition} + * and {@link org.springframework.transaction.interceptor.TransactionAttribute} javadocs. + * + *

Transaction Management

+ * *

This annotation commonly works with thread-bound transactions managed by a * {@link org.springframework.transaction.PlatformTransactionManager}, exposing a * transaction to all data access operations within the current execution thread. @@ -167,37 +207,33 @@ boolean readOnly() default false; /** - * Defines zero (0) or more exception {@link Class classes}, which must be + * Defines zero (0) or more exception {@linkplain Class classes}, which must be * subclasses of {@link Throwable}, indicating which exception types must cause * a transaction rollback. - *

By default, a transaction will be rolling back on {@link RuntimeException} + *

By default, a transaction will be rolled back on {@link RuntimeException} * and {@link Error} but not on checked exceptions (business exceptions). See * {@link org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)} * for a detailed explanation. *

This is the preferred way to construct a rollback rule (in contrast to - * {@link #rollbackForClassName}), matching the exception class and its subclasses. - *

Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)}. + * {@link #rollbackForClassName}), matching the exception type, its subclasses, + * and its nested classes. See the {@linkplain Transactional class-level javadocs} + * for further details on rollback rule semantics and warnings regarding possible + * unintentional matches. * @see #rollbackForClassName + * @see org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class) * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable) */ Class[] rollbackFor() default {}; /** - * Defines zero (0) or more exception names (for exceptions which must be a + * Defines zero (0) or more exception name patterns (for exceptions which must be a * subclass of {@link Throwable}), indicating which exception types must cause * a transaction rollback. - *

This can be a substring of a fully qualified class name, with no wildcard - * support at present. For example, a value of {@code "ServletException"} would - * match {@code javax.servlet.ServletException} and its subclasses. - *

NB: Consider carefully how specific the pattern is and whether - * to include package information (which isn't mandatory). For example, - * {@code "Exception"} will match nearly anything and will probably hide other - * rules. {@code "java.lang.Exception"} would be correct if {@code "Exception"} - * were meant to define a rule for all checked exceptions. With more unusual - * {@link Exception} names such as {@code "BaseBusinessException"} there is no - * need to use a FQN. - *

Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(String exceptionName)}. + *

See the {@linkplain Transactional class-level javadocs} for further details + * on rollback rule semantics, patterns, and warnings regarding possible + * unintentional matches. * @see #rollbackFor + * @see org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(String) * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable) */ String[] rollbackForClassName() default {}; @@ -206,23 +242,26 @@ * Defines zero (0) or more exception {@link Class Classes}, which must be * subclasses of {@link Throwable}, indicating which exception types must * not cause a transaction rollback. - *

This is the preferred way to construct a rollback rule (in contrast - * to {@link #noRollbackForClassName}), matching the exception class and - * its subclasses. - *

Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class clazz)}. + *

This is the preferred way to construct a rollback rule (in contrast to + * {@link #noRollbackForClassName}), matching the exception type, its subclasses, + * and its nested classes. See the {@linkplain Transactional class-level javadocs} + * for further details on rollback rule semantics and warnings regarding possible + * unintentional matches. * @see #noRollbackForClassName + * @see org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class) * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable) */ Class[] noRollbackFor() default {}; /** - * Defines zero (0) or more exception names (for exceptions which must be a + * Defines zero (0) or more exception name patterns (for exceptions which must be a * subclass of {@link Throwable}) indicating which exception types must not * cause a transaction rollback. - *

See the description of {@link #rollbackForClassName} for further - * information on how the specified names are treated. - *

Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(String exceptionName)}. + *

See the {@linkplain Transactional class-level javadocs} for further details + * on rollback rule semantics, patterns, and warnings regarding possible + * unintentional matches. * @see #noRollbackFor + * @see org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(String) * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable) */ String[] noRollbackForClassName() default {}; Index: 3rdParty_sources/spring/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java (.../AbstractFallbackTransactionAttributeSource.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java (.../AbstractFallbackTransactionAttributeSource.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -163,7 +163,7 @@ */ @Nullable protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class targetClass) { - // Don't allow no-public methods as required. + // Don't allow non-public methods, as configured. if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } Index: 3rdParty_sources/spring/org/springframework/transaction/interceptor/NoRollbackRuleAttribute.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/transaction/interceptor/NoRollbackRuleAttribute.java (.../NoRollbackRuleAttribute.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/transaction/interceptor/NoRollbackRuleAttribute.java (.../NoRollbackRuleAttribute.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2022 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. @@ -21,29 +21,36 @@ * to the {@code RollbackRuleAttribute} superclass. * * @author Rod Johnson + * @author Sam Brannen * @since 09.04.2003 */ @SuppressWarnings("serial") public class NoRollbackRuleAttribute extends RollbackRuleAttribute { /** * Create a new instance of the {@code NoRollbackRuleAttribute} class - * for the supplied {@link Throwable} class. - * @param clazz the {@code Throwable} class + * for the given {@code exceptionType}. + * @param exceptionType exception type; must be {@link Throwable} or a subclass + * of {@code Throwable} + * @throws IllegalArgumentException if the supplied {@code exceptionType} is + * not a {@code Throwable} type or is {@code null} * @see RollbackRuleAttribute#RollbackRuleAttribute(Class) */ - public NoRollbackRuleAttribute(Class clazz) { - super(clazz); + public NoRollbackRuleAttribute(Class exceptionType) { + super(exceptionType); } /** * Create a new instance of the {@code NoRollbackRuleAttribute} class - * for the supplied {@code exceptionName}. - * @param exceptionName the exception name pattern + * for the supplied {@code exceptionPattern}. + * @param exceptionPattern the exception name pattern; can also be a fully + * package-qualified class name + * @throws IllegalArgumentException if the supplied {@code exceptionPattern} + * is {@code null} or empty * @see RollbackRuleAttribute#RollbackRuleAttribute(String) */ - public NoRollbackRuleAttribute(String exceptionName) { - super(exceptionName); + public NoRollbackRuleAttribute(String exceptionPattern) { + super(exceptionPattern); } @Override Index: 3rdParty_sources/spring/org/springframework/transaction/interceptor/RollbackRuleAttribute.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/transaction/interceptor/RollbackRuleAttribute.java (.../RollbackRuleAttribute.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/transaction/interceptor/RollbackRuleAttribute.java (.../RollbackRuleAttribute.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -22,21 +22,37 @@ import org.springframework.util.Assert; /** - * Rule determining whether or not a given exception (and any subclasses) - * should cause a rollback. + * Rule determining whether or not a given exception should cause a rollback. * *

Multiple such rules can be applied to determine whether a transaction * should commit or rollback after an exception has been thrown. * + *

Each rule is based on an exception pattern which can be a fully qualified + * class name or a substring of a fully qualified class name for an exception + * type (which must be a subclass of {@code Throwable}), with no wildcard support + * at present. For example, a value of {@code "javax.servlet.ServletException"} + * or {@code "ServletException"} would match {@code javax.servlet.ServletException} + * and its subclasses. + * + *

An exception pattern can be specified as a {@link Class} reference or a + * {@link String} in {@link #RollbackRuleAttribute(Class)} and + * {@link #RollbackRuleAttribute(String)}, respectively. When an exception type + * is specified as a class reference its fully qualified name will be used as the + * pattern. See the javadocs for + * {@link org.springframework.transaction.annotation.Transactional @Transactional} + * for further details on rollback rule semantics, patterns, and warnings regarding + * possible unintentional matches. + * * @author Rod Johnson + * @author Sam Brannen * @since 09.04.2003 * @see NoRollbackRuleAttribute */ @SuppressWarnings("serial") public class RollbackRuleAttribute implements Serializable{ /** - * The {@link RollbackRuleAttribute rollback rule} for + * The {@linkplain RollbackRuleAttribute rollback rule} for * {@link RuntimeException RuntimeExceptions}. */ public static final RollbackRuleAttribute ROLLBACK_ON_RUNTIME_EXCEPTIONS = @@ -48,79 +64,90 @@ * This way does multiple string comparisons, but how often do we decide * whether to roll back a transaction following an exception? */ - private final String exceptionName; + private final String exceptionPattern; /** - * Create a new instance of the {@code RollbackRuleAttribute} class. + * Create a new instance of the {@code RollbackRuleAttribute} class + * for the given {@code exceptionType}. *

This is the preferred way to construct a rollback rule that matches - * the supplied {@link Exception} class, its subclasses, and its nested classes. - * @param clazz throwable class; must be {@link Throwable} or a subclass + * the supplied exception type, its subclasses, and its nested classes. + *

See the javadocs for + * {@link org.springframework.transaction.annotation.Transactional @Transactional} + * for further details on rollback rule semantics, patterns, and warnings regarding + * possible unintentional matches. + * @param exceptionType exception type; must be {@link Throwable} or a subclass * of {@code Throwable} - * @throws IllegalArgumentException if the supplied {@code clazz} is + * @throws IllegalArgumentException if the supplied {@code exceptionType} is * not a {@code Throwable} type or is {@code null} */ - public RollbackRuleAttribute(Class clazz) { - Assert.notNull(clazz, "'clazz' cannot be null"); - if (!Throwable.class.isAssignableFrom(clazz)) { + public RollbackRuleAttribute(Class exceptionType) { + Assert.notNull(exceptionType, "'exceptionType' cannot be null"); + if (!Throwable.class.isAssignableFrom(exceptionType)) { throw new IllegalArgumentException( - "Cannot construct rollback rule from [" + clazz.getName() + "]: it's not a Throwable"); + "Cannot construct rollback rule from [" + exceptionType.getName() + "]: it's not a Throwable"); } - this.exceptionName = clazz.getName(); + this.exceptionPattern = exceptionType.getName(); } /** * Create a new instance of the {@code RollbackRuleAttribute} class - * for the given {@code exceptionName}. - *

This can be a substring, with no wildcard support at present. A value - * of "ServletException" would match - * {@code javax.servlet.ServletException} and subclasses, for example. - *

NB: Consider carefully how specific the pattern is, and - * whether to include package information (which is not mandatory). For - * example, "Exception" will match nearly anything, and will probably hide - * other rules. "java.lang.Exception" would be correct if "Exception" was - * meant to define a rule for all checked exceptions. With more unusual - * exception names such as "BaseBusinessException" there's no need to use a - * fully package-qualified name. - * @param exceptionName the exception name pattern; can also be a fully + * for the given {@code exceptionPattern}. + *

See the javadocs for + * {@link org.springframework.transaction.annotation.Transactional @Transactional} + * for further details on rollback rule semantics, patterns, and warnings regarding + * possible unintentional matches. + * @param exceptionPattern the exception name pattern; can also be a fully * package-qualified class name - * @throws IllegalArgumentException if the supplied - * {@code exceptionName} is {@code null} or empty + * @throws IllegalArgumentException if the supplied {@code exceptionPattern} + * is {@code null} or empty */ - public RollbackRuleAttribute(String exceptionName) { - Assert.hasText(exceptionName, "'exceptionName' cannot be null or empty"); - this.exceptionName = exceptionName; + public RollbackRuleAttribute(String exceptionPattern) { + Assert.hasText(exceptionPattern, "'exceptionPattern' cannot be null or empty"); + this.exceptionPattern = exceptionPattern; } /** - * Return the pattern for the exception name. + * Get the configured exception name pattern that this rule uses for matching. + * @see #getDepth(Throwable) */ public String getExceptionName() { - return this.exceptionName; + return this.exceptionPattern; } /** - * Return the depth of the superclass matching. - *

{@code 0} means {@code ex} matches exactly. Returns - * {@code -1} if there is no match. Otherwise, returns depth with the - * lowest depth winning. + * Return the depth of the superclass matching, with the following semantics. + *

    + *
  • {@code -1} means this rule does not match the supplied {@code exception}.
  • + *
  • {@code 0} means this rule matches the supplied {@code exception} directly.
  • + *
  • Any other positive value means this rule matches the supplied {@code exception} + * within the superclass hierarchy, where the value is the number of levels in the + * class hierarchy between the supplied {@code exception} and the exception against + * which this rule matches directly.
  • + *
+ *

When comparing roll back rules that match against a given exception, a rule + * with a lower matching depth wins. For example, a direct match ({@code depth == 0}) + * wins over a match in the superclass hierarchy ({@code depth > 0}). + *

A match against a nested exception type or similarly named exception type + * will return a depth signifying a match at the corresponding level in the + * class hierarchy as if there had been a direct match. */ - public int getDepth(Throwable ex) { - return getDepth(ex.getClass(), 0); + public int getDepth(Throwable exception) { + return getDepth(exception.getClass(), 0); } - private int getDepth(Class exceptionClass, int depth) { - if (exceptionClass.getName().contains(this.exceptionName)) { + private int getDepth(Class exceptionType, int depth) { + if (exceptionType.getName().contains(this.exceptionPattern)) { // Found it! return depth; } // If we've gone as far as we can go and haven't found it... - if (exceptionClass == Throwable.class) { + if (exceptionType == Throwable.class) { return -1; } - return getDepth(exceptionClass.getSuperclass(), depth + 1); + return getDepth(exceptionType.getSuperclass(), depth + 1); } @@ -133,17 +160,17 @@ return false; } RollbackRuleAttribute rhs = (RollbackRuleAttribute) other; - return this.exceptionName.equals(rhs.exceptionName); + return this.exceptionPattern.equals(rhs.exceptionPattern); } @Override public int hashCode() { - return this.exceptionName.hashCode(); + return this.exceptionPattern.hashCode(); } @Override public String toString() { - return "RollbackRuleAttribute with pattern [" + this.exceptionName + "]"; + return "RollbackRuleAttribute with pattern [" + this.exceptionPattern + "]"; } } Index: 3rdParty_sources/spring/org/springframework/transaction/interceptor/TransactionAttributeSource.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/transaction/interceptor/TransactionAttributeSource.java (.../TransactionAttributeSource.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/transaction/interceptor/TransactionAttributeSource.java (.../TransactionAttributeSource.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -24,7 +24,7 @@ * Strategy interface used by {@link TransactionInterceptor} for metadata retrieval. * *

Implementations know how to source transaction attributes, whether from configuration, - * metadata attributes at source level (such as Java 5 annotations), or anywhere else. + * metadata attributes at source level (such as annotations), or anywhere else. * * @author Rod Johnson * @author Juergen Hoeller Index: 3rdParty_sources/spring/org/springframework/ui/ExtendedModelMap.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/ui/ExtendedModelMap.java (.../ExtendedModelMap.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/ui/ExtendedModelMap.java (.../ExtendedModelMap.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -23,7 +23,6 @@ /** * Subclass of {@link ModelMap} that implements the {@link Model} interface. - * Java 5 specific like the {@code Model} interface itself. * *

This is an implementation class exposed to handler methods by Spring MVC, typically via * a declaration of the {@link org.springframework.ui.Model} interface. There is no need to Index: 3rdParty_sources/spring/org/springframework/ui/Model.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/ui/Model.java (.../Model.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/ui/Model.java (.../Model.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -22,10 +22,12 @@ import org.springframework.lang.Nullable; /** - * Java-5-specific interface that defines a holder for model attributes. - * Primarily designed for adding attributes to the model. - * Allows for accessing the overall model as a {@code java.util.Map}. + * Interface that defines a holder for model attributes. * + *

Primarily designed for adding attributes to the model. + * + *

Allows for accessing the overall model as a {@code java.util.Map}. + * * @author Juergen Hoeller * @since 2.5.1 */ Index: 3rdParty_sources/spring/org/springframework/util/AntPathMatcher.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/util/AntPathMatcher.java (.../AntPathMatcher.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/util/AntPathMatcher.java (.../AntPathMatcher.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -733,6 +733,10 @@ } for (int i = 1; i <= matcher.groupCount(); i++) { String name = this.variableNames.get(i - 1); + if (name.startsWith("*")) { + throw new IllegalArgumentException("Capturing patterns (" + name + ") are not " + + "supported by the AntPathMatcher. Use the PathPatternParser instead."); + } String value = matcher.group(i); uriTemplateVariables.put(name, value); } Index: 3rdParty_sources/spring/org/springframework/util/ClassUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/util/ClassUtils.java (.../ClassUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/util/ClassUtils.java (.../ClassUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -1244,7 +1244,7 @@ * target class may be {@code DefaultFoo}. In this case, the method may be * {@code DefaultFoo.bar()}. This enables attributes on that method to be found. *

NOTE: In contrast to {@link org.springframework.aop.support.AopUtils#getMostSpecificMethod}, - * this method does not resolve Java 5 bridge methods automatically. + * this method does not resolve bridge methods automatically. * Call {@link org.springframework.core.BridgeMethodResolver#findBridgedMethod} * if bridge method resolution is desirable (e.g. for obtaining metadata from * the original method definition). @@ -1256,7 +1256,7 @@ * (may be {@code null} or may not even implement the method) * @return the specific target method, or the original method if the * {@code targetClass} does not implement it - * @see #getInterfaceMethodIfPossible + * @see #getInterfaceMethodIfPossible(Method, Class) */ public static Method getMostSpecificMethod(Method method, @Nullable Class targetClass) { if (targetClass != null && targetClass != method.getDeclaringClass() && isOverridable(method, targetClass)) { @@ -1289,28 +1289,54 @@ * @param method the method to be invoked, potentially from an implementation class * @return the corresponding interface method, or the original method if none found * @since 5.1 - * @see #getMostSpecificMethod + * @deprecated in favor of {@link #getInterfaceMethodIfPossible(Method, Class)} */ + @Deprecated public static Method getInterfaceMethodIfPossible(Method method) { + return getInterfaceMethodIfPossible(method, null); + } + + /** + * Determine a corresponding interface method for the given method handle, if possible. + *

This is particularly useful for arriving at a public exported type on Jigsaw + * which can be reflectively invoked without an illegal access warning. + * @param method the method to be invoked, potentially from an implementation class + * @param targetClass the target class to check for declared interfaces + * @return the corresponding interface method, or the original method if none found + * @since 5.3.16 + * @see #getMostSpecificMethod + */ + public static Method getInterfaceMethodIfPossible(Method method, @Nullable Class targetClass) { if (!Modifier.isPublic(method.getModifiers()) || method.getDeclaringClass().isInterface()) { return method; } - return interfaceMethodCache.computeIfAbsent(method, key -> { - Class current = key.getDeclaringClass(); - while (current != null && current != Object.class) { - Class[] ifcs = current.getInterfaces(); - for (Class ifc : ifcs) { - try { - return ifc.getMethod(key.getName(), key.getParameterTypes()); - } - catch (NoSuchMethodException ex) { - // ignore - } + // Try cached version of method in its declaring class + Method result = interfaceMethodCache.computeIfAbsent(method, + key -> findInterfaceMethodIfPossible(key, key.getDeclaringClass(), Object.class)); + if (result == method && targetClass != null) { + // No interface method found yet -> try given target class (possibly a subclass of the + // declaring class, late-binding a base class method to a subclass-declared interface: + // see e.g. HashMap.HashIterator.hasNext) + result = findInterfaceMethodIfPossible(method, targetClass, method.getDeclaringClass()); + } + return result; + } + + private static Method findInterfaceMethodIfPossible(Method method, Class startClass, Class endClass) { + Class current = startClass; + while (current != null && current != endClass) { + Class[] ifcs = current.getInterfaces(); + for (Class ifc : ifcs) { + try { + return ifc.getMethod(method.getName(), method.getParameterTypes()); } - current = current.getSuperclass(); + catch (NoSuchMethodException ex) { + // ignore + } } - return key; - }); + current = current.getSuperclass(); + } + return method; } /** Index: 3rdParty_sources/spring/org/springframework/util/ReflectionUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/util/ReflectionUtils.java (.../ReflectionUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/util/ReflectionUtils.java (.../ReflectionUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -46,12 +46,12 @@ public abstract class ReflectionUtils { /** - * Pre-built MethodFilter that matches all non-bridge non-synthetic methods + * Pre-built {@link MethodFilter} that matches all non-bridge non-synthetic methods * which are not declared on {@code java.lang.Object}. * @since 3.0.5 */ public static final MethodFilter USER_DECLARED_METHODS = - (method -> !method.isBridge() && !method.isSynthetic()); + (method -> !method.isBridge() && !method.isSynthetic() && (method.getDeclaringClass() != Object.class)); /** * Pre-built FieldFilter that matches all non-static, non-final fields. @@ -354,7 +354,10 @@ * @throws IllegalStateException if introspection fails */ public static void doWithMethods(Class clazz, MethodCallback mc, @Nullable MethodFilter mf) { - // Keep backing up the inheritance hierarchy. + if (mf == USER_DECLARED_METHODS && clazz == Object.class) { + // nothing to introspect + return; + } Method[] methods = getDeclaredMethods(clazz, false); for (Method method : methods) { if (mf != null && !mf.matches(method)) { @@ -367,6 +370,7 @@ throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex); } } + // Keep backing up the inheritance hierarchy. if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) { doWithMethods(clazz.getSuperclass(), mc, mf); } Index: 3rdParty_sources/spring/org/springframework/util/SerializationUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/util/SerializationUtils.java (.../SerializationUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/util/SerializationUtils.java (.../SerializationUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -25,9 +25,18 @@ import org.springframework.lang.Nullable; /** - * Static utilities for serialization and deserialization. + * Static utilities for serialization and deserialization using + * Java Object Serialization. * + *

WARNING: These utilities should be used with caution. See + * Secure Coding Guidelines for the Java Programming Language + * for details. + * * @author Dave Syer + * @author Loïc Ledoyen + * @author Sam Brannen * @since 3.0.5 */ public abstract class SerializationUtils { @@ -55,6 +64,12 @@ /** * Deserialize the byte array into an object. + *

WARNING: This utility will be deprecated in Spring + * Framework 6.0 since it uses Java Object Serialization, which allows arbitrary + * code to be run and is known for being the source of many Remote Code Execution + * (RCE) vulnerabilities. Prefer the use of an external tool (that serializes + * to JSON, XML, or any other format) which is regularly checked and updated + * for not allowing RCE. * @param bytes a serialized object * @return the result of deserializing the bytes */ Index: 3rdParty_sources/spring/org/springframework/util/SocketUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/util/SocketUtils.java (.../SocketUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/util/SocketUtils.java (.../SocketUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -32,13 +32,25 @@ *

Within this class, a TCP port refers to a port for a {@link ServerSocket}; * whereas, a UDP port refers to a port for a {@link DatagramSocket}. * + *

{@code SocketUtils} was introduced in Spring Framework 4.0, primarily to + * assist in writing integration tests which start an external server on an + * available random port. However, these utilities make no guarantee about the + * subsequent availability of a given port and are therefore unreliable. Instead + * of using {@code SocketUtils} to find an available local port for a server, it + * is recommended that you rely on a server's ability to start on a random port + * that it selects or is assigned by the operating system. To interact with that + * server, you should query the server for the port it is currently using. + * * @author Sam Brannen * @author Ben Hale * @author Arjen Poutsma * @author Gunnar Hillert * @author Gary Russell * @since 4.0 + * @deprecated as of Spring Framework 5.3.16, to be removed in 6.0; see + * {@link SocketUtils class-level Javadoc} for details. */ +@Deprecated public class SocketUtils { /** Index: 3rdParty_sources/spring/org/springframework/util/StringUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/util/StringUtils.java (.../StringUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/util/StringUtils.java (.../StringUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -65,6 +65,8 @@ private static final String FOLDER_SEPARATOR = "/"; + private static final char FOLDER_SEPARATOR_CHAR = '/'; + private static final String WINDOWS_FOLDER_SEPARATOR = "\\"; private static final String TOP_PATH = ".."; @@ -581,7 +583,7 @@ return null; } - int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); + int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR_CHAR); return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path); } @@ -602,7 +604,7 @@ return null; } - int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR); + int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR_CHAR); if (folderIndex > extIndex) { return null; } @@ -622,7 +624,7 @@ return path; } - int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR); + int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR_CHAR); if (folderIndex > extIndex) { return path; } @@ -639,11 +641,11 @@ * @return the full file path that results from applying the relative path */ public static String applyRelativePath(String path, String relativePath) { - int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); + int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR_CHAR); if (separatorIndex != -1) { String newPath = path.substring(0, separatorIndex); if (!relativePath.startsWith(FOLDER_SEPARATOR)) { - newPath += FOLDER_SEPARATOR; + newPath += FOLDER_SEPARATOR_CHAR; } return newPath + relativePath; } Index: 3rdParty_sources/spring/org/springframework/util/TypeUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/util/TypeUtils.java (.../TypeUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/util/TypeUtils.java (.../TypeUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -24,9 +24,10 @@ import org.springframework.lang.Nullable; /** - * Utility to work with Java 5 generic type parameters. - * Mainly for internal use within the framework. + * Utility to work with generic type parameters. * + *

Mainly for internal use within the framework. + * * @author Ramnivas Laddad * @author Juergen Hoeller * @author Chris Beams Index: 3rdParty_sources/spring/org/springframework/util/xml/XmlValidationModeDetector.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/util/xml/XmlValidationModeDetector.java (.../XmlValidationModeDetector.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/util/xml/XmlValidationModeDetector.java (.../XmlValidationModeDetector.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -58,7 +58,7 @@ /** - * The token in a XML document that declares the DTD to use for validation + * The token in an XML document that declares the DTD to use for validation * and thus that DTD validation is being used. */ private static final String DOCTYPE = "DOCTYPE"; @@ -82,20 +82,22 @@ /** * Detect the validation mode for the XML document in the supplied {@link InputStream}. - * Note that the supplied {@link InputStream} is closed by this method before returning. + *

Note that the supplied {@link InputStream} is closed by this method before returning. * @param inputStream the InputStream to parse * @throws IOException in case of I/O failure * @see #VALIDATION_DTD * @see #VALIDATION_XSD */ public int detectValidationMode(InputStream inputStream) throws IOException { + this.inComment = false; + // Peek into the file to look for DOCTYPE. try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { boolean isDtdValidated = false; String content; while ((content = reader.readLine()) != null) { content = consumeCommentTokens(content); - if (this.inComment || !StringUtils.hasText(content)) { + if (!StringUtils.hasText(content)) { continue; } if (hasDoctype(content)) { @@ -125,9 +127,11 @@ } /** - * Does the supplied content contain an XML opening tag. If the parse state is currently - * in an XML comment then this method always returns false. It is expected that all comment - * tokens will have consumed for the supplied content before passing the remainder to this method. + * Determine if the supplied content contains an XML opening tag. + *

It is expected that all comment tokens will have been consumed for the + * supplied content before passing the remainder to this method. However, as + * a sanity check, if the parse state is currently in an XML comment this + * method always returns {@code false}. */ private boolean hasOpeningTag(String content) { if (this.inComment) { @@ -139,11 +143,10 @@ } /** - * Consume all leading and trailing comments in the given String and return - * the remaining content, which may be empty since the supplied content might - * be all comment data. + * Consume all comments in the given String and return the remaining content, + * which may be empty since the supplied content might be all comment data. + *

This method takes the current "in comment" parsing state into account. */ - @Nullable private String consumeCommentTokens(String line) { int indexOfStartComment = line.indexOf(START_COMMENT); if (indexOfStartComment == -1 && !line.contains(END_COMMENT)) { @@ -152,21 +155,19 @@ String result = ""; String currLine = line; - if (indexOfStartComment >= 0) { + if (!this.inComment && (indexOfStartComment >= 0)) { result = line.substring(0, indexOfStartComment); currLine = line.substring(indexOfStartComment); } - while ((currLine = consume(currLine)) != null) { - if (!this.inComment && !currLine.trim().startsWith(START_COMMENT)) { - return result + currLine; - } + if ((currLine = consume(currLine)) != null) { + result += consumeCommentTokens(currLine); } - return null; + return result; } /** - * Consume the next comment token, update the "inComment" flag + * Consume the next comment token, update the "inComment" flag, * and return the remaining content. */ @Nullable @@ -183,14 +184,19 @@ return commentToken(line, START_COMMENT, true); } + /** + * Try to consume the {@link #END_COMMENT} token. + * @see #commentToken(String, String, boolean) + */ private int endComment(String line) { return commentToken(line, END_COMMENT, false); } /** * Try to consume the supplied token against the supplied content and update the - * in comment parse state to the supplied value. Returns the index into the content - * which is after the token or -1 if the token is not found. + * "in comment" parse state to the supplied value. + *

Returns the index into the content which is after the token or -1 if the + * token is not found. */ private int commentToken(String line, String token, boolean inCommentIfPresent) { int index = line.indexOf(token); Index: 3rdParty_sources/spring/org/springframework/validation/DataBinder.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/validation/DataBinder.java (.../DataBinder.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/validation/DataBinder.java (.../DataBinder.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -418,11 +418,13 @@ } /** - * Register fields that should be allowed for binding. Default is all - * fields. Restrict this for example to avoid unwanted modifications - * by malicious users when binding HTTP request parameters. - *

Supports "xxx*", "*xxx" and "*xxx*" patterns. More sophisticated matching - * can be implemented by overriding the {@code isAllowed} method. + * Register fields that should be allowed for binding. Default is all fields. + * Restrict this for example to avoid unwanted modifications by malicious + * users when binding HTTP request parameters. + *

Supports "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an + * arbitrary number of pattern parts), as well as direct equality. More + * sophisticated matching can be implemented by overriding the + * {@code isAllowed} method. *

Alternatively, specify a list of disallowed fields. * @param allowedFields array of field names * @see #setDisallowedFields @@ -442,11 +444,13 @@ } /** - * Register fields that should not be allowed for binding. Default is none. - * Mark fields as disallowed for example to avoid unwanted modifications - * by malicious users when binding HTTP request parameters. - *

Supports "xxx*", "*xxx" and "*xxx*" patterns. More sophisticated matching - * can be implemented by overriding the {@code isAllowed} method. + * Register fields that should not be allowed for binding. Default + * is none. Mark fields as disallowed for example to avoid unwanted + * modifications by malicious users when binding HTTP request parameters. + *

Supports "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an + * arbitrary number of pattern parts), as well as direct equality. + * More sophisticated matching can be implemented by overriding the + * {@code isAllowed} method. *

Alternatively, specify a list of allowed fields. * @param disallowedFields array of field names * @see #setAllowedFields @@ -772,10 +776,11 @@ /** * Return if the given field is allowed for binding. * Invoked for each passed-in property value. - *

The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches, - * as well as direct equality, in the specified lists of allowed fields and - * disallowed fields. A field matching a disallowed pattern will not be accepted - * even if it also happens to match a pattern in the allowed list. + *

The default implementation checks for "xxx*", "*xxx", "*xxx*" and "xxx*yyy" + * matches (with an arbitrary number of pattern parts), as well as direct equality, + * in the specified lists of allowed fields and disallowed fields. A field matching + * a disallowed pattern will not be accepted even if it also happens to match a + * pattern in the allowed list. *

Can be overridden in subclasses. * @param field the field to check * @return if the field is allowed Index: 3rdParty_sources/spring/org/springframework/web/bind/annotation/RequestMethod.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/bind/annotation/RequestMethod.java (.../RequestMethod.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/bind/annotation/RequestMethod.java (.../RequestMethod.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2022 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. @@ -17,11 +17,11 @@ package org.springframework.web.bind.annotation; /** - * Java 5 enumeration of HTTP request methods. Intended for use with the + * Enumeration of HTTP request methods. Intended for use with the * {@link RequestMapping#method()} attribute of the {@link RequestMapping} annotation. * *

Note that, by default, {@link org.springframework.web.servlet.DispatcherServlet} - * supports GET, HEAD, POST, PUT, PATCH and DELETE only. DispatcherServlet will + * supports GET, HEAD, POST, PUT, PATCH, and DELETE only. DispatcherServlet will * process TRACE and OPTIONS with the default HttpServlet behavior unless explicitly * told to dispatch those request types as well: Check out the "dispatchOptionsRequest" * and "dispatchTraceRequest" properties, switching them to "true" if necessary. Index: 3rdParty_sources/spring/org/springframework/web/client/AsyncRestTemplate.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/client/AsyncRestTemplate.java (.../AsyncRestTemplate.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/client/AsyncRestTemplate.java (.../AsyncRestTemplate.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -559,9 +559,9 @@ } private void handleResponseError(HttpMethod method, URI url, ClientHttpResponse response) throws IOException { - if (logger.isWarnEnabled()) { + if (logger.isDebugEnabled()) { try { - logger.warn("Async " + method.name() + " request for \"" + url + "\" resulted in " + + logger.debug("Async " + method.name() + " request for \"" + url + "\" resulted in " + response.getRawStatusCode() + " (" + response.getStatusText() + "); invoking error handler"); } catch (IOException ex) { Index: 3rdParty_sources/spring/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java (.../AnnotationConfigWebApplicationContext.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java (.../AnnotationConfigWebApplicationContext.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -36,16 +36,27 @@ /** * {@link org.springframework.web.context.WebApplicationContext WebApplicationContext} * implementation which accepts component classes as input — in particular - * {@link org.springframework.context.annotation.Configuration @Configuration}-annotated + * {@link org.springframework.context.annotation.Configuration @Configuration} * classes, but also plain {@link org.springframework.stereotype.Component @Component} - * classes and JSR-330 compliant classes using {@code javax.inject} annotations. + * classes as well as JSR-330 compliant classes using {@code javax.inject} annotations. * *

Allows for registering classes one by one (specifying class names as config - * location) as well as for classpath scanning (specifying base packages as config location). + * locations) as well as via classpath scanning (specifying base packages as config + * locations). * *

This is essentially the equivalent of * {@link org.springframework.context.annotation.AnnotationConfigApplicationContext - * AnnotationConfigApplicationContext} for a web environment. + * AnnotationConfigApplicationContext} for a web environment. However, in contrast to + * {@code AnnotationConfigApplicationContext}, this class does not extend + * {@link org.springframework.context.support.GenericApplicationContext + * GenericApplicationContext} and therefore does not provide some of the convenient + * {@code registerBean(...)} methods available in a {@code GenericApplicationContext}. + * If you wish to register annotated component classes with a + * {@code GenericApplicationContext} in a web environment, you may use a + * {@code GenericWebApplicationContext} with an + * {@link org.springframework.context.annotation.AnnotatedBeanDefinitionReader + * AnnotatedBeanDefinitionReader}. See the Javadoc for {@link GenericWebApplicationContext} + * for details and an example. * *

To make use of this application context, the * {@linkplain ContextLoader#CONTEXT_CLASS_PARAM "contextClass"} context-param for @@ -80,8 +91,10 @@ * * @author Chris Beams * @author Juergen Hoeller + * @author Sam Brannen * @since 3.0 * @see org.springframework.context.annotation.AnnotationConfigApplicationContext + * @see org.springframework.web.context.support.GenericWebApplicationContext */ public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWebApplicationContext implements AnnotationConfigRegistry { Index: 3rdParty_sources/spring/org/springframework/web/context/support/GenericWebApplicationContext.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/context/support/GenericWebApplicationContext.java (.../GenericWebApplicationContext.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/context/support/GenericWebApplicationContext.java (.../GenericWebApplicationContext.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -39,26 +39,42 @@ /** * Subclass of {@link GenericApplicationContext}, suitable for web environments. * - *

Implements {@link org.springframework.web.context.ConfigurableWebApplicationContext}, - * but is not intended for declarative setup in {@code web.xml}. Instead, it is designed - * for programmatic setup, for example for building nested contexts or for use within + *

Implements {@link ConfigurableWebApplicationContext}, but is not intended for + * declarative setup in {@code web.xml}. Instead, it is designed for programmatic setup, + * for example for building nested contexts or for use within * {@link org.springframework.web.WebApplicationInitializer WebApplicationInitializers}. * - *

If you intend to implement a WebApplicationContext that reads bean definitions - * from configuration files, consider deriving from AbstractRefreshableWebApplicationContext, - * reading the bean definitions in an implementation of the {@code loadBeanDefinitions} - * method. - * *

Interprets resource paths as servlet context resources, i.e. as paths beneath - * the web application root. Absolute paths, e.g. for files outside the web app root, - * can be accessed via "file:" URLs, as implemented by AbstractApplicationContext. + * the web application root. Absolute paths — for example, for files outside + * the web app root — can be accessed via {@code file:} URLs, as implemented + * by {@code AbstractApplicationContext}. * *

In addition to the special beans detected by - * {@link org.springframework.context.support.AbstractApplicationContext}, - * this class detects a ThemeSource bean in the context, with the name "themeSource". + * {@link org.springframework.context.support.AbstractApplicationContext AbstractApplicationContext}, + * this class detects a {@link ThemeSource} bean in the context, with the name "themeSource". * + *

If you wish to register annotated component classes with a + * {@code GenericWebApplicationContext}, you can use an + * {@link org.springframework.context.annotation.AnnotatedBeanDefinitionReader + * AnnotatedBeanDefinitionReader}, as demonstrated in the following example. + * Component classes include in particular + * {@link org.springframework.context.annotation.Configuration @Configuration} + * classes but also plain {@link org.springframework.stereotype.Component @Component} + * classes as well as JSR-330 compliant classes using {@code javax.inject} annotations. + * + *

+ * GenericWebApplicationContext context = new GenericWebApplicationContext();
+ * AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
+ * reader.register(AppConfig.class, UserController.class, UserRepository.class);
+ * + *

If you intend to implement a {@code WebApplicationContext} that reads bean definitions + * from configuration files, consider deriving from {@link AbstractRefreshableWebApplicationContext}, + * reading the bean definitions in an implementation of the {@code loadBeanDefinitions} + * method. + * * @author Juergen Hoeller * @author Chris Beams + * @author Sam Brannen * @since 1.2 */ public class GenericWebApplicationContext extends GenericApplicationContext @@ -72,7 +88,7 @@ /** - * Create a new GenericWebApplicationContext. + * Create a new {@code GenericWebApplicationContext}. * @see #setServletContext * @see #registerBeanDefinition * @see #refresh @@ -82,8 +98,8 @@ } /** - * Create a new GenericWebApplicationContext for the given ServletContext. - * @param servletContext the ServletContext to run in + * Create a new {@code GenericWebApplicationContext} for the given {@link ServletContext}. + * @param servletContext the {@code ServletContext} to run in * @see #registerBeanDefinition * @see #refresh */ @@ -92,8 +108,8 @@ } /** - * Create a new GenericWebApplicationContext with the given DefaultListableBeanFactory. - * @param beanFactory the DefaultListableBeanFactory instance to use for this context + * Create a new {@code GenericWebApplicationContext} with the given {@link DefaultListableBeanFactory}. + * @param beanFactory the {@code DefaultListableBeanFactory} instance to use for this context * @see #setServletContext * @see #registerBeanDefinition * @see #refresh @@ -103,9 +119,10 @@ } /** - * Create a new GenericWebApplicationContext with the given DefaultListableBeanFactory. - * @param beanFactory the DefaultListableBeanFactory instance to use for this context - * @param servletContext the ServletContext to run in + * Create a new {@code GenericWebApplicationContext} with the given {@link DefaultListableBeanFactory} + * and {@link ServletContext}. + * @param beanFactory the {@code DefaultListableBeanFactory} instance to use for this context + * @param servletContext the {@code ServletContext} to run in * @see #registerBeanDefinition * @see #refresh */ @@ -116,7 +133,7 @@ /** - * Set the ServletContext that this WebApplicationContext runs in. + * Set the {@link ServletContext} that this {@code WebApplicationContext} runs in. */ @Override public void setServletContext(@Nullable ServletContext servletContext) { @@ -143,8 +160,7 @@ } /** - * Register ServletContextAwareProcessor. - * @see ServletContextAwareProcessor + * Register request/session scopes, environment beans, a {@link ServletContextAwareProcessor}, etc. */ @Override protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { @@ -157,7 +173,7 @@ } /** - * This implementation supports file paths beneath the root of the ServletContext. + * This implementation supports file paths beneath the root of the {@link ServletContext}. * @see ServletContextResource */ @Override @@ -236,7 +252,7 @@ if (StringUtils.hasText(configLocation)) { throw new UnsupportedOperationException( "GenericWebApplicationContext does not support setConfigLocation(). " + - "Do you still have an 'contextConfigLocations' init-param set?"); + "Do you still have a 'contextConfigLocation' init-param set?"); } } @@ -245,7 +261,7 @@ if (!ObjectUtils.isEmpty(configLocations)) { throw new UnsupportedOperationException( "GenericWebApplicationContext does not support setConfigLocations(). " + - "Do you still have an 'contextConfigLocations' init-param set?"); + "Do you still have a 'contextConfigLocations' init-param set?"); } } Index: 3rdParty_sources/spring/org/springframework/web/filter/DelegatingFilterProxy.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/filter/DelegatingFilterProxy.java (.../DelegatingFilterProxy.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/filter/DelegatingFilterProxy.java (.../DelegatingFilterProxy.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2021 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. @@ -54,9 +54,9 @@ * of the {@code Filter.init} and {@code Filter.destroy} lifecycle methods * on the target bean, letting the servlet container manage the filter lifecycle. * - *

As of Spring 3.1, {@code DelegatingFilterProxy} has been updated to optionally accept - * constructor parameters when using Servlet 3.0's instance-based filter registration - * methods, usually in conjunction with Spring 3.1's + *

As of Spring 3.1, {@code DelegatingFilterProxy} has been updated to optionally + * accept constructor parameters when using a Servlet container's instance-based filter + * registration methods, usually in conjunction with Spring's * {@link org.springframework.web.WebApplicationInitializer} SPI. These constructors allow * for providing the delegate Filter bean directly, or providing the application context * and bean name to fetch, avoiding the need to look up the application context from the @@ -100,8 +100,7 @@ /** - * Create a new {@code DelegatingFilterProxy}. For traditional (pre-Servlet 3.0) use - * in {@code web.xml}. + * Create a new {@code DelegatingFilterProxy}. For traditional use in {@code web.xml}. * @see #setTargetBeanName(String) */ public DelegatingFilterProxy() { @@ -111,8 +110,7 @@ * Create a new {@code DelegatingFilterProxy} with the given {@link Filter} delegate. * Bypasses entirely the need for interacting with a Spring application context, * specifying the {@linkplain #setTargetBeanName target bean name}, etc. - *

For use in Servlet 3.0+ environments where instance-based registration of - * filters is supported. + *

For use with instance-based registration of filters. * @param delegate the {@code Filter} instance that this proxy will delegate to and * manage the lifecycle for (must not be {@code null}). * @see #doFilter(ServletRequest, ServletResponse, FilterChain) @@ -130,9 +128,8 @@ * bean from the Spring {@code WebApplicationContext} found in the {@code ServletContext} * (either the 'root' application context or the context named by * {@link #setContextAttribute}). - *

For use in Servlet 3.0+ environments where instance-based registration of - * filters is supported. - *

The target bean must implement the standard Servlet Filter. + *

For use with instance-based registration of filters. + *

The target bean must implement the standard Servlet Filter interface. * @param targetBeanName name of the target filter bean to look up in the Spring * application context (must not be {@code null}). * @see #findWebApplicationContext() @@ -145,8 +142,7 @@ /** * Create a new {@code DelegatingFilterProxy} that will retrieve the named target * bean from the given Spring {@code WebApplicationContext}. - *

For use in Servlet 3.0+ environments where instance-based registration of - * filters is supported. + *

For use with instance-based registration of filters. *

The target bean must implement the standard Servlet Filter interface. *

The given {@code WebApplicationContext} may or may not be refreshed when passed * in. If it has not, and if the context implements {@link ConfigurableApplicationContext}, Index: 3rdParty_sources/spring/org/springframework/web/filter/OncePerRequestFilter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/filter/OncePerRequestFilter.java (.../OncePerRequestFilter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/filter/OncePerRequestFilter.java (.../OncePerRequestFilter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -98,12 +98,10 @@ boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null; if (skipDispatch(httpRequest) || shouldNotFilter(httpRequest)) { - // Proceed without invoking this filter... filterChain.doFilter(request, response); } else if (hasAlreadyFilteredAttribute) { - if (DispatcherType.ERROR.equals(request.getDispatcherType())) { doFilterNestedErrorDispatch(httpRequest, httpResponse, filterChain); return; @@ -197,7 +195,7 @@ * setting up thread locals or to perform final processing at the very end. *

Note that although a filter can be mapped to handle specific dispatcher * types via {@code web.xml} or in Java through the {@code ServletContext}, - * servlet containers may enforce different defaults with regards to + * servlet containers may enforce different defaults with respect to * dispatcher types. This flag enforces the design intent of the filter. *

The default return value is "true", which means the filter will not be * invoked during subsequent async dispatches. If "false", the filter will Index: 3rdParty_sources/spring/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java (.../HandlerMethodArgumentResolverComposite.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/method/support/HandlerMethodArgumentResolverComposite.java (.../HandlerMethodArgumentResolverComposite.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -85,11 +85,12 @@ } /** - * Clear the list of configured resolvers. + * Clear the list of configured resolvers and the resolver cache. * @since 4.3 */ public void clear() { this.argumentResolvers.clear(); + this.argumentResolverCache.clear(); } Index: 3rdParty_sources/spring/org/springframework/web/server/MediaTypeNotSupportedStatusException.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/server/MediaTypeNotSupportedStatusException.java (.../MediaTypeNotSupportedStatusException.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/server/MediaTypeNotSupportedStatusException.java (.../MediaTypeNotSupportedStatusException.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -28,7 +28,7 @@ * @author Rossen Stoyanchev * @since 5.0 * @deprecated in favor of {@link UnsupportedMediaTypeStatusException}, - * with this class never thrown by Spring code and to be removed in 5.3 + * with this class never thrown by Spring code and to be removed in 6.0 */ @Deprecated @SuppressWarnings("serial") Index: 3rdParty_sources/spring/org/springframework/web/servlet/DispatcherServlet.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/DispatcherServlet.java (.../DispatcherServlet.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/DispatcherServlet.java (.../DispatcherServlet.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1395,6 +1395,7 @@ } try { if (mv.getStatus() != null) { + request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, mv.getStatus()); response.setStatus(mv.getStatus().value()); } view.render(mv.getModelInternal(), request, response); Index: 3rdParty_sources/spring/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java (.../AbstractUrlHandlerMapping.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java (.../AbstractUrlHandlerMapping.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -28,7 +28,6 @@ import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; -import org.springframework.http.server.PathContainer; import org.springframework.http.server.RequestPath; import org.springframework.lang.Nullable; import org.springframework.util.AntPathMatcher; @@ -216,8 +215,9 @@ handler = obtainApplicationContext().getBean(handlerName); } validateHandler(handler, request); - PathContainer pathWithinMapping = pattern.extractPathWithinPattern(path.pathWithinApplication()); - return buildPathExposingHandler(handler, pattern.getPatternString(), pathWithinMapping.value(), null); + String pathWithinMapping = pattern.extractPathWithinPattern(path.pathWithinApplication()).value(); + pathWithinMapping = UrlPathHelper.defaultInstance.removeSemicolonContent(pathWithinMapping); + return buildPathExposingHandler(handler, pattern.getPatternString(), pathWithinMapping, null); } /** Index: 3rdParty_sources/spring/org/springframework/web/servlet/handler/HandlerMappingIntrospector.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/handler/HandlerMappingIntrospector.java (.../HandlerMappingIntrospector.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/handler/HandlerMappingIntrospector.java (.../HandlerMappingIntrospector.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -103,14 +103,6 @@ } - /** - * Return the configured or detected {@code HandlerMapping}s. - */ - public List getHandlerMappings() { - return (this.handlerMappings != null ? this.handlerMappings : Collections.emptyList()); - } - - @Override public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; @@ -125,7 +117,14 @@ } } + /** + * Return the configured or detected {@code HandlerMapping}s. + */ + public List getHandlerMappings() { + return (this.handlerMappings != null ? this.handlerMappings : Collections.emptyList()); + } + /** * Find the {@link HandlerMapping} that would handle the given request and * return it as a {@link MatchableHandlerMapping} that can be used to test Index: 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodArgumentResolver.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodArgumentResolver.java (.../AbstractMessageConverterMethodArgumentResolver.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodArgumentResolver.java (.../AbstractMessageConverterMethodArgumentResolver.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -169,7 +169,7 @@ HttpMethod httpMethod = (inputMessage instanceof HttpRequest ? ((HttpRequest) inputMessage).getMethod() : null); Object body = NO_VALUE; - EmptyBodyCheckingHttpInputMessage message; + EmptyBodyCheckingHttpInputMessage message = null; try { message = new EmptyBodyCheckingHttpInputMessage(inputMessage); @@ -196,6 +196,11 @@ catch (IOException ex) { throw new HttpMessageNotReadableException("I/O error while reading input message", ex, inputMessage); } + finally { + if (message != null && message.hasBody()) { + closeStreamIfNecessary(message.getBody()); + } + } if (body == NO_VALUE) { if (httpMethod == null || !SUPPORTED_METHODS.contains(httpMethod) || @@ -298,7 +303,16 @@ return arg; } + /** + * Allow for closing the body stream if necessary, + * e.g. for part streams in a multipart request. + */ + void closeStreamIfNecessary(InputStream body) { + // No-op by default: A standard HttpInputMessage exposes the HTTP request stream + // (ServletRequest#getInputStream), with its lifecycle managed by the container. + } + private static class EmptyBodyCheckingHttpInputMessage implements HttpInputMessage { private final HttpHeaders headers; Index: 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinder.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinder.java (.../ExtendedServletRequestDataBinder.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinder.java (.../ExtendedServletRequestDataBinder.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -69,9 +69,8 @@ if (uriVars != null) { uriVars.forEach((name, value) -> { if (mpvs.contains(name)) { - if (logger.isWarnEnabled()) { - logger.warn("Skipping URI variable '" + name + - "' because request contains bind value with same name."); + if (logger.isDebugEnabled()) { + logger.debug("URI variable '" + name + "' overridden by request bind value."); } } else { Index: 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java (.../ReactiveTypeHandler.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java (.../ReactiveTypeHandler.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -202,7 +202,7 @@ "-------------------------------\n" + "Controller:\t" + returnType.getContainingClass().getName() + "\n" + "Method:\t\t" + returnType.getMethod().getName() + "\n" + - "Returning:\t" + ResolvableType.forMethodParameter(returnType).toString() + "\n" + + "Returning:\t" + ResolvableType.forMethodParameter(returnType) + "\n" + "!!!"); this.taskExecutorWarning = false; } Index: 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java (.../RequestMappingHandlerMapping.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java (.../RequestMappingHandlerMapping.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -187,7 +187,6 @@ @Override @SuppressWarnings("deprecation") public void afterPropertiesSet() { - this.config = new RequestMappingInfo.BuilderConfiguration(); this.config.setTrailingSlashMatch(useTrailingSlashMatch()); this.config.setContentNegotiationManager(getContentNegotiationManager()); @@ -246,7 +245,20 @@ return this.config.getFileExtensions(); } + /** + * Obtain a {@link RequestMappingInfo.BuilderConfiguration} that can reflects + * the internal configuration of this {@code HandlerMapping} and can be used + * to set {@link RequestMappingInfo.Builder#options(RequestMappingInfo.BuilderConfiguration)}. + *

This is useful for programmatic registration of request mappings via + * {@link #registerHandlerMethod(Object, Method, RequestMappingInfo)}. + * @return the builder configuration that reflects the internal state + * @since 5.3.14 + */ + public RequestMappingInfo.BuilderConfiguration getBuilderConfiguration() { + return this.config; + } + /** * {@inheritDoc} *

Expects a handler to have either a type-level @{@link Controller} @@ -390,6 +402,19 @@ updateConsumesCondition(mapping, method); } + /** + * {@inheritDoc} + *

Note: To create the {@link RequestMappingInfo}, + * please use {@link #getBuilderConfiguration()} and set the options on + * {@link RequestMappingInfo.Builder#options(RequestMappingInfo.BuilderConfiguration)} + * to match how this {@code HandlerMapping} is configured. This + * is important for example to ensure use of + * {@link org.springframework.web.util.pattern.PathPattern} or + * {@link org.springframework.util.PathMatcher} based matching. + * @param handler the bean name of the handler or the handler instance + * @param method the method to register + * @param mapping the mapping conditions associated with the handler method + */ @Override protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) { super.registerHandlerMethod(handler, method, mapping); Index: 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java (.../RequestPartMethodArgumentResolver.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java (.../RequestPartMethodArgumentResolver.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -16,6 +16,8 @@ package org.springframework.web.servlet.mvc.method.annotation; +import java.io.IOException; +import java.io.InputStream; import java.util.List; import javax.servlet.http.HttpServletRequest; @@ -180,4 +182,17 @@ return partName; } + @Override + void closeStreamIfNecessary(InputStream body) { + // RequestPartServletServerHttpRequest exposes individual part streams, + // potentially from temporary files -> explicit close call after resolution + // in order to prevent file descriptor leaks. + try { + body.close(); + } + catch (IOException ex) { + // ignore + } + } + } Index: 3rdParty_sources/spring/org/springframework/web/servlet/resource/PathResourceResolver.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/resource/PathResourceResolver.java (.../PathResourceResolver.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/resource/PathResourceResolver.java (.../PathResourceResolver.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -33,6 +33,7 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; +import org.springframework.core.log.LogFormatUtils; import org.springframework.http.server.PathContainer; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; @@ -190,11 +191,12 @@ return resource; } else if (logger.isWarnEnabled()) { - Resource[] allowedLocations = getAllowedLocations(); - logger.warn("Resource path \"" + resourcePath + "\" was successfully resolved " + - "but resource \"" + resource.getURL() + "\" is neither under the " + - "current location \"" + location.getURL() + "\" nor under any of the " + - "allowed locations " + (allowedLocations != null ? Arrays.asList(allowedLocations) : "[]")); + Resource[] allowed = getAllowedLocations(); + logger.warn(LogFormatUtils.formatValue( + "Resource path \"" + resourcePath + "\" was successfully resolved " + + "but resource \"" + resource.getURL() + "\" is neither under " + + "the current location \"" + location.getURL() + "\" nor under any of " + + "the allowed locations " + (allowed != null ? Arrays.asList(allowed) : "[]"), -1, true)); } } return null; @@ -297,7 +299,8 @@ try { String decodedPath = URLDecoder.decode(resourcePath, "UTF-8"); if (decodedPath.contains("../") || decodedPath.contains("..\\")) { - logger.warn("Resolved resource path contains encoded \"../\" or \"..\\\": " + resourcePath); + logger.warn(LogFormatUtils.formatValue( + "Resolved resource path contains encoded \"../\" or \"..\\\": " + resourcePath, -1, true)); return true; } } Index: 3rdParty_sources/spring/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java (.../ResourceHttpRequestHandler.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java (.../ResourceHttpRequestHandler.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -39,6 +39,7 @@ import org.springframework.context.EmbeddedValueResolverAware; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; +import org.springframework.core.log.LogFormatUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRange; @@ -734,22 +735,25 @@ protected boolean isInvalidPath(String path) { if (path.contains("WEB-INF") || path.contains("META-INF")) { if (logger.isWarnEnabled()) { - logger.warn("Path with \"WEB-INF\" or \"META-INF\": [" + path + "]"); + logger.warn(LogFormatUtils.formatValue( + "Path with \"WEB-INF\" or \"META-INF\": [" + path + "]", -1, true)); } return true; } if (path.contains(":/")) { String relativePath = (path.charAt(0) == '/' ? path.substring(1) : path); if (ResourceUtils.isUrl(relativePath) || relativePath.startsWith("url:")) { if (logger.isWarnEnabled()) { - logger.warn("Path represents URL or has \"url:\" prefix: [" + path + "]"); + logger.warn(LogFormatUtils.formatValue( + "Path represents URL or has \"url:\" prefix: [" + path + "]", -1, true)); } return true; } } if (path.contains("..") && StringUtils.cleanPath(path).contains("../")) { if (logger.isWarnEnabled()) { - logger.warn("Path contains \"../\" after call to StringUtils#cleanPath: [" + path + "]"); + logger.warn(LogFormatUtils.formatValue( + "Path contains \"../\" after call to StringUtils#cleanPath: [" + path + "]", -1, true)); } return true; } Index: 3rdParty_sources/spring/org/springframework/web/servlet/tags/form/TagWriter.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/servlet/tags/form/TagWriter.java (.../TagWriter.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/servlet/tags/form/TagWriter.java (.../TagWriter.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -99,6 +99,18 @@ } /** + * Variant of {@link #writeAttribute(String, String)} for writing empty HTML + * attributes without a value such as {@code required}. + * @since 5.3.14 + */ + public void writeAttribute(String attributeName) throws JspException { + if (currentState().isBlockTag()) { + throw new IllegalStateException("Cannot write attributes after opening tag is closed."); + } + this.writer.append(" ").append(attributeName); + } + + /** * Write an HTML attribute if the supplied value is not {@code null} * or zero length. * @see #writeAttribute(String, String) Index: 3rdParty_sources/spring/org/springframework/web/util/ContentCachingRequestWrapper.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/util/ContentCachingRequestWrapper.java (.../ContentCachingRequestWrapper.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/util/ContentCachingRequestWrapper.java (.../ContentCachingRequestWrapper.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -48,7 +48,6 @@ *

Used e.g. by {@link org.springframework.web.filter.AbstractRequestLoggingFilter}. * Note: As of Spring Framework 5.0, this wrapper is built on the Servlet 3.1 API. * - * * @author Juergen Hoeller * @author Brian Clozel * @since 4.1.3 Index: 3rdParty_sources/spring/org/springframework/web/util/HtmlCharacterEntityDecoder.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/util/HtmlCharacterEntityDecoder.java (.../HtmlCharacterEntityDecoder.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/util/HtmlCharacterEntityDecoder.java (.../HtmlCharacterEntityDecoder.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -72,7 +72,7 @@ boolean isPotentialReference = (this.nextPotentialReferencePosition != -1 && this.nextSemicolonPosition != -1 && - this.nextPotentialReferencePosition - this.nextSemicolonPosition < MAX_REFERENCE_SIZE); + this.nextSemicolonPosition - this.nextPotentialReferencePosition < MAX_REFERENCE_SIZE); if (isPotentialReference) { break; Index: 3rdParty_sources/spring/org/springframework/web/util/ServletRequestPathUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/util/ServletRequestPathUtils.java (.../ServletRequestPathUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/util/ServletRequestPathUtils.java (.../ServletRequestPathUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -74,7 +74,7 @@ */ public static RequestPath getParsedRequestPath(ServletRequest request) { RequestPath path = (RequestPath) request.getAttribute(PATH_ATTRIBUTE); - Assert.notNull(path, "Expected parsed RequestPath in request attribute \"" + PATH_ATTRIBUTE + "\"."); + Assert.notNull(path, () -> "Expected parsed RequestPath in request attribute \"" + PATH_ATTRIBUTE + "\"."); return path; } Index: 3rdParty_sources/spring/org/springframework/web/util/UriUtils.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/util/UriUtils.java (.../UriUtils.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/util/UriUtils.java (.../UriUtils.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -407,7 +407,7 @@ int paramIndex = path.indexOf(';', begin); end = (paramIndex != -1 && paramIndex < end ? paramIndex : end); int extIndex = path.lastIndexOf('.', end); - if (extIndex != -1 && extIndex > begin) { + if (extIndex != -1 && extIndex >= begin) { return path.substring(extIndex + 1, end); } return null; Index: 3rdParty_sources/spring/org/springframework/web/util/UrlPathHelper.java =================================================================== diff -u -rd3b7bd0be7b298ffca42f0d33989d6fb4763cef6 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/spring/org/springframework/web/util/UrlPathHelper.java (.../UrlPathHelper.java) (revision d3b7bd0be7b298ffca42f0d33989d6fb4763cef6) +++ 3rdParty_sources/spring/org/springframework/web/util/UrlPathHelper.java (.../UrlPathHelper.java) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -578,8 +578,8 @@ return UriUtils.decode(source, enc); } catch (UnsupportedCharsetException ex) { - if (logger.isWarnEnabled()) { - logger.warn("Could not decode request string [" + source + "] with encoding '" + enc + + if (logger.isDebugEnabled()) { + logger.debug("Could not decode request string [" + source + "] with encoding '" + enc + "': falling back to platform default encoding; exception message: " + ex.getMessage()); } return URLDecoder.decode(source); Index: 3rdParty_sources/versions.txt =================================================================== diff -u -r5694a8e26e12cfd208ef7f26d736f02dc6749f23 -r3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f --- 3rdParty_sources/versions.txt (.../versions.txt) (revision 5694a8e26e12cfd208ef7f26d736f02dc6749f23) +++ 3rdParty_sources/versions.txt (.../versions.txt) (revision 3f71f6dbe6fdfaccdb5be53cea559235e0ff2e0f) @@ -63,7 +63,7 @@ Servlet API 4.0.0 -Spring 5.3.13 +Spring 5.3.18 Undertow core 2.0.13