diff --git a/spring-core/src/main/java/org/springframework/aot/generate/GeneratedFiles.java b/spring-core/src/main/java/org/springframework/aot/generate/GeneratedFiles.java index bd6ec60ae27c..1c326e4fd96d 100644 --- a/spring-core/src/main/java/org/springframework/aot/generate/GeneratedFiles.java +++ b/spring-core/src/main/java/org/springframework/aot/generate/GeneratedFiles.java @@ -20,6 +20,7 @@ import org.springframework.javapoet.JavaFile; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; import org.springframework.util.function.ThrowingConsumer; /** @@ -43,6 +44,7 @@ public interface GeneratedFiles { * @param javaFile the java file to add */ default void addSourceFile(JavaFile javaFile) { + validatePackage(javaFile.packageName, javaFile.typeSpec.name); String className = javaFile.packageName + "." + javaFile.typeSpec.name; addSourceFile(className, javaFile::writeTo); } @@ -161,11 +163,20 @@ default void addFile(Kind kind, String path, ThrowingConsumer conten private static String getClassNamePath(String className) { Assert.hasLength(className, "'className' must not be empty"); + validatePackage(ClassUtils.getPackageName(className), className); Assert.isTrue(isJavaIdentifier(className), "'className' must be a valid identifier, got '" + className + "'"); return ClassUtils.convertClassNameToResourcePath(className) + ".java"; } + private static void validatePackage(String packageName, String className) { + if (!StringUtils.hasLength(packageName)) { + throw new IllegalArgumentException("Could not add '" + className + "', " + + "processing classes in the default package is not supported. " + + "Did you forget to add a package statement?"); + } + } + private static boolean isJavaIdentifier(String className) { char[] chars = className.toCharArray(); for (int i = 0; i < chars.length; i++) { diff --git a/spring-core/src/test/java/org/springframework/aot/generate/GeneratedFilesTests.java b/spring-core/src/test/java/org/springframework/aot/generate/GeneratedFilesTests.java index 0eeb510490e9..3372fe0c4dae 100644 --- a/spring-core/src/test/java/org/springframework/aot/generate/GeneratedFilesTests.java +++ b/spring-core/src/test/java/org/springframework/aot/generate/GeneratedFilesTests.java @@ -60,6 +60,15 @@ void addSourceFileWithJavaFileAddsFile() throws Exception { .contains("Hello, World!"); } + @Test + void addSourceFileWithJavaFileInTheDefaultPackageThrowsException() { + TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld").build(); + JavaFile javaFile = JavaFile.builder("", helloWorld).build(); + assertThatIllegalArgumentException().isThrownBy(() -> this.generatedFiles.addSourceFile(javaFile)) + .withMessage("Could not add 'HelloWorld', processing classes in the " + + "default package is not supported. Did you forget to add a package statement?"); + } + @Test void addSourceFileWithCharSequenceAddsFile() throws Exception { this.generatedFiles.addSourceFile("com.example.HelloWorld", "{}"); @@ -73,6 +82,14 @@ void addSourceFileWithCharSequenceWhenClassNameIsEmptyThrowsException() { .withMessage("'className' must not be empty"); } + @Test + void addSourceFileWithCharSequenceWhenClassNameIsInTheDefaultPackageThrowsException() { + assertThatIllegalArgumentException() + .isThrownBy(() -> this.generatedFiles.addSourceFile("HelloWorld", "{}")) + .withMessage("Could not add 'HelloWorld', processing classes in the " + + "default package is not supported. Did you forget to add a package statement?"); + } + @Test void addSourceFileWithCharSequenceWhenClassNameIsInvalidThrowsException() { assertThatIllegalArgumentException()