Polish "Align DocumentBuilderFactory configuration"

See gh-50282
This commit is contained in:
Phillip Webb
2026-05-04 14:02:22 -07:00
parent eb90d0de63
commit f8ecad5155
6 changed files with 84 additions and 38 deletions
@@ -26,11 +26,8 @@ import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
@@ -51,6 +48,7 @@ import org.springframework.boot.build.bom.ResolvedBom.Id;
import org.springframework.boot.build.bom.ResolvedBom.JavadocLink;
import org.springframework.boot.build.bom.ResolvedBom.Links;
import org.springframework.boot.build.bom.ResolvedBom.ResolvedLibrary;
import org.springframework.boot.build.xml.XmlDocument;
/**
* Creates a {@link ResolvedBom resolved bom}.
@@ -68,15 +66,7 @@ class BomResolver {
BomResolver(ConfigurationContainer configurations, DependencyHandler dependencies) {
this.configurations = configurations;
this.dependencies = dependencies;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
this.documentBuilder = factory.newDocumentBuilder();
}
catch (ParserConfigurationException ex) {
throw new RuntimeException(ex);
}
this.documentBuilder = XmlDocument.builder();
}
ResolvedBom resolve(BomExtension bomExtension) {
@@ -35,9 +35,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
@@ -52,6 +49,7 @@ import org.w3c.dom.Document;
import org.springframework.boot.build.bom.ResolvedBom.Id;
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
import org.springframework.boot.build.xml.XmlDocument;
/**
* A collection of modules, Maven plugins, and Maven boms that are versioned and released
@@ -677,11 +675,7 @@ public class Library {
private String propertyFrom(File pomFile) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
Document document = documentBuilder.parse(pomFile);
Document document = XmlDocument.parse(pomFile);
XPath xpath = XPathFactory.newInstance().newXPath();
return xpath.evaluate("/project/properties/" + this.name + "/text()", document);
}
@@ -16,7 +16,6 @@
package org.springframework.boot.build.bom.bomr;
import java.io.StringReader;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
@@ -26,8 +25,6 @@ import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
@@ -37,9 +34,9 @@ import org.gradle.api.credentials.Credentials;
import org.gradle.internal.artifacts.repositories.AuthenticationSupportedInternal;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
import org.springframework.boot.build.xml.XmlDocument;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -94,10 +91,7 @@ final class MavenMetadataVersionResolver implements VersionResolver {
}
HttpEntity<Void> request = new HttpEntity<>(headers);
String metadata = this.rest.exchange(url, HttpMethod.GET, request, String.class).getBody();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
Document metadataDocument = factory.newDocumentBuilder().parse(new InputSource(new StringReader(metadata)));
Document metadataDocument = XmlDocument.parseContent(metadata);
NodeList versionNodes = (NodeList) XPathFactory.newInstance()
.newXPath()
.evaluate("/metadata/versioning/versions/version", metadataDocument, XPathConstants.NODESET);
@@ -23,8 +23,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
@@ -33,6 +31,8 @@ import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.springframework.boot.build.xml.XmlDocument;
/**
* A parser for a Maven plugin's {@code plugin.xml} file.
*
@@ -49,10 +49,7 @@ class PluginXmlParser {
Plugin parse(File pluginXml) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
Node root = factory.newDocumentBuilder().parse(pluginXml);
Node root = XmlDocument.parse(pluginXml);
List<Mojo> mojos = parseMojos(root);
return new Plugin(textAt("//plugin/groupId", root), textAt("//plugin/artifactId", root),
textAt("//plugin/version", root), textAt("//plugin/goalPrefix", root), mojos);
@@ -0,0 +1,72 @@
/*
* Copyright 2026 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.boot.build.xml;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* XML {@link Document} builder and parsing.
*
* @author Phillip Webb
* @author Sebastien Tardif
*/
public final class XmlDocument {
private static final DocumentBuilderFactory factory;
static {
try {
factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
}
catch (ParserConfigurationException ex) {
throw new IllegalStateException(ex);
}
}
private XmlDocument() {
}
public static Document parseContent(String content) throws SAXException, IOException {
return builder().parse(new InputSource(new StringReader(content)));
}
public static Document parse(File file) throws SAXException, IOException {
return builder().parse(file);
}
public static DocumentBuilder builder() {
try {
return factory.newDocumentBuilder();
}
catch (ParserConfigurationException ex) {
throw new IllegalStateException(ex);
}
}
}
@@ -18,7 +18,6 @@ package org.springframework.boot.build.assertj;
import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
@@ -30,6 +29,8 @@ import org.assertj.core.api.StringAssert;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.springframework.boot.build.xml.XmlDocument;
/**
* AssertJ {@link AssertProvider} for {@link Node} assertions.
*
@@ -37,8 +38,6 @@ import org.w3c.dom.Node;
*/
public class NodeAssert extends AbstractAssert<NodeAssert, Node> implements AssertProvider<NodeAssert> {
private static final DocumentBuilderFactory FACTORY = DocumentBuilderFactory.newInstance();
private final XPathFactory xpathFactory = XPathFactory.newInstance();
private final XPath xpath = this.xpathFactory.newXPath();
@@ -53,7 +52,7 @@ public class NodeAssert extends AbstractAssert<NodeAssert, Node> implements Asse
private static Document read(File xmlFile) {
try {
return FACTORY.newDocumentBuilder().parse(xmlFile);
return XmlDocument.parse(xmlFile);
}
catch (Exception ex) {
throw new RuntimeException(ex);