Skip to content

Commit c3fca0a

Browse files
committed
Always register root directory for registered resource hints
See gh-29403
1 parent ca33752 commit c3fca0a

File tree

7 files changed

+39
-27
lines changed

7 files changed

+39
-27
lines changed

spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorAotContributionTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ void applyToWhenHasImportAwareConfigurationRegistersHints() {
150150
.satisfies(resourceHint -> assertThat(resourceHint.getIncludes())
151151
.map(ResourcePatternHint::getPattern)
152152
.containsExactlyInAnyOrder(
153+
"/",
153154
"org",
154155
"org/springframework",
155156
"org/springframework/context",

spring-core/src/main/java/org/springframework/aot/hint/ResourcePatternHints.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,20 +98,15 @@ public Builder includes(@Nullable TypeReference reachableType, String... include
9898
* @see <a href="https://github.com/spring-projects/spring-framework/issues/29403">gh-29403</a>
9999
*/
100100
private List<String> expandToIncludeDirectories(String includePattern) {
101-
// Root resource or no explicit subdirectories?
101+
// Resource in root or no explicit subdirectories?
102102
if (!includePattern.contains("/")) {
103-
if (includePattern.contains("*")) {
104-
// If it's a root pattern, include the root directory as well as the pattern
105-
return List.of("/", includePattern);
106-
}
107-
else {
108-
// Include only the root resource
109-
return List.of(includePattern);
110-
}
103+
// Include the root directory as well as the pattern
104+
return List.of("/", includePattern);
111105
}
112106

113107
List<String> includePatterns = new ArrayList<>();
114-
// Ensure the original pattern is always included
108+
// Ensure the root directory and original pattern are always included
109+
includePatterns.add("/");
115110
includePatterns.add(includePattern);
116111
StringBuilder path = new StringBuilder();
117112
for (String pathElement : includePattern.split("/")) {

spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,22 @@ class ResourceHintsTests {
4646
void registerType() {
4747
this.resourceHints.registerType(String.class);
4848
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(
49-
patternOf("java", "java/lang", "java/lang/String.class"));
49+
patternOf("/", "java", "java/lang", "java/lang/String.class"));
5050
}
5151

5252
@Test
5353
void registerTypeWithNestedType() {
5454
this.resourceHints.registerType(TypeReference.of(Nested.class));
5555
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(
56-
patternOf("org", "org/springframework", "org/springframework/aot", "org/springframework/aot/hint",
56+
patternOf("/", "org", "org/springframework", "org/springframework/aot", "org/springframework/aot/hint",
5757
"org/springframework/aot/hint/ResourceHintsTests$Nested.class"));
5858
}
5959

6060
@Test
6161
void registerTypeWithInnerNestedType() {
6262
this.resourceHints.registerType(TypeReference.of(Inner.class));
6363
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(
64-
patternOf("org", "org/springframework", "org/springframework/aot", "org/springframework/aot/hint",
64+
patternOf("/", "org", "org/springframework", "org/springframework/aot", "org/springframework/aot/hint",
6565
"org/springframework/aot/hint/ResourceHintsTests$Nested$Inner.class"));
6666
}
6767

@@ -70,16 +70,26 @@ void registerTypeSeveralTimesAddsOnlyOneEntry() {
7070
this.resourceHints.registerType(String.class);
7171
this.resourceHints.registerType(TypeReference.of(String.class));
7272
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(
73-
patternOf("java", "java/lang", "java/lang/String.class"));
73+
patternOf("/", "java", "java/lang", "java/lang/String.class"));
7474
}
7575

7676
@Test
7777
void registerExactMatches() {
7878
this.resourceHints.registerPattern("com/example/test.properties");
7979
this.resourceHints.registerPattern("com/example/another.properties");
8080
assertThat(this.resourceHints.resourcePatternHints())
81-
.anySatisfy(patternOf("com", "com/example", "com/example/test.properties"))
82-
.anySatisfy(patternOf("com", "com/example", "com/example/another.properties"))
81+
.anySatisfy(patternOf("/", "com", "com/example", "com/example/test.properties"))
82+
.anySatisfy(patternOf("/", "com", "com/example", "com/example/another.properties"))
83+
.hasSize(2);
84+
}
85+
86+
@Test
87+
void registerExactMatchesInRootDirectory() {
88+
this.resourceHints.registerPattern("test.properties");
89+
this.resourceHints.registerPattern("another.properties");
90+
assertThat(this.resourceHints.resourcePatternHints())
91+
.anySatisfy(patternOf("/", "test.properties"))
92+
.anySatisfy(patternOf("/", "another.properties"))
8393
.hasSize(2);
8494
}
8595

@@ -101,15 +111,15 @@ void registerRootPattern() {
101111
void registerPattern() {
102112
this.resourceHints.registerPattern("com/example/*.properties");
103113
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(
104-
patternOf("com", "com/example", "com/example/*.properties"));
114+
patternOf("/", "com", "com/example", "com/example/*.properties"));
105115
}
106116

107117
@Test
108118
void registerPatternWithIncludesAndExcludes() {
109119
this.resourceHints.registerPattern(resourceHint ->
110120
resourceHint.includes("com/example/*.properties").excludes("com/example/to-ignore.properties"));
111121
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(patternOf(
112-
List.of("com", "com/example", "com/example/*.properties"),
122+
List.of("/", "com", "com/example", "com/example/*.properties"),
113123
List.of("com/example/to-ignore.properties")));
114124
}
115125

@@ -118,7 +128,7 @@ void registerIfPresentRegisterExistingLocation() {
118128
this.resourceHints.registerPatternIfPresent(null, "META-INF/",
119129
resourceHint -> resourceHint.includes("com/example/*.properties"));
120130
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(
121-
patternOf("com", "com/example", "com/example/*.properties"));
131+
patternOf("/", "com", "com/example", "com/example/*.properties"));
122132
}
123133

124134
@Test
@@ -152,7 +162,7 @@ void registerResourceWithExistingClassPathResource() {
152162
ClassPathResource resource = new ClassPathResource(path);
153163
this.resourceHints.registerResource(resource);
154164
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(
155-
patternOf("org", "org/springframework", "org/springframework/aot", "org/springframework/aot/hint", path));
165+
patternOf("/", "org", "org/springframework", "org/springframework/aot", "org/springframework/aot/hint", path));
156166
}
157167

158168
@Test
@@ -161,7 +171,7 @@ void registerResourceWithExistingRelativeClassPathResource() {
161171
ClassPathResource resource = new ClassPathResource("support", RuntimeHints.class);
162172
this.resourceHints.registerResource(resource);
163173
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(
164-
patternOf("org", "org/springframework", "org/springframework/aot", "org/springframework/aot/hint", path));
174+
patternOf("/", "org", "org/springframework", "org/springframework/aot", "org/springframework/aot/hint", path));
165175
}
166176

167177
@Test
@@ -197,8 +207,7 @@ private Consumer<ResourcePatternHints> patternOf(List<String> includes, List<Str
197207

198208
static class Nested {
199209

200-
static class Inner {
201-
210+
class Inner {
202211
}
203212
}
204213

spring-core/src/test/java/org/springframework/aot/hint/RuntimeHintsTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void resourceHintWithClass() {
4949
this.hints.resources().registerType(String.class);
5050
assertThat(this.hints.resources().resourcePatternHints()).singleElement().satisfies(resourceHint -> {
5151
assertThat(resourceHint.getIncludes()).map(ResourcePatternHint::getPattern)
52-
.containsExactlyInAnyOrder("java", "java/lang", "java/lang/String.class");
52+
.containsExactlyInAnyOrder("/", "java", "java/lang", "java/lang/String.class");
5353
assertThat(resourceHint.getExcludes()).isEmpty();
5454
});
5555
}

spring-core/src/test/java/org/springframework/aot/hint/support/FilePatternResourceHintsRegistrarTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void registerWithLocationWithoutTrailingSlash() {
8989
new FilePatternResourceHintsRegistrar(List.of("test"), List.of("META-INF"), List.of(".txt"))
9090
.registerHints(this.hints, null);
9191
assertThat(this.hints.resourcePatternHints()).singleElement()
92-
.satisfies(includes("META-INF", "META-INF/test*.txt"));
92+
.satisfies(includes("/", "META-INF", "META-INF/test*.txt"));
9393
}
9494

9595
@Test
@@ -105,15 +105,15 @@ void registerWithLocationUsingResourceClasspathPrefix() {
105105
new FilePatternResourceHintsRegistrar(List.of("test"), List.of("classpath:META-INF"), List.of(".txt"))
106106
.registerHints(this.hints, null);
107107
assertThat(this.hints.resourcePatternHints()).singleElement()
108-
.satisfies(includes("META-INF", "META-INF/test*.txt"));
108+
.satisfies(includes("/", "META-INF", "META-INF/test*.txt"));
109109
}
110110

111111
@Test
112112
void registerWithLocationUsingResourceClasspathPrefixAndTrailingSlash() {
113113
new FilePatternResourceHintsRegistrar(List.of("test"), List.of("classpath:/META-INF"), List.of(".txt"))
114114
.registerHints(this.hints, null);
115115
assertThat(this.hints.resourcePatternHints()).singleElement()
116-
.satisfies(includes("META-INF", "META-INF/test*.txt"));
116+
.satisfies(includes("/", "META-INF", "META-INF/test*.txt"));
117117
}
118118

119119
@Test

spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ void resourceConfig() throws IOException, JSONException {
176176
"resources": {
177177
"includes": [
178178
{"pattern": "\\\\Qcom/example/test.properties\\\\E"},
179+
{"pattern": "\\\\Q/\\\\E"},
179180
{"pattern": "\\\\Qcom\\\\E"},
180181
{"pattern": "\\\\Qcom/example\\\\E"},
181182
{"pattern": "\\\\Qcom/example/another.properties\\\\E"}

spring-core/src/test/java/org/springframework/aot/nativex/ResourceHintsWriterTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ void registerExactMatch() throws JSONException {
5050
"resources": {
5151
"includes": [
5252
{ "pattern": "\\\\Qcom/example/test.properties\\\\E"},
53+
{ "pattern": "\\\\Q/\\\\E" },
5354
{ "pattern": "\\\\Qcom\\\\E"},
5455
{ "pattern": "\\\\Qcom/example\\\\E"},
5556
{ "pattern": "\\\\Qcom/example/another.properties\\\\E"}
@@ -82,6 +83,7 @@ void registerWildcardInTheMiddlePattern() throws JSONException {
8283
"resources": {
8384
"includes": [
8485
{ "pattern": "\\\\Qcom/example/\\\\E.*\\\\Q.properties\\\\E"},
86+
{ "pattern": "\\\\Q/\\\\E" },
8587
{ "pattern": "\\\\Qcom\\\\E"},
8688
{ "pattern": "\\\\Qcom/example\\\\E"}
8789
]
@@ -98,6 +100,7 @@ void registerWildcardAtTheEndPattern() throws JSONException {
98100
"resources": {
99101
"includes": [
100102
{ "pattern": "\\\\Qstatic/\\\\E.*"},
103+
{ "pattern": "\\\\Q/\\\\E" },
101104
{ "pattern": "\\\\Qstatic\\\\E"}
102105
]
103106
}
@@ -114,6 +117,7 @@ void registerPatternWithIncludesAndExcludes() throws JSONException {
114117
"resources": {
115118
"includes": [
116119
{ "pattern": "\\\\Qcom/example/\\\\E.*\\\\Q.properties\\\\E"},
120+
{ "pattern": "\\\\Q/\\\\E"},
117121
{ "pattern": "\\\\Qcom\\\\E"},
118122
{ "pattern": "\\\\Qcom/example\\\\E"},
119123
{ "pattern": "\\\\Qorg/other/\\\\E.*\\\\Q.properties\\\\E"},
@@ -137,6 +141,7 @@ void registerWithReachableTypeCondition() throws JSONException {
137141
"resources": {
138142
"includes": [
139143
{ "condition": { "typeReachable": "com.example.Test"}, "pattern": "\\\\Qcom/example/test.properties\\\\E"},
144+
{ "condition": { "typeReachable": "com.example.Test"}, "pattern": "\\\\Q/\\\\E"},
140145
{ "condition": { "typeReachable": "com.example.Test"}, "pattern": "\\\\Qcom\\\\E"},
141146
{ "condition": { "typeReachable": "com.example.Test"}, "pattern": "\\\\Qcom/example\\\\E"}
142147
]
@@ -153,6 +158,7 @@ void registerType() throws JSONException {
153158
"resources": {
154159
"includes": [
155160
{ "pattern": "\\\\Qjava/lang/String.class\\\\E" },
161+
{ "pattern": "\\\\Q/\\\\E" },
156162
{ "pattern": "\\\\Qjava\\\\E" },
157163
{ "pattern": "\\\\Qjava/lang\\\\E" }
158164
]

0 commit comments

Comments
 (0)