Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-Document-Separators "#---" comment checks do not account for '!' prefixed comments #32521

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -497,7 +497,7 @@ For example, the following file has two logical documents:
on-cloud-platform: "kubernetes"
----

For `application.properties` files a special `#---` comment is used to mark the document splits:
For `application.properties` files a special `#---` or `!---` comment is used to mark the document splits:

[source,properties,indent=0,subs="verbatim"]
----
Expand All @@ -508,7 +508,7 @@ For `application.properties` files a special `#---` comment is used to mark the
----

NOTE: Property file separators must not have any leading whitespace and must have exactly three hyphen characters.
The lines immediately before and after the separator must not be comments.
The lines immediately before and after the separator must not be same comment prefix.

TIP: Multi-document property files are often used in conjunction with activation properties such as `spring.config.activate.on-profile`.
See the <<features#features.external-config.files.activation-properties, next section>> for details.
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2022 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.
Expand Down Expand Up @@ -78,7 +78,8 @@ List<Document> load(boolean expandLists) throws IOException {
StringBuilder buffer = new StringBuilder();
try (CharacterReader reader = new CharacterReader(this.resource)) {
while (reader.read()) {
if (reader.isPoundCharacter()) {
if (reader.isCommentPrefixCharacter()) {
char commentPrefixCharacter = reader.getCharacter();
if (isNewDocument(reader)) {
if (!document.isEmpty()) {
documents.add(document);
Expand All @@ -89,12 +90,12 @@ List<Document> load(boolean expandLists) throws IOException {
if (document.isEmpty() && !documents.isEmpty()) {
document = documents.remove(documents.size() - 1);
}
reader.setLastLineComment(true);
reader.setLastLineCommentPrefix(commentPrefixCharacter);
reader.skipComment();
}
}
else {
reader.setLastLineComment(false);
reader.setLastLineCommentPrefix(-1);
loadKeyAndValue(expandLists, document, reader, buffer);
}
}
Expand Down Expand Up @@ -161,10 +162,10 @@ private OriginTrackedValue loadValue(StringBuilder buffer, CharacterReader reade
}

private boolean isNewDocument(CharacterReader reader) throws IOException {
if (reader.isLastLineComment()) {
if (reader.isSameLastLineCommentPrefix()) {
return false;
}
boolean result = reader.getLocation().getColumn() == 0 && reader.isPoundCharacter();
boolean result = reader.getLocation().getColumn() == 0;
result = result && readAndExpect(reader, reader::isHyphenCharacter);
result = result && readAndExpect(reader, reader::isHyphenCharacter);
result = result && readAndExpect(reader, reader::isHyphenCharacter);
Expand Down Expand Up @@ -196,7 +197,7 @@ private static class CharacterReader implements Closeable {

private int character;

private boolean lastLineComment;
private int lastLineCommentPrefix;

CharacterReader(Resource resource) throws IOException {
this.reader = new LineNumberReader(
Expand All @@ -209,20 +210,11 @@ public void close() throws IOException {
}

boolean read() throws IOException {
return read(false);
}

boolean read(boolean wrappedLine) throws IOException {
this.escaped = false;
this.character = this.reader.read();
this.columnNumber++;
if (this.columnNumber == 0) {
skipWhitespace();
if (!wrappedLine) {
if (this.character == '!') {
skipComment();
}
}
}
if (this.character == '\\') {
this.escaped = true;
Expand All @@ -241,12 +233,8 @@ private void skipWhitespace() throws IOException {
}
}

private void setLastLineComment(boolean lastLineComment) {
this.lastLineComment = lastLineComment;
}

private boolean isLastLineComment() {
return this.lastLineComment;
private void setLastLineCommentPrefix(int lastLineCommentPrefix) {
this.lastLineCommentPrefix = lastLineCommentPrefix;
}

private void skipComment() throws IOException {
Expand All @@ -264,7 +252,7 @@ private void readEscaped() throws IOException {
}
else if (this.character == '\n') {
this.columnNumber = -1;
read(true);
read();
}
else if (this.character == 'u') {
readUnicode();
Expand Down Expand Up @@ -318,8 +306,12 @@ Location getLocation() {
return new Location(this.reader.getLineNumber(), this.columnNumber);
}

boolean isPoundCharacter() {
return this.character == '#';
boolean isSameLastLineCommentPrefix() {
return this.lastLineCommentPrefix == this.character;
}

boolean isCommentPrefixCharacter() {
return this.character == '#' || this.character == '!';
}

boolean isHyphenCharacter() {
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2021 the original author or authors.
* Copyright 2012-2022 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.
Expand Down Expand Up @@ -183,33 +183,70 @@ void getImmediateMultiline() {
}

@Test
void loadWhenMultiDocumentWithoutWhitespaceLoadsMultiDoc() throws IOException {
void loadWhenMultiDocumentWithPoundPrefixAndWithoutWhitespaceLoadsMultiDoc() throws IOException {
String content = "a=a\n#---\nb=b";
List<Document> loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load();
assertThat(loaded).hasSize(2);
}

@Test
void loadWhenMultiDocumentWithLeadingWhitespaceLoadsSingleDoc() throws IOException {
void loadWhenMultiDocumentWithExclamationPrefixAndWithoutWhitespaceLoadsMultiDoc() throws IOException {
String content = "a=a\n!---\nb=b";
List<Document> loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load();
assertThat(loaded).hasSize(2);
}

@Test
void loadWhenMultiDocumentWithPoundPrefixAndLeadingWhitespaceLoadsSingleDoc() throws IOException {
String content = "a=a\n \t#---\nb=b";
List<Document> loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load();
assertThat(loaded).hasSize(1);
}

@Test
void loadWhenMultiDocumentWithTrailingWhitespaceLoadsMultiDoc() throws IOException {
void loadWhenMultiDocumentWithExclamationPrefixAndLeadingWhitespaceLoadsSingleDoc() throws IOException {
String content = "a=a\n \t!---\nb=b";
List<Document> loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load();
assertThat(loaded).hasSize(1);
}

@Test
void loadWhenMultiDocumentWithPoundPrefixAndTrailingWhitespaceLoadsMultiDoc() throws IOException {
String content = "a=a\n#--- \t \nb=b";
List<Document> loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load();
assertThat(loaded).hasSize(2);
}

@Test
void loadWhenMultiDocumentWithTrailingCharsLoadsSingleDoc() throws IOException {
void loadWhenMultiDocumentWithExclamationPrefixAndTrailingWhitespaceLoadsMultiDoc() throws IOException {
String content = "a=a\n!--- \t \nb=b";
List<Document> loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load();
assertThat(loaded).hasSize(2);
}

@Test
void loadWhenMultiDocumentWithPoundPrefixAndTrailingCharsLoadsSingleDoc() throws IOException {
String content = "a=a\n#--- \tcomment\nb=b";
List<Document> loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load();
assertThat(loaded).hasSize(1);
}

@Test
void loadWhenMultiDocumentWithExclamationPrefixAndTrailingCharsLoadsSingleDoc() throws IOException {
String content = "a=a\n!--- \tcomment\nb=b";
List<Document> loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load();
assertThat(loaded).hasSize(1);
}

@Test
void loadWhenMultiDocumentSeparatorPrefixDifferentFromCommentPrefixLoadsMultiDoc() throws IOException {
String[] contents = new String[] { "a=a\n# comment\n!---\nb=b", "a=a\n! comment\n#---\nb=b" };
for (String content : contents) {
List<Document> loaded = new OriginTrackedPropertiesLoader(new ByteArrayResource(content.getBytes())).load();
assertThat(loaded).hasSize(2);
}
}

@Test
void getPropertyWithWhitespaceAfterKey() {
OriginTrackedValue value = getFromFirst("bar");
Expand Down
Expand Up @@ -14,3 +14,19 @@ boot=bar
#---

bar=ok

!---
! Test
!---

ok=well

!---
! Test

well=hello

! Test
!---

hello=world