diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedPropertiesLoader.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedPropertiesLoader.java index 6deaa3d32d..f84e0c28ec 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedPropertiesLoader.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedPropertiesLoader.java @@ -57,8 +57,7 @@ class OriginTrackedPropertiesLoader { } /** - * Load {@code .properties} data and return a map of {@code String} -> - * {@link OriginTrackedValue}. + * Load {@code .properties} data and return a list of documents. * @return the loaded properties * @throws IOException on read error */ @@ -79,7 +78,7 @@ class OriginTrackedPropertiesLoader { try (CharacterReader reader = new CharacterReader(this.resource)) { StringBuilder buffer = new StringBuilder(); while (reader.read()) { - if (reader.getCharacter() == '#') { + if (reader.isPoundCharacter()) { if (isNewDocument(reader)) { if (!document.isEmpty()) { result.add(document); @@ -150,12 +149,13 @@ class OriginTrackedPropertiesLoader { } boolean isNewDocument(CharacterReader reader) throws IOException { - boolean result = reader.isPoundCharacter(); + boolean result = reader.getLocation().getColumn() == 0 && reader.isPoundCharacter(); result = result && readAndExpect(reader, reader::isHyphenCharacter); result = result && readAndExpect(reader, reader::isHyphenCharacter); result = result && readAndExpect(reader, reader::isHyphenCharacter); - result = result && readAndExpect(reader, reader::isEndOfLine); - return result; + reader.read(); + reader.skipWhitespace(); + return result && reader.isEndOfLine(); } private boolean readAndExpect(CharacterReader reader, BooleanSupplier check) throws IOException { @@ -198,7 +198,7 @@ class OriginTrackedPropertiesLoader { this.character = this.reader.read(); this.columnNumber++; if (this.columnNumber == 0) { - skipLeadingWhitespace(); + skipWhitespace(); if (!wrappedLine) { if (this.character == '!') { skipComment(); @@ -215,7 +215,7 @@ class OriginTrackedPropertiesLoader { return !isEndOfFile(); } - private void skipLeadingWhitespace() throws IOException { + private void skipWhitespace() throws IOException { while (isWhiteSpace()) { this.character = this.reader.read(); this.columnNumber++; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/env/OriginTrackedPropertiesLoaderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/env/OriginTrackedPropertiesLoaderTests.java index 8055942000..e13b4990b0 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/env/OriginTrackedPropertiesLoaderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/env/OriginTrackedPropertiesLoaderTests.java @@ -16,6 +16,7 @@ package org.springframework.boot.env; +import java.io.IOException; import java.util.List; import java.util.Properties; @@ -25,6 +26,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.env.OriginTrackedPropertiesLoader.Document; import org.springframework.boot.origin.OriginTrackedValue; import org.springframework.boot.origin.TextResourceOrigin; +import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.support.PropertiesLoaderUtils; @@ -180,6 +182,34 @@ class OriginTrackedPropertiesLoaderTests { assertThat(getLocation(value)).isEqualTo("32:1"); } + @Test + void loadWhenMultiDocumentWithoutWhitespaceLoadsMultiDoc() throws IOException { + String content = "a=a\n#---\nb=b"; + List loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load(); + assertThat(loaded).hasSize(2); + } + + @Test + void loadWhenMultiDocumentWithLeadingWhitespaceLoadsSingleDoc() throws IOException { + String content = "a=a\n \t#---\nb=b"; + List loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load(); + assertThat(loaded).hasSize(1); + } + + @Test + void loadWhenMultiDocumentWithTrailingWhitespaceLoadsMultiDoc() throws IOException { + String content = "a=a\n#--- \t \nb=b"; + List loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load(); + assertThat(loaded).hasSize(2); + } + + @Test + void loadWhenMultiDocumentWithTrailingCharsLoadsSingleDoc() throws IOException { + String content = "a=a\n#--- \tcomment\nb=b"; + List loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load(); + assertThat(loaded).hasSize(1); + } + @Test void getPropertyWithWhitespaceAfterKey() { OriginTrackedValue value = getFromFirst("bar");