Revisit RuntimeHints API
The `RuntimeHints` API mainly reflects what is needed to write GraalVM reachability metadata. The latest GraalVM version simplified its format. This commit applies relevant simplifications as parts of it are not needed anymore. The new metadata format implies methods, constructors and fields introspection as soon as a reflection hint is registered for a type. As a result, `ExecutableMode.INTROSPECT`, and all `MemberCategory` values except `MemberCategory.INVOKE_*` are being deprecated. They have no replacement, as registering a type hint is enough. In practice, it is enough to replace this: ``` hints.reflection().registerType(MyType.class, MemberCategory.DECLARED_FIELDS); ``` By this: ``` hints.reflection().registerType(MyType.class); ``` As for `MemberCategory.PUBLIC_FIELDS` and `MemberCategory.DECLARED_FIELDS`, values were replaced by `INVOKE_PUBLIC_FIELDS` and `INVOKE_DECLARED_FIELDS` to make their original intent clearer and align with the rest of the API. Note, if you were using those values for reflection only, you can safely remove those hints in favor of a simple type hint. See gh-33847
This commit is contained in:
parent
fec2ed5540
commit
71362c953c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -30,7 +30,10 @@ public enum ExecutableMode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only retrieving the {@link Executable} and its metadata is required.
|
* Only retrieving the {@link Executable} and its metadata is required.
|
||||||
|
* @deprecated with no replacement since introspection is included
|
||||||
|
* when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since= "7.0", forRemoval = true)
|
||||||
INTROSPECT,
|
INTROSPECT,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2023 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -32,32 +32,62 @@ import java.lang.reflect.Method;
|
||||||
public enum MemberCategory {
|
public enum MemberCategory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A category that represents public {@linkplain Field fields}.
|
* A category that represents introspection on public {@linkplain Field fields}.
|
||||||
|
* @deprecated with no replacement since introspection is included
|
||||||
|
* when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}.
|
||||||
|
* Use {@link #INVOKE_PUBLIC_FIELDS} if getting/setting field values is required.
|
||||||
* @see Class#getFields()
|
* @see Class#getFields()
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "7.0", forRemoval = true)
|
||||||
PUBLIC_FIELDS,
|
PUBLIC_FIELDS,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A category that represents {@linkplain Class#getDeclaredFields() declared
|
* A category that represents introspection on {@linkplain Class#getDeclaredFields() declared
|
||||||
* fields}: all fields defined by the class but not inherited fields.
|
* fields}: all fields defined by the class but not inherited fields.
|
||||||
|
* @deprecated with no replacement since introspection is included
|
||||||
|
* when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}.
|
||||||
|
* Use {@link #INVOKE_DECLARED_FIELDS} if getting/setting field values is required.
|
||||||
* @see Class#getDeclaredFields()
|
* @see Class#getDeclaredFields()
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "7.0", forRemoval = true)
|
||||||
DECLARED_FIELDS,
|
DECLARED_FIELDS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A category that represents getting/setting values on public {@linkplain Field fields}.
|
||||||
|
* @see Field#get(Object)
|
||||||
|
* @see Field#set(Object, Object)
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
INVOKE_PUBLIC_FIELDS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A category that represents getting/setting values on declared {@linkplain Field fields}.
|
||||||
|
* @see Field#get(Object)
|
||||||
|
* @see Field#set(Object, Object)
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
INVOKE_DECLARED_FIELDS,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A category that defines public {@linkplain Constructor constructors} can
|
* A category that defines public {@linkplain Constructor constructors} can
|
||||||
* be introspected but not invoked.
|
* be introspected but not invoked.
|
||||||
|
* @deprecated with no replacement since introspection is included
|
||||||
|
* when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}.
|
||||||
* @see Class#getConstructors()
|
* @see Class#getConstructors()
|
||||||
* @see ExecutableMode#INTROSPECT
|
* @see ExecutableMode#INTROSPECT
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "7.0", forRemoval = true)
|
||||||
INTROSPECT_PUBLIC_CONSTRUCTORS,
|
INTROSPECT_PUBLIC_CONSTRUCTORS,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A category that defines {@linkplain Class#getDeclaredConstructors() all
|
* A category that defines {@linkplain Class#getDeclaredConstructors() all
|
||||||
* constructors} can be introspected but not invoked.
|
* constructors} can be introspected but not invoked.
|
||||||
|
* @deprecated with no replacement since introspection is included
|
||||||
|
* when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}.
|
||||||
* @see Class#getDeclaredConstructors()
|
* @see Class#getDeclaredConstructors()
|
||||||
* @see ExecutableMode#INTROSPECT
|
* @see ExecutableMode#INTROSPECT
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "7.0", forRemoval = true)
|
||||||
INTROSPECT_DECLARED_CONSTRUCTORS,
|
INTROSPECT_DECLARED_CONSTRUCTORS,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,17 +109,23 @@ public enum MemberCategory {
|
||||||
/**
|
/**
|
||||||
* A category that defines public {@linkplain Method methods}, including
|
* A category that defines public {@linkplain Method methods}, including
|
||||||
* inherited ones, can be introspected but not invoked.
|
* inherited ones, can be introspected but not invoked.
|
||||||
|
* @deprecated with no replacement since introspection is added by default
|
||||||
|
* when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}.
|
||||||
* @see Class#getMethods()
|
* @see Class#getMethods()
|
||||||
* @see ExecutableMode#INTROSPECT
|
* @see ExecutableMode#INTROSPECT
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "7.0", forRemoval = true)
|
||||||
INTROSPECT_PUBLIC_METHODS,
|
INTROSPECT_PUBLIC_METHODS,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A category that defines {@linkplain Class#getDeclaredMethods() all
|
* A category that defines {@linkplain Class#getDeclaredMethods() all
|
||||||
* methods}, excluding inherited ones, can be introspected but not invoked.
|
* methods}, excluding inherited ones, can be introspected but not invoked.
|
||||||
|
* @deprecated with no replacement since introspection is added by default
|
||||||
|
* when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}.
|
||||||
* @see Class#getDeclaredMethods()
|
* @see Class#getDeclaredMethods()
|
||||||
* @see ExecutableMode#INTROSPECT
|
* @see ExecutableMode#INTROSPECT
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "7.0", forRemoval = true)
|
||||||
INTROSPECT_DECLARED_METHODS,
|
INTROSPECT_DECLARED_METHODS,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,7 +150,10 @@ public enum MemberCategory {
|
||||||
* <p>Contrary to other categories, this does not register any particular
|
* <p>Contrary to other categories, this does not register any particular
|
||||||
* reflection for inner classes but rather makes sure they are available
|
* reflection for inner classes but rather makes sure they are available
|
||||||
* via a call to {@link Class#getClasses}.
|
* via a call to {@link Class#getClasses}.
|
||||||
|
* @deprecated with no replacement since introspection is included
|
||||||
|
* when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "7.0", forRemoval = true)
|
||||||
PUBLIC_CLASSES,
|
PUBLIC_CLASSES,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,7 +162,10 @@ public enum MemberCategory {
|
||||||
* <p>Contrary to other categories, this does not register any particular
|
* <p>Contrary to other categories, this does not register any particular
|
||||||
* reflection for inner classes but rather makes sure they are available
|
* reflection for inner classes but rather makes sure they are available
|
||||||
* via a call to {@link Class#getDeclaredClasses}.
|
* via a call to {@link Class#getDeclaredClasses}.
|
||||||
|
* @deprecated with no replacement since introspection is included
|
||||||
|
* when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "7.0", forRemoval = true)
|
||||||
DECLARED_CLASSES
|
DECLARED_CLASSES
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,6 +255,7 @@ public class ReflectionHintsPredicates {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
public abstract static class ExecutableHintPredicate<T extends Executable> implements Predicate<RuntimeHints> {
|
public abstract static class ExecutableHintPredicate<T extends Executable> implements Predicate<RuntimeHints> {
|
||||||
|
|
||||||
protected final T executable;
|
protected final T executable;
|
||||||
|
@ -299,6 +300,7 @@ public class ReflectionHintsPredicates {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
public static class ConstructorHintPredicate extends ExecutableHintPredicate<Constructor<?>> {
|
public static class ConstructorHintPredicate extends ExecutableHintPredicate<Constructor<?>> {
|
||||||
|
|
||||||
ConstructorHintPredicate(Constructor<?> constructor) {
|
ConstructorHintPredicate(Constructor<?> constructor) {
|
||||||
|
@ -308,28 +310,17 @@ public class ReflectionHintsPredicates {
|
||||||
@Override
|
@Override
|
||||||
public boolean test(RuntimeHints runtimeHints) {
|
public boolean test(RuntimeHints runtimeHints) {
|
||||||
return (new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass()))
|
return (new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass()))
|
||||||
.withAnyMemberCategory(getPublicMemberCategories())
|
.and(hints -> this.executableMode == ExecutableMode.INTROSPECT))
|
||||||
.and(hints -> Modifier.isPublic(this.executable.getModifiers())))
|
.or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass()))
|
||||||
.or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())).withAnyMemberCategory(getDeclaredMemberCategories()))
|
.withMemberCategory(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS)
|
||||||
|
.and(hints -> Modifier.isPublic(this.executable.getModifiers()))
|
||||||
|
.and(hints -> this.executableMode == ExecutableMode.INVOKE))
|
||||||
|
.or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass()))
|
||||||
|
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)
|
||||||
|
.and(hints -> this.executableMode == ExecutableMode.INVOKE))
|
||||||
.or(exactMatch()).test(runtimeHints);
|
.or(exactMatch()).test(runtimeHints);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemberCategory[] getPublicMemberCategories() {
|
|
||||||
if (this.executableMode == ExecutableMode.INTROSPECT) {
|
|
||||||
return new MemberCategory[] { MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS,
|
|
||||||
MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS };
|
|
||||||
}
|
|
||||||
return new MemberCategory[] { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS };
|
|
||||||
}
|
|
||||||
|
|
||||||
MemberCategory[] getDeclaredMemberCategories() {
|
|
||||||
if (this.executableMode == ExecutableMode.INTROSPECT) {
|
|
||||||
return new MemberCategory[] { MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS,
|
|
||||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS };
|
|
||||||
}
|
|
||||||
return new MemberCategory[] { MemberCategory.INVOKE_DECLARED_CONSTRUCTORS };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Predicate<RuntimeHints> exactMatch() {
|
Predicate<RuntimeHints> exactMatch() {
|
||||||
return hints -> {
|
return hints -> {
|
||||||
|
@ -343,6 +334,7 @@ public class ReflectionHintsPredicates {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
public static class MethodHintPredicate extends ExecutableHintPredicate<Method> {
|
public static class MethodHintPredicate extends ExecutableHintPredicate<Method> {
|
||||||
|
|
||||||
MethodHintPredicate(Method method) {
|
MethodHintPredicate(Method method) {
|
||||||
|
@ -352,31 +344,18 @@ public class ReflectionHintsPredicates {
|
||||||
@Override
|
@Override
|
||||||
public boolean test(RuntimeHints runtimeHints) {
|
public boolean test(RuntimeHints runtimeHints) {
|
||||||
return (new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass()))
|
return (new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass()))
|
||||||
.withAnyMemberCategory(getPublicMemberCategories())
|
.and(hints -> this.executableMode == ExecutableMode.INTROSPECT))
|
||||||
.and(hints -> Modifier.isPublic(this.executable.getModifiers())))
|
.or((new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass()))
|
||||||
.or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass()))
|
.withMemberCategory(MemberCategory.INVOKE_PUBLIC_METHODS)
|
||||||
.withAnyMemberCategory(getDeclaredMemberCategories())
|
.and(hints -> Modifier.isPublic(this.executable.getModifiers()))
|
||||||
.and(hints -> !Modifier.isPublic(this.executable.getModifiers())))
|
.and(hints -> this.executableMode == ExecutableMode.INVOKE)))
|
||||||
|
.or((new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass()))
|
||||||
|
.withMemberCategory(MemberCategory.INVOKE_DECLARED_METHODS)
|
||||||
|
.and(hints -> !Modifier.isPublic(this.executable.getModifiers()))
|
||||||
|
.and(hints -> this.executableMode == ExecutableMode.INVOKE)))
|
||||||
.or(exactMatch()).test(runtimeHints);
|
.or(exactMatch()).test(runtimeHints);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemberCategory[] getPublicMemberCategories() {
|
|
||||||
if (this.executableMode == ExecutableMode.INTROSPECT) {
|
|
||||||
return new MemberCategory[] { MemberCategory.INTROSPECT_PUBLIC_METHODS,
|
|
||||||
MemberCategory.INVOKE_PUBLIC_METHODS };
|
|
||||||
}
|
|
||||||
return new MemberCategory[] { MemberCategory.INVOKE_PUBLIC_METHODS };
|
|
||||||
}
|
|
||||||
|
|
||||||
MemberCategory[] getDeclaredMemberCategories() {
|
|
||||||
|
|
||||||
if (this.executableMode == ExecutableMode.INTROSPECT) {
|
|
||||||
return new MemberCategory[] { MemberCategory.INTROSPECT_DECLARED_METHODS,
|
|
||||||
MemberCategory.INVOKE_DECLARED_METHODS };
|
|
||||||
}
|
|
||||||
return new MemberCategory[] { MemberCategory.INVOKE_DECLARED_METHODS };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Predicate<RuntimeHints> exactMatch() {
|
Predicate<RuntimeHints> exactMatch() {
|
||||||
return hints -> {
|
return hints -> {
|
||||||
|
@ -394,31 +373,40 @@ public class ReflectionHintsPredicates {
|
||||||
|
|
||||||
private final Field field;
|
private final Field field;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private ExecutableMode executableMode;
|
||||||
|
|
||||||
FieldHintPredicate(Field field) {
|
FieldHintPredicate(Field field) {
|
||||||
this.field = field;
|
this.field = field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refine the current predicate to only match if an invocation hint is registered for this field.
|
||||||
|
* @return the refined {@link RuntimeHints} predicate
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
public FieldHintPredicate invocation() {
|
||||||
|
this.executableMode = ExecutableMode.INVOKE;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(RuntimeHints runtimeHints) {
|
public boolean test(RuntimeHints runtimeHints) {
|
||||||
TypeHint typeHint = runtimeHints.reflection().getTypeHint(this.field.getDeclaringClass());
|
TypeHint typeHint = runtimeHints.reflection().getTypeHint(this.field.getDeclaringClass());
|
||||||
if (typeHint == null) {
|
if (typeHint != null) {
|
||||||
return false;
|
if (this.executableMode == ExecutableMode.INVOKE) {
|
||||||
|
if (Modifier.isPublic(this.field.getModifiers())) {
|
||||||
|
return typeHint.getMemberCategories().contains(MemberCategory.INVOKE_PUBLIC_FIELDS);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return typeHint.getMemberCategories().contains(MemberCategory.INVOKE_DECLARED_FIELDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return memberCategoryMatch(typeHint) || exactMatch(typeHint);
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
private boolean memberCategoryMatch(TypeHint typeHint) {
|
|
||||||
if (Modifier.isPublic(this.field.getModifiers())) {
|
|
||||||
return typeHint.getMemberCategories().contains(MemberCategory.PUBLIC_FIELDS);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return typeHint.getMemberCategories().contains(MemberCategory.DECLARED_FIELDS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean exactMatch(TypeHint typeHint) {
|
|
||||||
return typeHint.fields().anyMatch(fieldHint ->
|
|
||||||
this.field.getName().equals(fieldHint.getName()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,14 +19,13 @@ package org.springframework.aot.hint.predicate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.springframework.aot.hint.ResourceHints;
|
import org.springframework.aot.hint.ResourceHints;
|
||||||
import org.springframework.aot.hint.ResourcePatternHint;
|
import org.springframework.aot.hint.ResourcePatternHint;
|
||||||
import org.springframework.aot.hint.RuntimeHints;
|
import org.springframework.aot.hint.RuntimeHints;
|
||||||
import org.springframework.aot.hint.TypeReference;
|
import org.springframework.aot.hint.TypeReference;
|
||||||
|
import org.springframework.util.AntPathMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ConcurrentLruCache;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generator of {@link ResourceHints} predicates, testing whether the given hints
|
* Generator of {@link ResourceHints} predicates, testing whether the given hints
|
||||||
|
@ -39,7 +38,7 @@ import org.springframework.util.ConcurrentLruCache;
|
||||||
*/
|
*/
|
||||||
public class ResourceHintsPredicates {
|
public class ResourceHintsPredicates {
|
||||||
|
|
||||||
private static final ConcurrentLruCache<ResourcePatternHint, Pattern> CACHED_RESOURCE_PATTERNS = new ConcurrentLruCache<>(32, ResourcePatternHint::toRegex);
|
private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
|
||||||
|
|
||||||
ResourceHintsPredicates() {
|
ResourceHintsPredicates() {
|
||||||
}
|
}
|
||||||
|
@ -100,26 +99,18 @@ public class ResourceHintsPredicates {
|
||||||
return hints -> {
|
return hints -> {
|
||||||
AggregatedResourcePatternHints aggregatedResourcePatternHints = AggregatedResourcePatternHints.of(
|
AggregatedResourcePatternHints aggregatedResourcePatternHints = AggregatedResourcePatternHints.of(
|
||||||
hints.resources());
|
hints.resources());
|
||||||
boolean isExcluded = aggregatedResourcePatternHints.excludes().stream().anyMatch(excluded ->
|
|
||||||
CACHED_RESOURCE_PATTERNS.get(excluded).matcher(resourceNameToUse).matches());
|
|
||||||
if (isExcluded) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return aggregatedResourcePatternHints.includes().stream().anyMatch(included ->
|
return aggregatedResourcePatternHints.includes().stream().anyMatch(included ->
|
||||||
CACHED_RESOURCE_PATTERNS.get(included).matcher(resourceNameToUse).matches());
|
PATH_MATCHER.match(included.getPattern(), resourceNameToUse));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private record AggregatedResourcePatternHints(List<ResourcePatternHint> includes, List<ResourcePatternHint> excludes) {
|
private record AggregatedResourcePatternHints(List<ResourcePatternHint> includes) {
|
||||||
|
|
||||||
static AggregatedResourcePatternHints of(ResourceHints resourceHints) {
|
static AggregatedResourcePatternHints of(ResourceHints resourceHints) {
|
||||||
List<ResourcePatternHint> includes = new ArrayList<>();
|
List<ResourcePatternHint> includes = new ArrayList<>();
|
||||||
List<ResourcePatternHint> excludes = new ArrayList<>();
|
resourceHints.resourcePatternHints().forEach(resourcePatternHint ->
|
||||||
resourceHints.resourcePatternHints().forEach(resourcePatternHint -> {
|
includes.addAll(resourcePatternHint.getIncludes()));
|
||||||
includes.addAll(resourcePatternHint.getIncludes());
|
return new AggregatedResourcePatternHints(includes);
|
||||||
excludes.addAll(resourcePatternHint.getExcludes());
|
|
||||||
});
|
|
||||||
return new AggregatedResourcePatternHints(includes, excludes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @since 6.0
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("removal")
|
||||||
class ExecutableHintTests {
|
class ExecutableHintTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("removal")
|
||||||
class ExecutableModeTests {
|
class ExecutableModeTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -37,6 +37,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Sebastien Deleuze
|
* @author Sebastien Deleuze
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("removal")
|
||||||
class ReflectionHintsTests {
|
class ReflectionHintsTests {
|
||||||
|
|
||||||
private final ReflectionHints reflectionHints = new ReflectionHints();
|
private final ReflectionHints reflectionHints = new ReflectionHints();
|
||||||
|
|
|
@ -117,7 +117,7 @@ class ResourceHintsTests {
|
||||||
@Test
|
@Test
|
||||||
void registerPatternWithIncludesAndExcludes() {
|
void registerPatternWithIncludesAndExcludes() {
|
||||||
this.resourceHints.registerPattern(resourceHint ->
|
this.resourceHints.registerPattern(resourceHint ->
|
||||||
resourceHint.includes("com/example/*.properties").excludes("com/example/to-ignore.properties"));
|
resourceHint.includes("com/example/*.properties"));
|
||||||
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(patternOf(
|
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(patternOf(
|
||||||
List.of("/", "com", "com/example", "com/example/*.properties"),
|
List.of("/", "com", "com/example", "com/example/*.properties"),
|
||||||
List.of("com/example/to-ignore.properties")));
|
List.of("com/example/to-ignore.properties")));
|
||||||
|
@ -198,10 +198,7 @@ class ResourceHintsTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Consumer<ResourcePatternHints> patternOf(List<String> includes, List<String> excludes) {
|
private Consumer<ResourcePatternHints> patternOf(List<String> includes, List<String> excludes) {
|
||||||
return pattern -> {
|
return pattern -> assertThat(pattern.getIncludes()).map(ResourcePatternHint::getPattern).containsExactlyInAnyOrderElementsOf(includes);
|
||||||
assertThat(pattern.getIncludes()).map(ResourcePatternHint::getPattern).containsExactlyInAnyOrderElementsOf(includes);
|
|
||||||
assertThat(pattern.getExcludes()).map(ResourcePatternHint::getPattern).containsExactlyElementsOf(excludes);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Nested {
|
static class Nested {
|
||||||
|
|
|
@ -47,11 +47,9 @@ class RuntimeHintsTests {
|
||||||
@Test
|
@Test
|
||||||
void resourceHintWithClass() {
|
void resourceHintWithClass() {
|
||||||
this.hints.resources().registerType(String.class);
|
this.hints.resources().registerType(String.class);
|
||||||
assertThat(this.hints.resources().resourcePatternHints()).singleElement().satisfies(resourceHint -> {
|
assertThat(this.hints.resources().resourcePatternHints()).singleElement().satisfies(resourceHint ->
|
||||||
assertThat(resourceHint.getIncludes()).map(ResourcePatternHint::getPattern)
|
assertThat(resourceHint.getIncludes()).map(ResourcePatternHint::getPattern)
|
||||||
.containsExactlyInAnyOrder("/", "java", "java/lang", "java/lang/String.class");
|
.containsExactlyInAnyOrder("/", "java", "java/lang", "java/lang/String.class"));
|
||||||
assertThat(resourceHint.getExcludes()).isEmpty();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("removal")
|
||||||
class TypeHintTests {
|
class TypeHintTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -169,9 +170,8 @@ class TypeHintTests {
|
||||||
void builtWithAppliesMemberCategories() {
|
void builtWithAppliesMemberCategories() {
|
||||||
TypeHint.Builder builder = new TypeHint.Builder(TypeReference.of(String.class));
|
TypeHint.Builder builder = new TypeHint.Builder(TypeReference.of(String.class));
|
||||||
assertThat(builder.build().getMemberCategories()).isEmpty();
|
assertThat(builder.build().getMemberCategories()).isEmpty();
|
||||||
TypeHint.builtWith(MemberCategory.DECLARED_CLASSES, MemberCategory.DECLARED_FIELDS).accept(builder);
|
TypeHint.builtWith(MemberCategory.DECLARED_FIELDS).accept(builder);
|
||||||
assertThat(builder.build().getMemberCategories()).containsExactlyInAnyOrder(MemberCategory.DECLARED_CLASSES,
|
assertThat(builder.build().getMemberCategories()).containsExactly(MemberCategory.DECLARED_FIELDS);
|
||||||
MemberCategory.DECLARED_FIELDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2023 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -40,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
*
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("removal")
|
||||||
class ReflectionHintsPredicatesTests {
|
class ReflectionHintsPredicatesTests {
|
||||||
|
|
||||||
private static Constructor<?> privateConstructor;
|
private static Constructor<?> privateConstructor;
|
||||||
|
@ -160,6 +161,12 @@ class ReflectionHintsPredicatesTests {
|
||||||
assertPredicateDoesNotMatch(reflection.onConstructor(publicConstructor).introspect());
|
assertPredicateDoesNotMatch(reflection.onConstructor(publicConstructor).introspect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructorIntrospectionMatchesTypeHint() {
|
||||||
|
runtimeHints.reflection().registerType(SampleClass.class);
|
||||||
|
assertPredicateMatches(reflection.onConstructor(publicConstructor).introspect());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void constructorIntrospectionMatchesConstructorHint() {
|
void constructorIntrospectionMatchesConstructorHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||||
|
@ -230,22 +237,16 @@ class ReflectionHintsPredicatesTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void privateConstructorIntrospectionMatchesConstructorHint() {
|
void privateConstructorIntrospectionMatchesTypeHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
runtimeHints.reflection().registerType(SampleClass.class);
|
||||||
typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT));
|
|
||||||
assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect());
|
assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void privateConstructorIntrospectionDoesNotMatchIntrospectPublicConstructors() {
|
void privateConstructorIntrospectionMatchesConstructorHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS);
|
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||||
assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).introspect());
|
typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT));
|
||||||
}
|
assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect());
|
||||||
|
|
||||||
@Test
|
|
||||||
void privateConstructorIntrospectionDoesNotMatchInvokePublicConstructors() {
|
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);
|
|
||||||
assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).introspect());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -303,6 +304,12 @@ class ReflectionHintsPredicatesTests {
|
||||||
@Nested
|
@Nested
|
||||||
class ReflectionOnMethod {
|
class ReflectionOnMethod {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void methodIntrospectionMatchesTypeHint() {
|
||||||
|
runtimeHints.reflection().registerType(SampleClass.class);
|
||||||
|
assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").introspect());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void methodIntrospectionMatchesMethodHint() {
|
void methodIntrospectionMatchesMethodHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||||
|
@ -328,18 +335,6 @@ class ReflectionHintsPredicatesTests {
|
||||||
assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").introspect());
|
assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").introspect());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void methodIntrospectionDoesNotMatchIntrospectDeclaredMethods() {
|
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_DECLARED_METHODS);
|
|
||||||
assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "publicMethod").introspect());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void methodIntrospectionDoesNotMatchInvokeDeclaredMethods() {
|
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_DECLARED_METHODS);
|
|
||||||
assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "publicMethod").introspect());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void methodInvocationDoesNotMatchMethodHint() {
|
void methodInvocationDoesNotMatchMethodHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||||
|
@ -379,22 +374,16 @@ class ReflectionHintsPredicatesTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void privateMethodIntrospectionMatchesMethodHint() {
|
void privateMethodIntrospectionMatchesTypeHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
runtimeHints.reflection().registerType(SampleClass.class);
|
||||||
typeHint.withMethod("privateMethod", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
|
||||||
assertPredicateMatches(reflection.onMethod(SampleClass.class, "privateMethod").introspect());
|
assertPredicateMatches(reflection.onMethod(SampleClass.class, "privateMethod").introspect());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void privateMethodIntrospectionDoesNotMatchIntrospectPublicMethods() {
|
void privateMethodIntrospectionMatchesMethodHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
|
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||||
assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "privateMethod").introspect());
|
typeHint.withMethod("privateMethod", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||||
}
|
assertPredicateMatches(reflection.onMethod(SampleClass.class, "privateMethod").introspect());
|
||||||
|
|
||||||
@Test
|
|
||||||
void privateMethodIntrospectionDoesNotMatchInvokePublicMethods() {
|
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_PUBLIC_METHODS);
|
|
||||||
assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "privateMethod").introspect());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -464,15 +453,15 @@ class ReflectionHintsPredicatesTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void fieldReflectionMatchesFieldHint() {
|
void fieldReflectionMatchesTypeHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withField("publicField"));
|
runtimeHints.reflection().registerType(SampleClass.class);
|
||||||
assertPredicateMatches(reflection.onField(SampleClass.class, "publicField"));
|
assertPredicateMatches(reflection.onField(SampleClass.class, "publicField"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void fieldReflectionDoesNotMatchNonRegisteredFielddHint() {
|
void fieldReflectionMatchesFieldHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withField("publicField"));
|
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withField("publicField"));
|
||||||
assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "privateField"));
|
assertPredicateMatches(reflection.onField(SampleClass.class, "publicField"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -482,9 +471,21 @@ class ReflectionHintsPredicatesTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void fieldReflectionDoesNotMatchDeclaredFieldsHint() {
|
void fieldInvocationMatchesPublicFieldsHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.DECLARED_FIELDS);
|
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_PUBLIC_FIELDS);
|
||||||
assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "publicField"));
|
assertPredicateMatches(reflection.onField(SampleClass.class, "publicField").invocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void fieldInvocationDoesNotMatchTypeHint() {
|
||||||
|
runtimeHints.reflection().registerType(SampleClass.class);
|
||||||
|
assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "publicField").invocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void privateFieldReflectionMatchesTypeHint() {
|
||||||
|
runtimeHints.reflection().registerType(SampleClass.class);
|
||||||
|
assertPredicateMatches(reflection.onField(SampleClass.class, "privateField"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -493,18 +494,24 @@ class ReflectionHintsPredicatesTests {
|
||||||
assertPredicateMatches(reflection.onField(SampleClass.class, "privateField"));
|
assertPredicateMatches(reflection.onField(SampleClass.class, "privateField"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void privateFieldReflectionDoesNotMatchPublicFieldsHint() {
|
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.PUBLIC_FIELDS);
|
|
||||||
assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "privateField"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void privateFieldReflectionMatchesDeclaredFieldsHint() {
|
void privateFieldReflectionMatchesDeclaredFieldsHint() {
|
||||||
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.DECLARED_FIELDS);
|
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.DECLARED_FIELDS);
|
||||||
assertPredicateMatches(reflection.onField(SampleClass.class, "privateField"));
|
assertPredicateMatches(reflection.onField(SampleClass.class, "privateField"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void privateFieldInvocationMatchesDeclaredFieldsHint() {
|
||||||
|
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_DECLARED_FIELDS);
|
||||||
|
assertPredicateMatches(reflection.onField(SampleClass.class, "privateField").invocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void privateFieldInvocationDoesNotMatchTypeHint() {
|
||||||
|
runtimeHints.reflection().registerType(SampleClass.class);
|
||||||
|
assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "privateField").invocation());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertPredicateMatches(Predicate<RuntimeHints> predicate) {
|
private void assertPredicateMatches(Predicate<RuntimeHints> predicate) {
|
||||||
|
|
|
@ -140,11 +140,8 @@ class FilePatternResourceHintsRegistrarTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Consumer<ResourcePatternHints> includes(String... patterns) {
|
private Consumer<ResourcePatternHints> includes(String... patterns) {
|
||||||
return hint -> {
|
return hint -> assertThat(hint.getIncludes().stream().map(ResourcePatternHint::getPattern))
|
||||||
assertThat(hint.getIncludes().stream().map(ResourcePatternHint::getPattern))
|
.containsExactlyInAnyOrder(patterns);
|
||||||
.containsExactlyInAnyOrder(patterns);
|
|
||||||
assertThat(hint.getExcludes()).isEmpty();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue