Previously, canonicalPropertyName() located the end of a [key]
expression via a naive indexOf("]") search, while
AbstractNestablePropertyAccessor.getPropertyNameKeyEnd() -- used during
actual property resolution -- tracked bracket nesting depth. This meant
the two methods could disagree on the canonical form of a property
path whose map key itself contains bracket characters (e.g.,
map['key[0]']).
Similarly, getNestedPropertySeparatorIndex() tracked whether a dot
separator occurs inside a [key] expression using a simple boolean
toggle that flips on both '[' and ']', which produces an incorrect
result when a key contains an odd net count of inner bracket
characters.
To address those inconsistencies, this commit extracts the private
getPropertyNameKeyEnd() method from AbstractNestablePropertyAccessor to
a package-private static utility method in PropertyAccessorUtils, so
that canonicalPropertyName() can reuse the same depth-aware bracket
matching, and getNestedPropertySeparatorIndex() has been reworked to
track bracket nesting depth instead of toggling a boolean flag.
Closes gh-36999
Previously, PropertyEditorRegistrySupport.addStrippedPropertyPaths()
recursively enumerated every combination of stripped/retained [key]
segments in a property path, producing 2^n - 1 variants for a path
with n bracket pairs.
To address that, this commit limits the recursion at a depth of 8,
preserving existing behavior for realistic property paths while
bounding the work done for paths with an unusually large number of
bracket segments.
Closes gh-37020
Prior to this commit, the List branch in
AbstractNestablePropertyAccessor's getPropertyValue() method called
list.get(index) unconditionally after invoking
growCollectionIfNecessary(), which implicitly relied on the list
throwing an IndexOutOfBoundsException for out-of-range access. Such an
exception is caught downstream and wrapped as an
InvalidPropertyException; however, any List implementation whose get()
method allocates elements on demand rather than throwing an
IndexOutOfBoundsException could bypass that check.
This behavior was also inconsistent with the Collection/Iterable branch
in the same method, which already performs an explicit `index >=
collection.size()` bounds check before attempting element access.
To address that, this commit aligns the List branch with the
Collection/Iterable branch by adding an explicit `index < 0 || index >=
list.size()` check immediately after the auto-grow attempt. If the
index remains out of bounds after growCollectionIfNecessary() runs –
for example, because growth was capped by autoGrowCollectionLimit or
auto-growing was disabled – an InvalidPropertyException is now thrown
rather than delegating to list.get() which may or may not throw an
exception.
Closes gh-37036
Prior to this commit, PropertyDescriptorUtils.determineBasicProperties()
incorrectly recognized static `get` and `is` accessor methods as
JavaBean read methods, in contrast to the standard
java.beans.Introspector, which has always excluded static methods from
property discovery. This regression was introduced in Spring Framework
6.0 when determineBasicProperties() replaced the delegation to
java.beans.Introspector for the fast property-discovery path used by
SimpleBeanInfoFactory. As a result, an unrelated static method such as
a singleton accessor could be exposed as a bean property, and
reflective access to such a property (for example, via BeanWrapperImpl)
could lead to a StackOverflowError if the property's value recursively
exposed the same static accessor.
To address that, this commit adds Modifier.isStatic(...) checks to the
`get` and `is` branches in determineBasicProperties(), mirroring the
equivalent check already present in
CachedIntrospectionResults.isPlainAccessor(). Static `set` methods
continue to be supported as write methods, consistent with the existing
behavior in ExtendedBeanInfo.
See gh-37068
Closes gh-37081
Signed-off-by: Arnab Nandy <arnab_nandy7@yahoo.com>
This commit addresses warnings across the code base related to:
- internal and public deprecations in Spring Framework
- deprecated Locale constructors
- deprecated URL constructors
- deprecated Thread#getId method
Revise the BeanRegistrar Javadoc to document the two distinct usage
modes: @Configuration/@Import and programmatic GenericApplicationContext
setup.
Clarify that implementations are not Spring components (requiring a
no-arg constructor and no dependency injection), and detail the ordering
guarantees for each mode.
Add missing tests
Signed-off-by: Stéphane Nicoll <stephane.nicoll@broadcom.com>
The resolveDependency() utility method in ParameterResolutionDelegate
resolves a dependency using the name of the parameter as a fallback
qualifier. That suffices for most use cases; however, there are times
when a custom parameter name should be used instead.
For example, for our Bean Override support in the Spring TestContext
Framework, an annotation such as @MockitoBean("myBean") specifies an
explicit name that should be used instead of name of the annotated
parameter.
Furthermore, introducing support for custom parameter names will
greatly simplify the logic in SpringExtension that will be required to
implement #36096.
To address those issues, this commit introduces an overloaded variant
of resolveDependency() which accepts a custom parameter name.
Internally, a custom DependencyDescriptor has been implemented to
transparently support this use case.
See gh-36096
Closes gh-36534