Skip to content

Commit 198576d

Browse files
committed
Merge branch '5.3.x'
2 parents 680ec30 + 4b1b254 commit 198576d

File tree

8 files changed

+105
-25
lines changed

8 files changed

+105
-25
lines changed

spring-core/src/main/java/org/springframework/util/xml/XmlValidationModeDetector.java

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -58,7 +58,7 @@ public class XmlValidationModeDetector {
5858

5959

6060
/**
61-
* The token in a XML document that declares the DTD to use for validation
61+
* The token in an XML document that declares the DTD to use for validation
6262
* and thus that DTD validation is being used.
6363
*/
6464
private static final String DOCTYPE = "DOCTYPE";
@@ -82,20 +82,22 @@ public class XmlValidationModeDetector {
8282

8383
/**
8484
* Detect the validation mode for the XML document in the supplied {@link InputStream}.
85-
* Note that the supplied {@link InputStream} is closed by this method before returning.
85+
* <p>Note that the supplied {@link InputStream} is closed by this method before returning.
8686
* @param inputStream the InputStream to parse
8787
* @throws IOException in case of I/O failure
8888
* @see #VALIDATION_DTD
8989
* @see #VALIDATION_XSD
9090
*/
9191
public int detectValidationMode(InputStream inputStream) throws IOException {
92+
this.inComment = false;
93+
9294
// Peek into the file to look for DOCTYPE.
9395
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
9496
boolean isDtdValidated = false;
9597
String content;
9698
while ((content = reader.readLine()) != null) {
9799
content = consumeCommentTokens(content);
98-
if (this.inComment || !StringUtils.hasText(content)) {
100+
if (!StringUtils.hasText(content)) {
99101
continue;
100102
}
101103
if (hasDoctype(content)) {
@@ -125,9 +127,11 @@ private boolean hasDoctype(String content) {
125127
}
126128

127129
/**
128-
* Does the supplied content contain an XML opening tag. If the parse state is currently
129-
* in an XML comment then this method always returns false. It is expected that all comment
130-
* tokens will have consumed for the supplied content before passing the remainder to this method.
130+
* Determine if the supplied content contains an XML opening tag.
131+
* <p>It is expected that all comment tokens will have been consumed for the
132+
* supplied content before passing the remainder to this method. However, as
133+
* a sanity check, if the parse state is currently in an XML comment this
134+
* method always returns {@code false}.
131135
*/
132136
private boolean hasOpeningTag(String content) {
133137
if (this.inComment) {
@@ -139,11 +143,10 @@ private boolean hasOpeningTag(String content) {
139143
}
140144

141145
/**
142-
* Consume all leading and trailing comments in the given String and return
143-
* the remaining content, which may be empty since the supplied content might
144-
* be all comment data.
146+
* Consume all comments in the given String and return the remaining content,
147+
* which may be empty since the supplied content might be all comment data.
148+
* <p>This method takes the current "in comment" parsing state into account.
145149
*/
146-
@Nullable
147150
private String consumeCommentTokens(String line) {
148151
int indexOfStartComment = line.indexOf(START_COMMENT);
149152
if (indexOfStartComment == -1 && !line.contains(END_COMMENT)) {
@@ -152,21 +155,19 @@ private String consumeCommentTokens(String line) {
152155

153156
String result = "";
154157
String currLine = line;
155-
if (indexOfStartComment >= 0) {
158+
if (!this.inComment && (indexOfStartComment >= 0)) {
156159
result = line.substring(0, indexOfStartComment);
157160
currLine = line.substring(indexOfStartComment);
158161
}
159162

160-
while ((currLine = consume(currLine)) != null) {
161-
if (!this.inComment && !currLine.trim().startsWith(START_COMMENT)) {
162-
return result + currLine;
163-
}
163+
if ((currLine = consume(currLine)) != null) {
164+
result += consumeCommentTokens(currLine);
164165
}
165-
return null;
166+
return result;
166167
}
167168

168169
/**
169-
* Consume the next comment token, update the "inComment" flag
170+
* Consume the next comment token, update the "inComment" flag,
170171
* and return the remaining content.
171172
*/
172173
@Nullable
@@ -183,14 +184,19 @@ private int startComment(String line) {
183184
return commentToken(line, START_COMMENT, true);
184185
}
185186

187+
/**
188+
* Try to consume the {@link #END_COMMENT} token.
189+
* @see #commentToken(String, String, boolean)
190+
*/
186191
private int endComment(String line) {
187192
return commentToken(line, END_COMMENT, false);
188193
}
189194

190195
/**
191196
* Try to consume the supplied token against the supplied content and update the
192-
* in comment parse state to the supplied value. Returns the index into the content
193-
* which is after the token or -1 if the token is not found.
197+
* "in comment" parse state to the supplied value.
198+
* <p>Returns the index into the content which is after the token or -1 if the
199+
* token is not found.
194200
*/
195201
private int commentToken(String line, String token, boolean inCommentIfPresent) {
196202
int index = line.indexOf(token);

spring-core/src/test/java/org/springframework/util/xml/XmlValidationModeDetectorTests.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,13 +16,15 @@
1616

1717
package org.springframework.util.xml;
1818

19+
import java.io.IOException;
1920
import java.io.InputStream;
2021

2122
import org.junit.jupiter.params.ParameterizedTest;
2223
import org.junit.jupiter.params.provider.ValueSource;
2324

2425
import static org.assertj.core.api.Assertions.assertThat;
2526
import static org.springframework.util.xml.XmlValidationModeDetector.VALIDATION_DTD;
27+
import static org.springframework.util.xml.XmlValidationModeDetector.VALIDATION_XSD;
2628

2729
/**
2830
* Unit tests for {@link XmlValidationModeDetector}.
@@ -36,11 +38,36 @@ class XmlValidationModeDetectorTests {
3638

3739

3840
@ParameterizedTest
39-
@ValueSource(strings = { "dtdWithTrailingComment.xml", "dtdWithLeadingComment.xml", "dtdWithCommentOnNextLine.xml",
40-
"dtdWithMultipleComments.xml" })
41+
@ValueSource(strings = {
42+
"dtdWithNoComments.xml",
43+
"dtdWithLeadingComment.xml",
44+
"dtdWithTrailingComment.xml",
45+
"dtdWithTrailingCommentAcrossMultipleLines.xml",
46+
"dtdWithCommentOnNextLine.xml",
47+
"dtdWithMultipleComments.xml"
48+
})
4149
void dtdDetection(String fileName) throws Exception {
42-
InputStream inputStream = getClass().getResourceAsStream(fileName);
43-
assertThat(xmlValidationModeDetector.detectValidationMode(inputStream)).isEqualTo(VALIDATION_DTD);
50+
assertValidationMode(fileName, VALIDATION_DTD);
51+
}
52+
53+
@ParameterizedTest
54+
@ValueSource(strings = {
55+
"xsdWithNoComments.xml",
56+
"xsdWithMultipleComments.xml",
57+
"xsdWithDoctypeInComment.xml",
58+
"xsdWithDoctypeInOpenCommentWithAdditionalCommentOnSameLine.xml"
59+
})
60+
void xsdDetection(String fileName) throws Exception {
61+
assertValidationMode(fileName, VALIDATION_XSD);
62+
}
63+
64+
65+
private void assertValidationMode(String fileName, int expectedValidationMode) throws IOException {
66+
try (InputStream inputStream = getClass().getResourceAsStream(fileName)) {
67+
assertThat(xmlValidationModeDetector.detectValidationMode(inputStream))
68+
.as("Validation Mode")
69+
.isEqualTo(expectedValidationMode);
70+
}
4471
}
4572

4673
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd">
3+
4+
<beans>
5+
6+
</beans>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd"><!-- comment --><beans><!--
3+
trailing comment across multiple lines -->
4+
5+
6+
</beans>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!-- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd"> -->
3+
<beans xmlns="http://www.springframework.org/schema/beans"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="https://www.springframework.org/schema/beans
6+
https://www.springframework.org/schema/beans/spring-beans.xsd">
7+
8+
</beans>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd"> --> <!-- additional comment on same line -->
4+
<beans xmlns="http://www.springframework.org/schema/beans"
5+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6+
xsi:schemaLocation="https://www.springframework.org/schema/beans
7+
https://www.springframework.org/schema/beans/spring-beans.xsd">
8+
9+
</beans>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!-- comment #1 --> <!-- comment #2 --> <beans xmlns="http://www.springframework.org/schema/beans"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="https://www.springframework.org/schema/beans
5+
https://www.springframework.org/schema/beans/spring-beans.xsd"><!--
6+
trailing
7+
comment
8+
-->
9+
10+
</beans>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<beans xmlns="http://www.springframework.org/schema/beans"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="https://www.springframework.org/schema/beans
6+
https://www.springframework.org/schema/beans/spring-beans.xsd">
7+
8+
</beans>

0 commit comments

Comments
 (0)