Allow registration of resource hint for root directory

Prior to this commit, it was not possible to register the root
directory as a native image resource; however, it is necessary to be
able to register the root directory to enable classpath scanning of the
root directory within a native image -- for example, to support
resource patterns such as `classpath*:/*.properties`.

This commit therefore relaxes the precondition check in the
ResourcePatternHint constructor to allow explicit registration of the
root directory.

Closes gh-29402
This commit is contained in:
Sam Brannen 2022-10-30 18:18:07 +01:00
parent 3c42363ba4
commit d03102edc3
3 changed files with 23 additions and 4 deletions

View File

@ -43,7 +43,8 @@ import org.springframework.util.Assert;
* and its child directories at any depth.</li> * and its child directories at any depth.</li>
* </ul> * </ul>
* *
* <p>A resource pattern must not start with a slash ({@code /}). * <p>A resource pattern must not start with a slash ({@code /}) unless it is the
* root directory.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Brian Clozel * @author Brian Clozel
@ -58,13 +59,16 @@ public final class ResourcePatternHint implements ConditionalHint {
@Nullable @Nullable
private final TypeReference reachableType; private final TypeReference reachableType;
ResourcePatternHint(String pattern, @Nullable TypeReference reachableType) { ResourcePatternHint(String pattern, @Nullable TypeReference reachableType) {
Assert.isTrue(!pattern.startsWith("/"), Assert.isTrue(("/".equals(pattern) || !pattern.startsWith("/")),
() -> "Resource pattern [%s] must not start with a '/'".formatted(pattern)); () -> "Resource pattern [%s] must not start with a '/' unless it is the root directory"
.formatted(pattern));
this.pattern = pattern; this.pattern = pattern;
this.reachableType = reachableType; this.reachableType = reachableType;
} }
/** /**
* Return the pattern to use for identifying the resources to match. * Return the pattern to use for identifying the resources to match.
* @return the pattern * @return the pattern

View File

@ -81,6 +81,13 @@ class ResourceHintsTests {
.hasSize(2); .hasSize(2);
} }
@Test
void registerRootDirectory() {
this.resourceHints.registerPattern("/");
assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(
patternOf("/"));
}
@Test @Test
void registerPattern() { void registerPattern() {
this.resourceHints.registerPattern("com/example/*.properties"); this.resourceHints.registerPattern("com/example/*.properties");

View File

@ -33,7 +33,15 @@ class ResourcePatternHintTests {
void patternWithLeadingSlashIsRejected() { void patternWithLeadingSlashIsRejected() {
assertThatIllegalArgumentException() assertThatIllegalArgumentException()
.isThrownBy(() -> new ResourcePatternHint("/file.properties", null)) .isThrownBy(() -> new ResourcePatternHint("/file.properties", null))
.withMessage("Resource pattern [/file.properties] must not start with a '/'"); .withMessage("Resource pattern [/file.properties] must not start with a '/' unless it is the root directory");
}
@Test
void rootDirectory() {
ResourcePatternHint hint = new ResourcePatternHint("/", null);
assertThat(hint.toRegex().asMatchPredicate())
.accepts("/")
.rejects("/com/example", "/file.txt");
} }
@Test @Test