In order to keep the maximum of flexibility, this commit makes
shouldSkipType and shouldSkipMembers methods private.
That will allow for example to refactor
BindingReflectionHintsRegistrar in order to support skipping
custom classes specified via @RegisterReflectionForBinding
without having to subclass it.
See gh-29279
This commit also removes ResourcePropertiesPersister which
was introduced in 5.3 specifically for spring.xml.ignore
flag and which is expected to be used only internally by
Spring Framework. DefaultPropertiesPersister should be used
instead.
Closes gh-29277
This commit introduces a shouldSkipType(Class<?> type) method
and changes shouldRegisterMembers(Class<?> type) to
shouldSkipMembers(Class<?> type).
Closes gh-29279
Prior to this commit, if a FileSystemResource was created from a
java.nio.file.Path or java.nio.file.FileSystem, the URI returned from
getURI() was based on the semantics of Path#toUri() which always
includes the "authority component" (i.e., "//") after the scheme (e.g.,
"file://..."). In contrast, if a FileSystemResource is created from a
java.io.File or String, the URI returned from getURI() never includes
the "authority component" due to the semantics of File#toURI().
Consequently, invoking myFileSystemResource.getURI().toString() could
result in "file:/my/path" or "file:///my/path", depending on how the
FileSystemResource was created.
This behavior is not new; however, recent changes in
PathMatchingResourcePatternResolver -- which result in a
FileSystemResource being created from a java.nio.file.Path instead of
from a java.io.File -- make this difference more noticeable to users
and may in fact surface as a breaking change.
To address that issue, this commit revises the implementation of
FileSystemResource.getURI() by normalizing any `file:` URIs that it
returns. Effectively, URIs like "file:///my/path" will now take the
form "file:/my/path".
See gh-29163
Closes gh-29275
Prior to this commit, if two ClassPathResource instances were
constructed differently (one from an absolute path and one from a path
relative to a Class) but had the same absolute path and the same
ClassLoader, they were effectively equal, but ClassPathResource#equals
returned false.
This commit addresses this by revising the logic in
ClassPathResource#equals accordingly.
Closes gh-29263
Prior to this commit, UrlResource#getFilename() returned the filename
of the resource URL-encoded which is in contrast to what
FileSystemResource#getFilename() returns for an equivalent resource.
In addition, users most likely expect that a filename returned from a
method defined in the Resource interface is unencoded.
This commit therefore revises UrlResource#getFilename() so that it
always returns the filename URL-decoded.
Closes gh-29261
This commit introduces assertions that verify that the sub-path is
properly URL-decoded when a path contains `#`. The additional assertions
are necessary since the existing assertions use Resource#getFilename
which already implicitly decodes the path.
See gh-29243
This commit introduces tests which serve as "regression tests" for the
behavior of PathMatchingResourcePatternResolver in Spring Framework
5.3.x with regard to URL-encoding and Unicode normalization of resource
paths.
Specifically, the new tests demonstrate that resource paths do NOT need
to be decoded or normalized in 5.3.x.
See gh-29243
Prior to this commit, the parsing algorithm in
`StringUtils#parseLocaleString` would skip empty tokens, turning
`en__VARIANT` into `en_VARIANT` when parsed.
This commit ensures that such cases are now supported and that more
invalid formats are rejected by the parser.
Fixes gh-29248
This commit adapts AccessVisibility so that it can determine if the
member or type signature is accessible from a given package. This lets
implementers figure out if reflection is necessary without assuming that
package private visibility is OK.
Closes gh-29245
In addition to consistent use of cleaned file paths, this revision avoids FileSystem SPI interaction, resolving NIO Path instances from URI (and FileSystemResource from Path).
See gh-29226
Prior to this commit, the AOT infrastructure would rely on the fact that
native runtime reflection on a type would only consider
methods/fields/constructors that had specific hints contributed. When
listing them through the reflection API on the type, the native image
would only return those for which we had hints contributed.
This behavior will soon change in GraalVM and will better align with the
JVM behavior: when asking for all declared methods on a type in a native
image, we should get all existing methods, not just the ones registered
previously in the native image.
This commit aligns the behavior of the `RuntimeHintsAgent` and removes
the now misleading predicates as a consequence.
Closes gh-29205
Commit 0eb66789ed which introduced generic FileSystem support in
PathMatchingResourcePatternResolver also introduced a regression in that
a matching folder is now returned in the results.
This commit address this by additionally using Files#isRegularFile() in
the predicate used to filter candidates.
Closes gh-29163
The upgrade to SLF4J 2 via gh-29152 has broken
ConstantFieldSubstitutionProcessor when the class processed
has both a static boolean field to make constant at build
time and a static logger.
This issue is about catching and logging those errors,
skipping the processing of such fields which will be
then evaluated at runtime.
Closes gh-29219
The JDK has decent support for walking a file system (via the
FileSystem API in java.nio.file), but prior to this commit Spring still
used hand-rolled pre-Java 7 code. Also, in principle, FileSystem can be
an abstraction used to express any hierarchy of resources through their
URIs. This is a good fit with the Spring Resource abstraction, and for
instance would mean that GraalVM native images could potentially do
classpath scanning through a custom URI and FileSystem already provided
by GraalVM.
In light of the above, this commit overhauls the implementation of
PathMatchingResourcePatternResolver to use a java.nio.file.FileSystem
to find matching resources within a file system.
As a side effect, several obsolete `protected` methods have been
removed from PathMatchingResourcePatternResolver.
See gh-29163
This commit improves GeneratedClass to support inner classes, allowing
them to be registered by name with a type customizer, as
GeneratedClasses does for top level classes.
BeanDefinitionMethodGenerator leverages this feature to create a
matching structure for configuration classes that contain inner classes.
Closes gh-29213
This commit adds an overloaded version of invokeSuspendingFunction
that specifies a CoroutineContext, instead of using
Dispatchers.Unconfined.
Closes gh-27193
This commit updates ClassNameGenerator so that it uses a ClassName for
its default target. This makes sure that a target that has been
generated can be used.
See gh-29027
In general, `Stream#toList()` is not a transparent replacement for
`.collect(Collectors.toList()))`, as the former returns an immutable
list.
This commit reverts some of those changes, where the returned `List`
instance was expected to be mutable.
See gh-29203
Prior to this commit, resource handling would not serve empty files and
return instead HTTP 404 responses. This would only happen for files
contained by JARs, but not on the filesystem.
This can be tracked to changes done in `AbstractFileResolvingResource`
where we avoid serving empty files for directories, see gh-21372.
This commit improves the `checkReadable` method to align this behavior
between file system and JAR files.
Closes gh-28850
Prior to this commit, the following exception was thrown when using the
PathMatchingResourcePatternResolver to scan for class path resources
using the `classpath*:` prefix within a native image.
com.oracle.svm.core.jdk.UnsupportedFeatureError: JRT file system is disabled
com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89)
jdk.internal.module.SystemModuleFinders$SystemImage.reader(SystemModuleFinders.java:139)
jdk.internal.module.SystemModuleFinders$ModuleContentSpliterator.<init>(SystemModuleFinders.java:527)
jdk.internal.module.SystemModuleFinders$SystemModuleReader.list(SystemModuleFinders.java:502)
org.springframework.core.io.support.PathMatchingResourcePatternResolver.lambda$findAllModulePathResources$6(PathMatchingResourcePatternResolver.java:819)
This commit addresses this by not attempting to scan the module path
when running in a GraalVM native image.
Closes gh-29183
In preparation for gh-29163, this commit revamps
PathMatchingResourcePatternResolverTests as follows.
- organizes tests into @Nested test classes
- reintroduces the @Disabled classpathStarWithPatternOnFileSystem() test
- stops asserting the protocol of Resource URLs, since the protocol is
dependent on the environment -- for example, file: and jar: URLs are
actually resource: URLs within a GraalVM native image
- simplifies implementation of test methods and assertFilenames()
Previously, only the first occurance of `@Reflective` and its
processor was considered. When `@Reflective` appeared twice on a type
due to meta-annotations or inheritance, this resulted in other
processors being ignored and hints were missing as a result.
This commit updates ReflectiveRuntimeHintsRegistrar to consider
every occurance of `@Reflective` found in the type hierarchy,
and to then use the processors from each of them.
Fixes gh-29193
gh-28506 introduces a big footprint regression on
native, so it should for now be skipped when
compiling to native images. Such support could
potentially be re-introduced via gh-29081.
Closes gh-29183
This commit fixes an issue in StringDecoder, where, if the buffer did
not contain any delimiters, it was released before it was relayed to
any subscribers.
Closes gh-29119
This commit adds predicates variants that accept `String className`
instead of actual `Class<?>` when checking for fields and method hints.
This is useful when the type under test is not visible from the current
test class.
Closes gh-29143
Prior to this commit, the Javadoc for the getPath() method in
ClassPathResource stated the following.
> Return the path for this resource (as resource path within the class path).
That implied the returned path was an "absolute path" within the class
path; however, that was not always true.
If the resource was created using ClassPathResource(String) or
ClassPathResource(String, ClassLoader), the returned path was a cleaned
version of the ABSOLUTE PATH supplied to the constructor, WITHOUT a
leading slash.
If the resource was created using ClassPathResource(String, Class) with
an absolute path, the returned path was a cleaned version of the
ABSOLUTE PATH supplied to the constructor, WITH a leading slash.
If the resource was created using ClassPathResource(String, Class) with
a relative path, the returned path was a cleaned version of the
RELATIVE PATH supplied to the constructor.
In addition, ClassPathResource does not provide public access the Class
passed to the ClassPathResource(String, Class) constructor.
Consequently, the path returned by getPath() could not be reliably used
with ClassLoader.getResource(String) or with the recently introduced
registerResource(Resource) method in ResourceHints.
This commit addresses this issue by ensuring that getPath()
consistently returns the absolute path within the class path without a
leading slash.
See gh-29083
Reverts gh-29094
Closes gh-29099
Previously, a shortcut method for the default ExecutableMode was
provided, but we found out that the shortcut makes it harder to
determine the intent.
This commit harmonizes hints registration for types, methods, and
fields. An ExecutableMode is now mandatory to register a method or
constructor. Previous methods that infer a mode or provided a
customizer of the builder are deprecated.
Closes gh-29135
In recent GraalVM versions, allowWrite and allowUnsafeAccess have been
deprecated and are no longer use. This commit updates FieldHint to
remove the irrelevant properties.
See gh-29130
Update StreamUtils.drain to use InputStream.transferTo with a null
OutputStream. This avoids allocating buffers for cases where the
supplied InputStream has an optimized transferTo method (e.g.,
ByteArrayInputStream and FileInputStream).
Additionally, update StreamUtils.emptyInput to simply call
InputStream.nullInputStream.
Closes gh-28961
This commit records `@PropertySource` declarations defined on
configuration classes so that these are contributed to the environment
of a context that is initialized by generated code.
Closes gh-28976
This commit moves MethodReference to an interface with a default
implementation that relies on a MethodSpec. Such an arrangement avoid
the need of specifying attributes of the method such as whether it is
static or not.
The resolution of the invocation block now takes an
ArgumentCodeGenerator rather than the raw arguments. Doing so gives
the opportunity to create more flexible signatures.
See gh-29005
This commit updates GeneratedMethod and its underlying infrastructure
to be able to produce a MethodReference. This simplifies the need when
such a reference needs to be created manually and reuses more of what
MethodReference has to offer.
See gh-29005
This commit renames registerResourceIfNecessary() to registerResource()
and throws an exception if the class path resource does not exist.
Closes gh-29083
This aligns the buffer size used in StreamUtils with the buffer sizes
used throughout the JDK (see InputStream, BufferedInputStream, Files).
Closes gh-28965
As of Java 18, the serial lint warning in javac has been expanded to
check for class fields that are not marked as `Serializable`.
See https://www.oracle.com/java/technologies/javase/18all-relnotes.html#JDK-8202056
In the Spring Framework codebase, this can happen with `Map`, `Set` or
`List` attributes which are often assigned with an unmodifiable
implementation variant. Such implementations are `Serializable` but
cannot be used as field types.
This commit ensures that the following changes are applied:
* fields are marked as transient if they can't be serialized
* classes are marked as `Serializable` if this was missing
* `@SuppressWarnings("serial")` is applied where relevant
Prior to this commit, the `RuntimeHintsAgent` and its testing
infrastructure would assume that calling `MyClass.class.getMethods()`
requires a reflection hint on the class for introspecting public/private
methods.
GraalVM does not require this, in fact this call only returns methods
that have reflection hints in the native image.
This commit refines the agent behavior for `Class.getMethods()`,
`Class.getDeclaredMethods()`, `Class.getFields()` and
`Class.getDeclaredFields()`. With this change, registering at least one
method/field for reflection is enough to match.
During the execution of Java tests, all methods and fields will be
provided, regardless of hints being registered or not. This could cause
false negatives where we're missing reflection hints on methods or
fields.
This risk is mitigated thanks to additional instrumentation on
`Method.getAnnotations()`, `Method.getParameterTypes()` and
`Method.invoke()`. If a method is found reflectively, chances are it
will be used for further reflection.
Closes gh-29091
Since getPath() returns a relative path if the resource was created
using the ClassPathResource(String,Class) constructor, there was
previously no way to consistently obtain the absolute path to the
resource within the class path.
This commit addresses this shortcoming by introducing a new
getAbsolutePath() for consistently obtaining the absolute path to the
resource within the class path.
See gh-29083
Closes gh-29094
This commit introduces a new registerResourceIfNecessary() method in
RuntimeHintsUtils that simplifies the registration of hints for
`classpath:` resources.
Closes gh-29083
Prior to this commit, if a ResourcePatternHint was created with a
resource pattern with a leading slash, the hint was registered and
eventually converted to configuration for the GraalVM native image
compiler.
However, such a resource pattern is invalid for GraalVM. Consequently,
the registered resources were not available within the compiled native
image.
This commit ensures that registered patterns are applicable in a native
image by preventing creation of a ResourcePatternHint with a pattern
with a leading slash.
Closes gh-29088
Prior to this commit, if the TypeReference supplied to
ResourceHintsPredicates.forResource(TypeReference,String) was for a
class declared in the default package (i.e., without a package), the
resolveAbsoluteResourceName() method incorrectly prepended two leading
slashes (//) to the absolute resource name, causing correct matches to
fail.
This commit fixes this by adding special handling for a TypeReference
without a package name. In addition, this commit introduces lenient
handling of resource names by consistently removing a leading slash in
ResourceHintsPredicates.forResource(*) methods. The latter aligns with
absolute resource path handling in other places in the framework, such
as ClassPathResource.
Closes gh-29086
This commit adds support generating graalvm `jni-config.json` file.
Configuration format for jni/reflection in graalvm is documented
to be exactly same so we can re-use facilities for reflection hints
which should be relatively clean for a user as also graalvm uses same
classes for both jni/reflection.
Closes gh-29007
This annotation and the related processor allows to
register reflection hints for data binding purpose
(class, fields, properties, record components for
the whole type hierarchy)
Closes gh-28979
This commit provides an alternative
java.beans.Introspector#findCustomizerClass implementation
via a GraalVM substitution that avoids to include thousands
of unused AWT classes in the native image.
Closes gh-29060