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 @@ + + + + + +