From 1cb5f0072335cc215e3c6ebc9cde325b5b0f24c1 Mon Sep 17 00:00:00 2001 From: SreenathTM Date: Sat, 10 Sep 2022 18:47:13 +0530 Subject: [PATCH 1/2] Adapt FieldHint to recent GraalVM versions 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 --- .../springframework/aot/hint/FieldHint.java | 144 ------------------ .../springframework/aot/hint/TypeHint.java | 36 +---- 2 files changed, 7 insertions(+), 173 deletions(-) delete mode 100644 spring-core/src/main/java/org/springframework/aot/hint/FieldHint.java diff --git a/spring-core/src/main/java/org/springframework/aot/hint/FieldHint.java b/spring-core/src/main/java/org/springframework/aot/hint/FieldHint.java deleted file mode 100644 index 0587700ccbc..00000000000 --- a/spring-core/src/main/java/org/springframework/aot/hint/FieldHint.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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.aot.hint; - -import java.lang.reflect.Field; -import java.util.function.Consumer; - -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * A hint that describes the need for reflection on a {@link Field}. - * - * @author Stephane Nicoll - * @since 6.0 - */ -public final class FieldHint extends MemberHint { - - private final FieldMode mode; - - private final boolean allowUnsafeAccess; - - - private FieldHint(Builder builder) { - super(builder.name); - this.mode = (builder.mode != null ? builder.mode : FieldMode.WRITE); - this.allowUnsafeAccess = builder.allowUnsafeAccess; - } - - /** - * Return whether setting the value of the field should be allowed. - * @return {@code true} to allow {@link Field#set(Object, Object)}. - * @deprecated in favor of {@link #getMode()} - */ - @Deprecated - public boolean isAllowWrite() { - return this.mode == FieldMode.WRITE; - } - - /** - * Return the {@linkplain FieldMode mode} that applies to this hint. - * @return the mode - */ - public FieldMode getMode() { - return this.mode; - } - - /** - * Return whether using {@code Unsafe} on the field should be allowed. - * @return {@code true} to allow unsafe access - */ - public boolean isAllowUnsafeAccess() { - return this.allowUnsafeAccess; - } - - /** - * Return a {@link Consumer} that applies the given {@link FieldMode} - * to the accepted {@link Builder}. - * @param mode the mode to apply - * @return a consumer to apply the mode - */ - public static Consumer builtWith(FieldMode mode) { - return builder -> builder.withMode(mode); - } - - - /** - * Builder for {@link FieldHint}. - */ - public static class Builder { - - private final String name; - - @Nullable - private FieldMode mode; - - private boolean allowUnsafeAccess; - - - Builder(String name) { - this.name = name; - } - - /** - * Specify if setting the value of the field should be allowed. - * @param allowWrite {@code true} to allow {@link Field#set(Object, Object)} - * @return {@code this}, to facilitate method chaining - * @deprecated in favor of {@link #withMode(FieldMode)} - */ - @Deprecated - public Builder allowWrite(boolean allowWrite) { - if (allowWrite) { - return withMode(FieldMode.WRITE); - } - return this; - } - - /** - * Specify that the {@linkplain FieldMode mode} is required. - * @param mode the required mode - * @return {@code this}, to facilitate method chaining - */ - public Builder withMode(FieldMode mode) { - Assert.notNull(mode, "'mode' must not be null"); - if ((this.mode == null || !this.mode.includes(mode))) { - this.mode = mode; - } - return this; - } - - /** - * Specify whether using {@code Unsafe} on the field should be allowed. - * @param allowUnsafeAccess {@code true} to allow unsafe access - * @return {@code this}, to facilitate method chaining - */ - public Builder allowUnsafeAccess(boolean allowUnsafeAccess) { - this.allowUnsafeAccess = allowUnsafeAccess; - return this; - } - - /** - * Create a {@link FieldHint} based on the state of this builder. - * @return a field hint - */ - FieldHint build() { - return new FieldHint(this); - } - - } -} diff --git a/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java b/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java index 95432587add..3de974f2e98 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java @@ -44,7 +44,7 @@ public final class TypeHint implements ConditionalHint { @Nullable private final TypeReference reachableType; - private final Set fields; + private final Set fields; private final Set constructors; @@ -57,7 +57,7 @@ public final class TypeHint implements ConditionalHint { this.type = builder.type; this.reachableType = builder.reachableType; this.memberCategories = Set.copyOf(builder.memberCategories); - this.fields = builder.fields.values().stream().map(FieldHint.Builder::build).collect(Collectors.toSet()); + this.fields = builder.fields; this.constructors = builder.constructors.values().stream().map(ExecutableHint.Builder::build).collect(Collectors.toSet()); this.methods = builder.methods.values().stream().map(ExecutableHint.Builder::build).collect(Collectors.toSet()); } @@ -89,10 +89,10 @@ public final class TypeHint implements ConditionalHint { /** * Return the fields that require reflection. - * @return a stream of {@link FieldHint} + * @return a stream of Strings */ - public Stream fields() { - return this.fields.stream(); + public Set fields() { + return this.fields; } /** @@ -147,7 +147,7 @@ public final class TypeHint implements ConditionalHint { @Nullable private TypeReference reachableType; - private final Map fields = new HashMap<>(); + private final Set fields = new HashSet<>(); private final Map constructors = new HashMap<>(); @@ -191,31 +191,9 @@ public final class TypeHint implements ConditionalHint { * @return {@code this}, to facilitate method chaining */ public Builder withField(String name) { - return withField(name, FieldMode.WRITE); + return withField(name); } - /** - * Register the need for reflection on the field with the specified name - * using the specified {@link FieldMode}. - * @param name the name of the field - * @param mode the requested mode - * @return {@code this}, to facilitate method chaining - */ - public Builder withField(String name, FieldMode mode) { - return withField(name, FieldHint.builtWith(mode)); - } - - /** - * Register the need for reflection on the field with the specified name. - * @param name the name of the field - * @param fieldHint a builder to further customize the hints of this field - * @return {@code this}, to facilitate method chaining - */ - public Builder withField(String name, Consumer fieldHint) { - FieldHint.Builder builder = this.fields.computeIfAbsent(name, FieldHint.Builder::new); - fieldHint.accept(builder); - return this; - } /** * Register the need for reflection on the constructor with the specified From 042a4f3518eae203c63d0db2b69ddc7fd9a61e3b Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Sat, 10 Sep 2022 15:56:26 +0200 Subject: [PATCH 2/2] Polish "Adapt FieldHint to recent GraalVM versions" See gh-29130 --- ...nBeanRegistrationAotContributionTests.java | 4 +- .../aot/agent/InstrumentedMethod.java | 2 +- .../springframework/aot/hint/FieldHint.java} | 19 +++--- .../springframework/aot/hint/FieldMode.java | 51 ---------------- .../aot/hint/ReflectionHints.java | 25 +------- .../springframework/aot/hint/TypeHint.java | 17 +++--- .../predicate/ReflectionHintsPredicates.java | 53 +--------------- .../aot/nativex/ReflectionHintsWriter.java | 7 --- .../aot/hint/FieldModeTests.java | 61 ------------------- .../aot/hint/ReflectionHintsTests.java | 57 +---------------- .../aot/hint/TypeHintTests.java | 57 +---------------- .../ReflectionHintsPredicatesTests.java | 28 +-------- .../FileNativeConfigurationWriterTests.java | 34 +++++------ .../nativex/ReflectionHintsWriterTests.java | 10 +-- .../support/InjectionCodeGeneratorTests.java | 2 +- ...BeanPostProcessorAotContributionTests.java | 10 +-- 16 files changed, 49 insertions(+), 388 deletions(-) rename spring-core/src/{test/java/org/springframework/aot/hint/FieldHintTests.java => main/java/org/springframework/aot/hint/FieldHint.java} (59%) delete mode 100644 spring-core/src/main/java/org/springframework/aot/hint/FieldMode.java delete mode 100644 spring-core/src/test/java/org/springframework/aot/hint/FieldModeTests.java diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanRegistrationAotContributionTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanRegistrationAotContributionTests.java index 219093424e7..5e425d305e1 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanRegistrationAotContributionTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanRegistrationAotContributionTests.java @@ -73,7 +73,7 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests { RegisteredBean registeredBean = getAndApplyContribution( PrivateFieldInjectionSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onField(PrivateFieldInjectionSample.class, "environment").withWriteMode()) + .onField(PrivateFieldInjectionSample.class, "environment")) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PrivateFieldInjectionSample instance = new PrivateFieldInjectionSample(); @@ -92,7 +92,7 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests { RegisteredBean registeredBean = getAndApplyContribution( PackagePrivateFieldInjectionSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onField(PackagePrivateFieldInjectionSample.class, "environment").withWriteMode()) + .onField(PackagePrivateFieldInjectionSample.class, "environment")) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PackagePrivateFieldInjectionSample instance = new PackagePrivateFieldInjectionSample(); diff --git a/spring-core-test/src/main/java/org/springframework/aot/agent/InstrumentedMethod.java b/spring-core-test/src/main/java/org/springframework/aot/agent/InstrumentedMethod.java index f7fc7e8a51d..091cfbef583 100644 --- a/spring-core-test/src/main/java/org/springframework/aot/agent/InstrumentedMethod.java +++ b/spring-core-test/src/main/java/org/springframework/aot/agent/InstrumentedMethod.java @@ -290,7 +290,7 @@ enum InstrumentedMethod { * {@link Field#set(Object, Object)}. */ FIELD_SET(Field.class, "set", HintType.REFLECTION, - invocation -> reflection().onField(invocation.getInstance()).withWriteMode()), + invocation -> reflection().onField(invocation.getInstance())), /* diff --git a/spring-core/src/test/java/org/springframework/aot/hint/FieldHintTests.java b/spring-core/src/main/java/org/springframework/aot/hint/FieldHint.java similarity index 59% rename from spring-core/src/test/java/org/springframework/aot/hint/FieldHintTests.java rename to spring-core/src/main/java/org/springframework/aot/hint/FieldHint.java index 8c89a21e567..e2be3052bbe 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/FieldHintTests.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/FieldHint.java @@ -16,23 +16,18 @@ package org.springframework.aot.hint; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; +import java.lang.reflect.Field; /** - * Tests for {@link FieldHint}. + * A hint that describes the need for reflection on a {@link Field}. * - * @author Phillip Webb + * @author Stephane Nicoll + * @since 6.0 */ -class FieldHintTests { +public final class FieldHint extends MemberHint { - @Test - void builtWithAppliesMode() { - FieldHint.Builder builder = new FieldHint.Builder("test"); - assertThat(builder.build().getMode()).isEqualTo(FieldMode.WRITE); - FieldHint.builtWith(FieldMode.READ).accept(builder); - assertThat(builder.build().getMode()).isEqualTo(FieldMode.READ); + FieldHint(String name) { + super(name); } } diff --git a/spring-core/src/main/java/org/springframework/aot/hint/FieldMode.java b/spring-core/src/main/java/org/springframework/aot/hint/FieldMode.java deleted file mode 100644 index 289e4793142..00000000000 --- a/spring-core/src/main/java/org/springframework/aot/hint/FieldMode.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.aot.hint; - -import java.lang.reflect.Field; - -import org.springframework.lang.Nullable; - -/** - * Represents the need of reflection for a given {@link Field}. - * - * @author Phillip Webb - * @since 6.0 - * @see ReflectionHints - */ -public enum FieldMode { - - /** - * Only field read is required. - */ - READ, - - /** - * Full field read and write is required. - */ - WRITE; - - /** - * Specify if this mode already includes the specified {@code other} mode. - * @param other the other mode to check - * @return {@code true} if this mode includes the other mode - */ - public boolean includes(@Nullable FieldMode other) { - return (other == null || this.ordinal() >= other.ordinal()); - } - -} diff --git a/spring-core/src/main/java/org/springframework/aot/hint/ReflectionHints.java b/spring-core/src/main/java/org/springframework/aot/hint/ReflectionHints.java index a656a74f350..e70e9d94cca 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/ReflectionHints.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/ReflectionHints.java @@ -147,35 +147,14 @@ public class ReflectionHints { return this; } - /** - * Register the need for reflection on the specified {@link Field}, - * enabling {@link FieldMode#WRITE}. - * @param field the field that requires reflection - * @return {@code this}, to facilitate method chaining - */ - public ReflectionHints registerField(Field field) { - return registerField(field, FieldMode.WRITE); - } - - /** - * Register the need for reflection on the specified {@link Field} - * using the specified {@link FieldMode}. - * @param field the field that requires reflection - * @return {@code this}, to facilitate method chaining - */ - public ReflectionHints registerField(Field field, FieldMode mode) { - return registerField(field, FieldHint.builtWith(mode)); - } - /** * Register the need for reflection on the specified {@link Field}. * @param field the field that requires reflection - * @param fieldHint a builder to further customize the hints of this field * @return {@code this}, to facilitate method chaining */ - public ReflectionHints registerField(Field field, Consumer fieldHint) { + public ReflectionHints registerField(Field field) { return registerType(TypeReference.of(field.getDeclaringClass()), - typeHint -> typeHint.withField(field.getName(), fieldHint)); + typeHint -> typeHint.withField(field.getName())); } /** diff --git a/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java b/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java index 3de974f2e98..f660ad3a3c5 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java @@ -44,7 +44,7 @@ public final class TypeHint implements ConditionalHint { @Nullable private final TypeReference reachableType; - private final Set fields; + private final Set fields; private final Set constructors; @@ -57,7 +57,7 @@ public final class TypeHint implements ConditionalHint { this.type = builder.type; this.reachableType = builder.reachableType; this.memberCategories = Set.copyOf(builder.memberCategories); - this.fields = builder.fields; + this.fields = builder.fields.stream().map(FieldHint::new).collect(Collectors.toSet()); this.constructors = builder.constructors.values().stream().map(ExecutableHint.Builder::build).collect(Collectors.toSet()); this.methods = builder.methods.values().stream().map(ExecutableHint.Builder::build).collect(Collectors.toSet()); } @@ -89,10 +89,10 @@ public final class TypeHint implements ConditionalHint { /** * Return the fields that require reflection. - * @return a stream of Strings + * @return a stream of {@link FieldHint} */ - public Set fields() { - return this.fields; + public Stream fields() { + return this.fields.stream(); } /** @@ -185,16 +185,15 @@ public final class TypeHint implements ConditionalHint { } /** - * Register the need for reflection on the field with the specified name, - * enabling write access. + * Register the need for reflection on the field with the specified name. * @param name the name of the field * @return {@code this}, to facilitate method chaining */ public Builder withField(String name) { - return withField(name); + this.fields.add(name); + return this; } - /** * Register the need for reflection on the constructor with the specified * parameter types, enabling {@link ExecutableMode#INVOKE}. diff --git a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java index c745cff465d..45110dccae6 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java @@ -28,8 +28,6 @@ import java.util.function.Predicate; import org.springframework.aot.hint.ExecutableHint; import org.springframework.aot.hint.ExecutableMode; -import org.springframework.aot.hint.FieldHint; -import org.springframework.aot.hint.FieldMode; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.ReflectionHints; import org.springframework.aot.hint.RuntimeHints; @@ -375,57 +373,10 @@ public class ReflectionHintsPredicates { private final Field field; - private FieldMode mode = FieldMode.READ; - - private boolean allowUnsafeAccess; - FieldHintPredicate(Field field) { this.field = field; } - /** - * Refine the current predicate to match if write access is allowed on the field. - * @return the refined {@link RuntimeHints} predicate - * @see FieldHint#isAllowWrite() - * @deprecated in favor of {@link #withReadMode()} or {@link #withWriteMode()} - */ - @Deprecated - public FieldHintPredicate allowWrite() { - this.mode = FieldMode.WRITE; - return this; - } - - /** - * Refine the current predicate to match if read access is allowed on the field. - * @return the refined {@link RuntimeHints} predicate - * @see FieldHint#getMode() - */ - public FieldHintPredicate withReadMode() { - // FieldMode.READ is already the default and should not override a writeMode() call. - return this; - } - - /** - * Refine the current predicate to match if write access is allowed on the field. - * @return the refined {@link RuntimeHints} predicate - * @see FieldHint#getMode() - */ - public FieldHintPredicate withWriteMode() { - this.mode = FieldMode.WRITE; - return this; - } - - - /** - * Refine the current predicate to match if unsafe access is allowed on the field. - * @return the refined {@link RuntimeHints} predicate - * @see FieldHint#isAllowUnsafeAccess() () - */ - public FieldHintPredicate allowUnsafeAccess() { - this.allowUnsafeAccess = true; - return this; - } - @Override public boolean test(RuntimeHints runtimeHints) { TypeHint typeHint = runtimeHints.reflection().getTypeHint(this.field.getDeclaringClass()); @@ -447,9 +398,7 @@ public class ReflectionHintsPredicates { private boolean exactMatch(TypeHint typeHint) { return typeHint.fields().anyMatch(fieldHint -> - this.field.getName().equals(fieldHint.getName()) - && (fieldHint.getMode().includes(this.mode)) - && (!this.allowUnsafeAccess || this.allowUnsafeAccess == fieldHint.isAllowUnsafeAccess())); + this.field.getName().equals(fieldHint.getName())); } } diff --git a/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsWriter.java b/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsWriter.java index 3e2f220f0a8..8a2b3603b05 100644 --- a/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsWriter.java +++ b/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsWriter.java @@ -26,7 +26,6 @@ import java.util.stream.Stream; import org.springframework.aot.hint.ExecutableHint; import org.springframework.aot.hint.ExecutableMode; import org.springframework.aot.hint.FieldHint; -import org.springframework.aot.hint.FieldMode; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.ReflectionHints; import org.springframework.aot.hint.TypeHint; @@ -78,12 +77,6 @@ class ReflectionHintsWriter { private Map toAttributes(FieldHint hint) { Map attributes = new LinkedHashMap<>(); attributes.put("name", hint.getName()); - if (hint.getMode() == FieldMode.WRITE) { - attributes.put("allowWrite", true); - } - if (hint.isAllowUnsafeAccess()) { - attributes.put("allowUnsafeAccess", hint.isAllowUnsafeAccess()); - } return attributes; } diff --git a/spring-core/src/test/java/org/springframework/aot/hint/FieldModeTests.java b/spring-core/src/test/java/org/springframework/aot/hint/FieldModeTests.java deleted file mode 100644 index bb6ecf6f042..00000000000 --- a/spring-core/src/test/java/org/springframework/aot/hint/FieldModeTests.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.aot.hint; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link FieldMode}. - * - * @author Phillip Webb - * @since 6.0 - */ -class FieldModeTests { - - @Test - void writeIncludesNullMode() { - assertThat(FieldMode.WRITE.includes(null)).isTrue(); - } - - @Test - void writeIncludesRead() { - assertThat(FieldMode.WRITE.includes(FieldMode.READ)).isTrue(); - } - - @Test - void writeIncludesWrite() { - assertThat(FieldMode.WRITE.includes(FieldMode.WRITE)).isTrue(); - } - - @Test - void readIncludesNullMode() { - assertThat(FieldMode.READ.includes(null)).isTrue(); - } - - @Test - void readIncludesRead() { - assertThat(FieldMode.READ.includes(FieldMode.READ)).isTrue(); - } - - @Test - void readDoesNotIncludeWrite() { - assertThat(FieldMode.READ.includes(FieldMode.WRITE)).isFalse(); - } - -} diff --git a/spring-core/src/test/java/org/springframework/aot/hint/ReflectionHintsTests.java b/spring-core/src/test/java/org/springframework/aot/hint/ReflectionHintsTests.java index a7213d999ad..b585609a06d 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/ReflectionHintsTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/ReflectionHintsTests.java @@ -124,63 +124,12 @@ class ReflectionHintsTests { } @Test - void registerFieldAllowsWriteByDefault() { + void registerField() { Field field = ReflectionUtils.findField(TestType.class, "field"); assertThat(field).isNotNull(); this.reflectionHints.registerField(field); - assertTestTypeFieldHint(fieldHint -> { - assertThat(fieldHint.getName()).isEqualTo("field"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.WRITE); - assertThat(fieldHint.isAllowUnsafeAccess()).isFalse(); - }); - } - - @Test - void registerFieldWithEmptyCustomizerAppliesConsistentDefault() { - Field field = ReflectionUtils.findField(TestType.class, "field"); - assertThat(field).isNotNull(); - this.reflectionHints.registerField(field, fieldHint -> {}); - assertTestTypeFieldHint(fieldHint -> { - assertThat(fieldHint.getName()).isEqualTo("field"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.WRITE); - assertThat(fieldHint.isAllowUnsafeAccess()).isFalse(); - }); - } - - @Test - void registerFieldWithCustomizerAppliesCustomization() { - Field field = ReflectionUtils.findField(TestType.class, "field"); - assertThat(field).isNotNull(); - this.reflectionHints.registerField(field, fieldHint -> - fieldHint.withMode(FieldMode.READ).allowUnsafeAccess(true)); - assertTestTypeFieldHint(fieldHint -> { - assertThat(fieldHint.getName()).isEqualTo("field"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.READ); - assertThat(fieldHint.isAllowUnsafeAccess()).isTrue(); - }); - } - - @Test - void registerFieldWithMode() { - Field field = ReflectionUtils.findField(TestType.class, "field"); - assertThat(field).isNotNull(); - this.reflectionHints.registerField(field, FieldMode.READ); - assertTestTypeFieldHint(fieldHint -> { - assertThat(fieldHint.getName()).isEqualTo("field"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.READ); - }); - } - - @Test // gh-29055 - void registerFieldWithCustomizersCannotDowngradeWrite() { - Field field = ReflectionUtils.findField(TestType.class, "field"); - assertThat(field).isNotNull(); - this.reflectionHints.registerField(field, FieldMode.WRITE); - this.reflectionHints.registerField(field, FieldMode.READ); - assertTestTypeFieldHint(fieldHint -> { - assertThat(fieldHint.getName()).isEqualTo("field"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.WRITE); - }); + assertTestTypeFieldHint(fieldHint -> + assertThat(fieldHint.getName()).isEqualTo("field")); } private void assertTestTypeFieldHint(Consumer fieldHint) { diff --git a/spring-core/src/test/java/org/springframework/aot/hint/TypeHintTests.java b/spring-core/src/test/java/org/springframework/aot/hint/TypeHintTests.java index aef5bebf9bc..c0f57435623 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/TypeHintTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/TypeHintTests.java @@ -55,62 +55,9 @@ class TypeHintTests { } @Test - void createWithFieldAllowsWriteByDefault() { + void createWithField() { assertFieldHint(TypeHint.of(TypeReference.of(String.class)) - .withField("value"), fieldHint -> { - assertThat(fieldHint.getName()).isEqualTo("value"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.WRITE); - assertThat(fieldHint.isAllowUnsafeAccess()).isFalse(); - }); - } - - @Test - void createWithFieldAndEmptyCustomizerAppliesConsistentDefault() { - assertFieldHint(TypeHint.of(TypeReference.of(String.class)) - .withField("value", fieldHint -> {}), fieldHint -> { - assertThat(fieldHint.getName()).isEqualTo("value"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.WRITE); - assertThat(fieldHint.isAllowUnsafeAccess()).isFalse(); - }); - } - - @Test - void createWithFieldAndCustomizerAppliesCustomization() { - assertFieldHint(TypeHint.of(TypeReference.of(String.class)) - .withField("value", fieldHint -> { - fieldHint.withMode(FieldMode.READ); - fieldHint.allowUnsafeAccess(true); - }), fieldHint -> { - assertThat(fieldHint.getName()).isEqualTo("value"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.READ); - assertThat(fieldHint.isAllowUnsafeAccess()).isTrue(); - }); - } - - @Test - void createWithFieldReuseBuilder() { - Builder builder = TypeHint.of(TypeReference.of(String.class)); - builder.withField("value", fieldHint -> fieldHint.allowUnsafeAccess(true)); - builder.withField("value", fieldHint -> { - fieldHint.withMode(FieldMode.WRITE); - fieldHint.allowUnsafeAccess(false); - }); - assertFieldHint(builder, fieldHint -> { - assertThat(fieldHint.getName()).isEqualTo("value"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.WRITE); - assertThat(fieldHint.isAllowUnsafeAccess()).isFalse(); - }); - } - - @Test - void createFieldWithFieldMode() { - Builder builder = TypeHint.of(TypeReference.of(String.class)); - builder.withField("value", FieldMode.READ); - assertFieldHint(builder, fieldHint -> { - assertThat(fieldHint.getName()).isEqualTo("value"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.READ); - assertThat(fieldHint.isAllowUnsafeAccess()).isFalse(); - }); + .withField("value"), fieldHint -> assertThat(fieldHint.getName()).isEqualTo("value")); } void assertFieldHint(Builder builder, Consumer fieldHint) { diff --git a/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java b/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java index 6275105e44e..ade56f2d0d5 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java @@ -27,7 +27,6 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.aot.hint.ExecutableMode; -import org.springframework.aot.hint.FieldMode; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeReference; @@ -261,7 +260,7 @@ class ReflectionHintsPredicatesTests { @Test void privateConstructorInvocationDoesNotMatchConstructorHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> - typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT)); + typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT)); assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).invoke()); } @@ -480,30 +479,9 @@ class ReflectionHintsPredicatesTests { } @Test - void fieldWriteReflectionDoesNotMatchFieldHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withField("publicField", - FieldMode.READ)); - assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "publicField").withWriteMode()); - } - - @Test - void fieldUnsafeReflectionDoesNotMatchFieldHint() { + void fieldReflectionDoesNotMatchNonRegisteredFielddHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withField("publicField")); - assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "publicField").allowUnsafeAccess()); - } - - @Test - void fieldWriteReflectionMatchesFieldHintWithWrite() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> - typeHint.withField("publicField", FieldMode.WRITE)); - assertPredicateMatches(reflection.onField(SampleClass.class, "publicField").withWriteMode()); - } - - @Test - void fieldUnsafeReflectionMatchesFieldHintWithUnsafe() { - runtimeHints.reflection().registerType(SampleClass.class, - typeHint -> typeHint.withField("publicField", fieldHint -> fieldHint.allowUnsafeAccess(true))); - assertPredicateMatches(reflection.onField(SampleClass.class, "publicField").allowUnsafeAccess()); + assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "privateField")); } @Test diff --git a/spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java b/spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java index 6f297cb3f82..2668180fa88 100644 --- a/spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java +++ b/spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java @@ -32,7 +32,6 @@ import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONCompareMode; import org.springframework.aot.hint.ExecutableMode; -import org.springframework.aot.hint.FieldMode; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.ProxyHints; import org.springframework.aot.hint.ReflectionHints; @@ -99,24 +98,19 @@ public class FileNativeConfigurationWriterTests { FileNativeConfigurationWriter generator = new FileNativeConfigurationWriter(tempDir); RuntimeHints hints = new RuntimeHints(); ReflectionHints reflectionHints = hints.reflection(); - reflectionHints.registerType(StringDecoder.class, builder -> { - builder - .onReachableType(String.class) - .withMembers(MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, - MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS, - MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, - MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS, - MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES) - .withField("DEFAULT_CHARSET", fieldBuilder -> fieldBuilder.withMode(FieldMode.READ)) - .withField("defaultCharset", fieldBuilder -> { - fieldBuilder.withMode(FieldMode.WRITE); - fieldBuilder.allowUnsafeAccess(true); - }) - .withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), ExecutableMode.INTROSPECT) - .withMethod("setDefaultCharset", TypeReference.listOf(Charset.class)) - .withMethod("getDefaultCharset", Collections.emptyList(), ExecutableMode.INTROSPECT); - }); + reflectionHints.registerType(StringDecoder.class, builder -> builder + .onReachableType(String.class) + .withMembers(MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS, + MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, + MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS, + MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES) + .withField("DEFAULT_CHARSET") + .withField("defaultCharset") + .withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), ExecutableMode.INTROSPECT) + .withMethod("setDefaultCharset", TypeReference.listOf(Charset.class)) + .withMethod("getDefaultCharset", Collections.emptyList(), ExecutableMode.INTROSPECT)); generator.write(hints); assertEquals(""" [ @@ -137,7 +131,7 @@ public class FileNativeConfigurationWriterTests { "allDeclaredClasses": true, "fields": [ { "name": "DEFAULT_CHARSET" }, - { "name": "defaultCharset", "allowWrite": true, "allowUnsafeAccess": true } + { "name": "defaultCharset" } ], "methods": [ { "name": "setDefaultCharset", "parameterTypes": [ "java.nio.charset.Charset" ] } diff --git a/spring-core/src/test/java/org/springframework/aot/nativex/ReflectionHintsWriterTests.java b/spring-core/src/test/java/org/springframework/aot/nativex/ReflectionHintsWriterTests.java index bcdb73b08b1..0aa8bce1332 100644 --- a/spring-core/src/test/java/org/springframework/aot/nativex/ReflectionHintsWriterTests.java +++ b/spring-core/src/test/java/org/springframework/aot/nativex/ReflectionHintsWriterTests.java @@ -27,7 +27,6 @@ import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONCompareMode; import org.springframework.aot.hint.ExecutableMode; -import org.springframework.aot.hint.FieldMode; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.ReflectionHints; import org.springframework.aot.hint.TypeReference; @@ -58,11 +57,8 @@ public class ReflectionHintsWriterTests { MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES) - .withField("DEFAULT_CHARSET", fieldBuilder -> fieldBuilder.withMode(FieldMode.READ)) - .withField("defaultCharset", fieldBuilder -> { - fieldBuilder.withMode(FieldMode.WRITE); - fieldBuilder.allowUnsafeAccess(true); - }) + .withField("DEFAULT_CHARSET") + .withField("defaultCharset") .withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), ExecutableMode.INTROSPECT) .withMethod("setDefaultCharset", List.of(TypeReference.of(Charset.class))) .withMethod("getDefaultCharset", Collections.emptyList(), ExecutableMode.INTROSPECT)); @@ -85,7 +81,7 @@ public class ReflectionHintsWriterTests { "allDeclaredClasses": true, "fields": [ { "name": "DEFAULT_CHARSET" }, - { "name": "defaultCharset", "allowWrite": true, "allowUnsafeAccess": true } + { "name": "defaultCharset" } ], "methods": [ { "name": "setDefaultCharset", "parameterTypes": [ "java.nio.charset.Charset" ] } diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/support/InjectionCodeGeneratorTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/support/InjectionCodeGeneratorTests.java index 90fe9bdeb3c..f71007d7244 100644 --- a/spring-orm/src/test/java/org/springframework/orm/jpa/support/InjectionCodeGeneratorTests.java +++ b/spring-orm/src/test/java/org/springframework/orm/jpa/support/InjectionCodeGeneratorTests.java @@ -87,7 +87,7 @@ class InjectionCodeGeneratorTests { TestBean bean = new TestBean(); Field field = ReflectionUtils.findField(bean.getClass(), "age"); this.generator.generateInjectionCode(field, INSTANCE_VARIABLE, CodeBlock.of("$L", 123)); - assertThat(RuntimeHintsPredicates.reflection().onField(TestBean.class, "age").withWriteMode()) + assertThat(RuntimeHintsPredicates.reflection().onField(TestBean.class, "age")) .accepts(this.hints); } diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessorAotContributionTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessorAotContributionTests.java index 7ce1e532c68..e68dde6a018 100644 --- a/spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessorAotContributionTests.java +++ b/spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessorAotContributionTests.java @@ -32,7 +32,6 @@ import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.aot.hint.FieldMode; import org.springframework.aot.hint.TypeReference; import org.springframework.aot.test.generate.TestGenerationContext; import org.springframework.aot.test.generate.compile.CompileWithTargetClassAccess; @@ -129,13 +128,8 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests { .singleElement().satisfies(typeHint -> { assertThat(typeHint.getType()).isEqualTo( TypeReference.of(DefaultPersistenceContextField.class)); - assertThat(typeHint.fields()).singleElement() - .satisfies(fieldHint -> { - assertThat(fieldHint.getName()) - .isEqualTo("entityManager"); - assertThat(fieldHint.getMode()).isEqualTo(FieldMode.WRITE); - assertThat(fieldHint.isAllowUnsafeAccess()).isFalse(); - }); + assertThat(typeHint.fields()).singleElement().satisfies(fieldHint -> + assertThat(fieldHint.getName()).isEqualTo("entityManager")); }); }); }