From ead80ce2f536ed9f37d3241fc6be3260a85f97e1 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 7 May 2025 22:53:47 -0700 Subject: [PATCH] Return null for getSuperClassName() with package-info classes Update `ClassFileClassMetadata` to align the behavior of `getSuperClassName()` with other readers in that it returns `null` for `package-info` classes. See gh-34869 --- .../classreading/ClassFileClassMetadata.java | 2 +- .../type/AbstractAnnotationMetadataTests.java | 6 +++ .../DefaultAnnotationMetadataTests.java | 42 +++++++++++++++++++ .../SimpleAnnotationMetadataTests.java | 8 ++-- 4 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 spring-core/src/test/java/org/springframework/core/type/classreading/DefaultAnnotationMetadataTests.java diff --git a/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileClassMetadata.java b/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileClassMetadata.java index 17d274a82f..39908947c6 100644 --- a/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileClassMetadata.java +++ b/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileClassMetadata.java @@ -72,7 +72,7 @@ class ClassFileClassMetadata implements AnnotationMetadata { this.className = className; this.accessFlags = accessFlags; this.enclosingClassName = enclosingClassName; - this.superClassName = superClassName; + this.superClassName = (!className.endsWith(".package-info")) ? superClassName : null; this.independentInnerClass = independentInnerClass; this.interfaceNames = interfaceNames; this.memberClassNames = memberClassNames; diff --git a/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java b/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java index c1e2d7a78e..eb6edc94aa 100644 --- a/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java +++ b/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java @@ -161,6 +161,12 @@ public abstract class AbstractAnnotationMetadataTests { assertThat(get(TestSubInterface.class).getSuperClassName()).isIn(null, "java.lang.Object"); } + @Test + void getSuperClassNameWhenPackageInfoReturnsNull() throws Exception { + Class packageClass = Class.forName(getClass().getPackageName() + ".package-info"); + assertThat(get(packageClass).getSuperClassName()).isNull(); + } + @Test void getInterfaceNamesWhenHasInterfacesReturnsNames() { assertThat(get(TestSubclass.class).getInterfaceNames()).containsExactly(TestInterface.class.getName()); diff --git a/spring-core/src/test/java/org/springframework/core/type/classreading/DefaultAnnotationMetadataTests.java b/spring-core/src/test/java/org/springframework/core/type/classreading/DefaultAnnotationMetadataTests.java new file mode 100644 index 0000000000..1a2b01ed9b --- /dev/null +++ b/spring-core/src/test/java/org/springframework/core/type/classreading/DefaultAnnotationMetadataTests.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2025 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.core.type.classreading; + +import org.springframework.core.type.AbstractAnnotationMetadataTests; +import org.springframework.core.type.AnnotationMetadata; + +/** + * Tests for {@link SimpleAnnotationMetadata} and + * {@link SimpleAnnotationMetadataReadingVisitor} on Java < 24, + * and for the ClassFile API variant on Java >= 24. + * + * @author Phillip Webb + */ +class DefaultAnnotationMetadataTests extends AbstractAnnotationMetadataTests { + + @Override + protected AnnotationMetadata get(Class source) { + try { + return MetadataReaderFactory.create(source.getClassLoader()) + .getMetadataReader(source.getName()).getAnnotationMetadata(); + } + catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + +} diff --git a/spring-core/src/test/java/org/springframework/core/type/classreading/SimpleAnnotationMetadataTests.java b/spring-core/src/test/java/org/springframework/core/type/classreading/SimpleAnnotationMetadataTests.java index 27b53e3de4..43e9fc8481 100644 --- a/spring-core/src/test/java/org/springframework/core/type/classreading/SimpleAnnotationMetadataTests.java +++ b/spring-core/src/test/java/org/springframework/core/type/classreading/SimpleAnnotationMetadataTests.java @@ -21,8 +21,7 @@ import org.springframework.core.type.AnnotationMetadata; /** * Tests for {@link SimpleAnnotationMetadata} and - * {@link SimpleAnnotationMetadataReadingVisitor} on Java < 24, - * and for the ClassFile API variant on Java >= 24. + * {@link SimpleAnnotationMetadataReadingVisitor}. * * @author Phillip Webb */ @@ -31,8 +30,9 @@ class SimpleAnnotationMetadataTests extends AbstractAnnotationMetadataTests { @Override protected AnnotationMetadata get(Class source) { try { - return MetadataReaderFactory.create(source.getClassLoader()) - .getMetadataReader(source.getName()).getAnnotationMetadata(); + return new SimpleMetadataReaderFactory( + source.getClassLoader()).getMetadataReader( + source.getName()).getAnnotationMetadata(); } catch (Exception ex) { throw new IllegalStateException(ex);