diff --git a/spring-core/src/main/java/org/springframework/util/xml/XmlValidationModeDetector.java b/spring-core/src/main/java/org/springframework/util/xml/XmlValidationModeDetector.java
index 8cef06a80f4..305619e1fb0 100644
--- a/spring-core/src/main/java/org/springframework/util/xml/XmlValidationModeDetector.java
+++ b/spring-core/src/main/java/org/springframework/util/xml/XmlValidationModeDetector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -30,6 +30,7 @@ import org.springframework.util.StringUtils;
*
* @author Rob Harrop
* @author Juergen Hoeller
+ * @author Sam Brannen
* @since 2.0
*/
public class XmlValidationModeDetector {
@@ -142,20 +143,27 @@ public class XmlValidationModeDetector {
}
/**
- * Consumes all the leading comment data in the given String and returns the remaining content, which
- * may be empty since the supplied content might be all comment data. For our purposes it is only important
- * to strip leading comment content on a line since the first piece of non comment content will be either
- * the DOCTYPE declaration or the root element of the document.
+ * Consume all leading and trailing comments in the given String and return
+ * the remaining content, which may be empty since the supplied content might
+ * be all comment data.
*/
@Nullable
private String consumeCommentTokens(String line) {
- if (!line.contains(START_COMMENT) && !line.contains(END_COMMENT)) {
+ int indexOfStartComment = line.indexOf(START_COMMENT);
+ if (indexOfStartComment == -1 && !line.contains(END_COMMENT)) {
return line;
}
+
+ String result = "";
String currLine = line;
+ if (indexOfStartComment >= 0) {
+ result = line.substring(0, indexOfStartComment);
+ currLine = line.substring(indexOfStartComment);
+ }
+
while ((currLine = consume(currLine)) != null) {
if (!this.inComment && !currLine.trim().startsWith(START_COMMENT)) {
- return currLine;
+ return result + currLine;
}
}
return null;
diff --git a/spring-core/src/test/java/org/springframework/util/xml/XmlValidationModeDetectorTests.java b/spring-core/src/test/java/org/springframework/util/xml/XmlValidationModeDetectorTests.java
new file mode 100644
index 00000000000..61b01af8966
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/XmlValidationModeDetectorTests.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2002-2019 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.InputStream;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.springframework.util.xml.XmlValidationModeDetector.VALIDATION_DTD;
+
+/**
+ * Unit tests for {@link XmlValidationModeDetector}.
+ *
+ * @author Sam Brannen
+ * @since 5.1.10
+ */
+public class XmlValidationModeDetectorTests {
+
+ private final XmlValidationModeDetector xmlValidationModeDetector = new XmlValidationModeDetector();
+
+
+ @Test
+ public void dtdWithTrailingComment() throws Exception {
+ dtdDetection("dtdWithTrailingComment.xml");
+ }
+
+ @Test
+ public void dtdWithLeadingComment() throws Exception {
+ dtdDetection("dtdWithLeadingComment.xml");
+ }
+
+ @Test
+ public void dtdWithCommentOnNextLine() throws Exception {
+ dtdDetection("dtdWithCommentOnNextLine.xml");
+ }
+
+ @Test
+ public void dtdWithMultipleComments() throws Exception {
+ dtdDetection("dtdWithMultipleComments.xml");
+ }
+
+ private void dtdDetection(String fileName) throws Exception {
+ InputStream inputStream = getClass().getResourceAsStream(fileName);
+ assertEquals(VALIDATION_DTD, xmlValidationModeDetector.detectValidationMode(inputStream));
+ }
+
+}
diff --git a/spring-core/src/test/resources/org/springframework/util/xml/dtdWithCommentOnNextLine.xml b/spring-core/src/test/resources/org/springframework/util/xml/dtdWithCommentOnNextLine.xml
new file mode 100644
index 00000000000..cc610ba4abf
--- /dev/null
+++ b/spring-core/src/test/resources/org/springframework/util/xml/dtdWithCommentOnNextLine.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/spring-core/src/test/resources/org/springframework/util/xml/dtdWithLeadingComment.xml b/spring-core/src/test/resources/org/springframework/util/xml/dtdWithLeadingComment.xml
new file mode 100644
index 00000000000..710a5a4b044
--- /dev/null
+++ b/spring-core/src/test/resources/org/springframework/util/xml/dtdWithLeadingComment.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/spring-core/src/test/resources/org/springframework/util/xml/dtdWithMultipleComments.xml b/spring-core/src/test/resources/org/springframework/util/xml/dtdWithMultipleComments.xml
new file mode 100644
index 00000000000..03b9964f01d
--- /dev/null
+++ b/spring-core/src/test/resources/org/springframework/util/xml/dtdWithMultipleComments.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/spring-core/src/test/resources/org/springframework/util/xml/dtdWithTrailingComment.xml b/spring-core/src/test/resources/org/springframework/util/xml/dtdWithTrailingComment.xml
new file mode 100644
index 00000000000..c8fd329eef8
--- /dev/null
+++ b/spring-core/src/test/resources/org/springframework/util/xml/dtdWithTrailingComment.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+