diff --git a/spring-xml/src/main/java/org/springframework/xml/XmlException.java b/spring-xml/src/main/java/org/springframework/xml/XmlException.java index 690d38eb..5c700859 100644 --- a/spring-xml/src/main/java/org/springframework/xml/XmlException.java +++ b/spring-xml/src/main/java/org/springframework/xml/XmlException.java @@ -16,6 +16,8 @@ package org.springframework.xml; +import org.jspecify.annotations.Nullable; + import org.springframework.core.NestedRuntimeException; /** @@ -42,7 +44,7 @@ public abstract class XmlException extends NestedRuntimeException { * @param message the detail message * @param throwable the wrapped exception */ - protected XmlException(String message, Throwable throwable) { + protected XmlException(@Nullable String message, Throwable throwable) { super(message, throwable); } diff --git a/spring-xml/src/main/java/org/springframework/xml/dom/package-info.java b/spring-xml/src/main/java/org/springframework/xml/dom/package-info.java index 458bd77f..7889a702 100644 --- a/spring-xml/src/main/java/org/springframework/xml/dom/package-info.java +++ b/spring-xml/src/main/java/org/springframework/xml/dom/package-info.java @@ -18,4 +18,7 @@ * Provides classes that help with DOM: the Document Object Model. Mostly for internal use * by the framework. */ +@NullMarked package org.springframework.xml.dom; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-xml/src/main/java/org/springframework/xml/namespace/QNameUtils.java b/spring-xml/src/main/java/org/springframework/xml/namespace/QNameUtils.java index 46bb78a6..71cc2dfe 100644 --- a/spring-xml/src/main/java/org/springframework/xml/namespace/QNameUtils.java +++ b/spring-xml/src/main/java/org/springframework/xml/namespace/QNameUtils.java @@ -18,6 +18,7 @@ package org.springframework.xml.namespace; import javax.xml.namespace.QName; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Node; import org.springframework.util.Assert; @@ -37,7 +38,7 @@ public abstract class QNameUtils { * @param text the qualified name * @return {@code true} if valid, {@code false} otherwise */ - public static boolean validateQName(String text) { + public static boolean validateQName(@Nullable String text) { if (!StringUtils.hasLength(text)) { return false; } diff --git a/spring-xml/src/main/java/org/springframework/xml/namespace/SimpleNamespaceContext.java b/spring-xml/src/main/java/org/springframework/xml/namespace/SimpleNamespaceContext.java index 11bfd279..1965e2d3 100644 --- a/spring-xml/src/main/java/org/springframework/xml/namespace/SimpleNamespaceContext.java +++ b/spring-xml/src/main/java/org/springframework/xml/namespace/SimpleNamespaceContext.java @@ -27,6 +27,8 @@ import java.util.Set; import javax.xml.XMLConstants; import javax.xml.namespace.NamespaceContext; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; /** @@ -59,7 +61,7 @@ public class SimpleNamespaceContext implements NamespaceContext { } @Override - public String getPrefix(String namespaceUri) { + public @Nullable String getPrefix(String namespaceUri) { Iterator iterator = getPrefixes(namespaceUri); return iterator.hasNext() ? iterator.next() : null; } diff --git a/spring-xml/src/main/java/org/springframework/xml/namespace/package-info.java b/spring-xml/src/main/java/org/springframework/xml/namespace/package-info.java index 9a4a8d72..3469c9f1 100644 --- a/spring-xml/src/main/java/org/springframework/xml/namespace/package-info.java +++ b/spring-xml/src/main/java/org/springframework/xml/namespace/package-info.java @@ -18,4 +18,7 @@ * Provides classes that help with XML Namespace processing. Mostly for internal use by * the framework. */ +@NullMarked package org.springframework.xml.namespace; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-xml/src/main/java/org/springframework/xml/package-info.java b/spring-xml/src/main/java/org/springframework/xml/package-info.java index 86c03b43..b26411d7 100644 --- a/spring-xml/src/main/java/org/springframework/xml/package-info.java +++ b/spring-xml/src/main/java/org/springframework/xml/package-info.java @@ -18,4 +18,7 @@ * Provides classes for XML handling: version detection and a base XML exception class. * Mostly for internal use by the framework. */ +@NullMarked package org.springframework.xml; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-xml/src/main/java/org/springframework/xml/sax/AbstractXmlReader.java b/spring-xml/src/main/java/org/springframework/xml/sax/AbstractXmlReader.java index f2d33282..32fd32ff 100644 --- a/spring-xml/src/main/java/org/springframework/xml/sax/AbstractXmlReader.java +++ b/spring-xml/src/main/java/org/springframework/xml/sax/AbstractXmlReader.java @@ -16,6 +16,7 @@ package org.springframework.xml.sax; +import org.jspecify.annotations.Nullable; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.EntityResolver; @@ -38,18 +39,18 @@ import org.xml.sax.ext.LexicalHandler; */ public abstract class AbstractXmlReader implements XMLReader { - private DTDHandler dtdHandler; + private @Nullable DTDHandler dtdHandler; - private ContentHandler contentHandler; + private @Nullable ContentHandler contentHandler; - private EntityResolver entityResolver; + private @Nullable EntityResolver entityResolver; - private ErrorHandler errorHandler; + private @Nullable ErrorHandler errorHandler; - private LexicalHandler lexicalHandler; + private @Nullable LexicalHandler lexicalHandler; @Override - public ContentHandler getContentHandler() { + public @Nullable ContentHandler getContentHandler() { return this.contentHandler; } @@ -64,12 +65,12 @@ public abstract class AbstractXmlReader implements XMLReader { } @Override - public DTDHandler getDTDHandler() { + public @Nullable DTDHandler getDTDHandler() { return this.dtdHandler; } @Override - public EntityResolver getEntityResolver() { + public @Nullable EntityResolver getEntityResolver() { return this.entityResolver; } @@ -79,7 +80,7 @@ public abstract class AbstractXmlReader implements XMLReader { } @Override - public ErrorHandler getErrorHandler() { + public @Nullable ErrorHandler getErrorHandler() { return this.errorHandler; } @@ -88,7 +89,7 @@ public abstract class AbstractXmlReader implements XMLReader { this.errorHandler = errorHandler; } - protected LexicalHandler getLexicalHandler() { + protected @Nullable LexicalHandler getLexicalHandler() { return this.lexicalHandler; } @@ -116,7 +117,7 @@ public abstract class AbstractXmlReader implements XMLReader { * {@code http://xml.org/sax/properties/lexical-handler}. */ @Override - public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { + public @Nullable Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { if ("http://xml.org/sax/properties/lexical-handler".equals(name)) { return this.lexicalHandler; } diff --git a/spring-xml/src/main/java/org/springframework/xml/sax/SaxUtils.java b/spring-xml/src/main/java/org/springframework/xml/sax/SaxUtils.java index 09e9feca..67b90d20 100644 --- a/spring-xml/src/main/java/org/springframework/xml/sax/SaxUtils.java +++ b/spring-xml/src/main/java/org/springframework/xml/sax/SaxUtils.java @@ -25,6 +25,7 @@ import javax.xml.parsers.SAXParserFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; @@ -76,7 +77,7 @@ public abstract class SaxUtils { * Retrieves the URL from the given resource as System ID. Returns {@code null} if it * cannot be opened. */ - public static String getSystemId(Resource resource) { + public static @Nullable String getSystemId(Resource resource) { try { return new URI(resource.getURL().toExternalForm()).toString(); } diff --git a/spring-xml/src/main/java/org/springframework/xml/sax/package-info.java b/spring-xml/src/main/java/org/springframework/xml/sax/package-info.java index d9b72eb2..727f74c4 100644 --- a/spring-xml/src/main/java/org/springframework/xml/sax/package-info.java +++ b/spring-xml/src/main/java/org/springframework/xml/sax/package-info.java @@ -18,4 +18,7 @@ * Provides classes that help with SAX: the Simple API for XML. Mostly for internal use by * the framework. */ +@NullMarked package org.springframework.xml.sax; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-xml/src/main/java/org/springframework/xml/transform/StringSource.java b/spring-xml/src/main/java/org/springframework/xml/transform/StringSource.java index e2719253..ab72b23d 100644 --- a/spring-xml/src/main/java/org/springframework/xml/transform/StringSource.java +++ b/spring-xml/src/main/java/org/springframework/xml/transform/StringSource.java @@ -22,6 +22,8 @@ import java.io.StringReader; import javax.xml.transform.stream.StreamSource; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; /** @@ -64,7 +66,7 @@ public class StringSource extends StreamSource { * @return {@code null} */ @Override - public InputStream getInputStream() { + public @Nullable InputStream getInputStream() { return null; } diff --git a/spring-xml/src/main/java/org/springframework/xml/transform/TransformerHelper.java b/spring-xml/src/main/java/org/springframework/xml/transform/TransformerHelper.java index 2d5b2fa9..3455224d 100644 --- a/spring-xml/src/main/java/org/springframework/xml/transform/TransformerHelper.java +++ b/spring-xml/src/main/java/org/springframework/xml/transform/TransformerHelper.java @@ -23,6 +23,8 @@ import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; /** @@ -34,9 +36,9 @@ import org.springframework.util.Assert; */ public class TransformerHelper { - private volatile TransformerFactory transformerFactory; + private volatile @Nullable TransformerFactory transformerFactory; - private Class transformerFactoryClass; + private @Nullable Class transformerFactoryClass; /** * Initializes a new instance of the {@code TransformerHelper}. @@ -81,7 +83,8 @@ public class TransformerHelper { * @see #setTransformerFactoryClass * @see #getTransformerFactory() */ - protected TransformerFactory newTransformerFactory(Class transformerFactoryClass) { + protected TransformerFactory newTransformerFactory( + @Nullable Class transformerFactoryClass) { if (transformerFactoryClass != null) { return TransformerFactoryUtils.newInstance(transformerFactoryClass); } diff --git a/spring-xml/src/main/java/org/springframework/xml/transform/TraxUtils.java b/spring-xml/src/main/java/org/springframework/xml/transform/TraxUtils.java index fd5f2bf5..dba4ef64 100644 --- a/spring-xml/src/main/java/org/springframework/xml/transform/TraxUtils.java +++ b/spring-xml/src/main/java/org/springframework/xml/transform/TraxUtils.java @@ -36,6 +36,7 @@ import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.ContentHandler; @@ -59,7 +60,7 @@ public abstract class TraxUtils { * @param source the DOM source * @return the document */ - public static Document getDocument(DOMSource source) { + public static @Nullable Document getDocument(DOMSource source) { Node node = source.getNode(); if (node instanceof Document) { return (Document) node; diff --git a/spring-xml/src/main/java/org/springframework/xml/transform/package-info.java b/spring-xml/src/main/java/org/springframework/xml/transform/package-info.java index b0233ae5..d723aae0 100644 --- a/spring-xml/src/main/java/org/springframework/xml/transform/package-info.java +++ b/spring-xml/src/main/java/org/springframework/xml/transform/package-info.java @@ -18,4 +18,7 @@ * Provides classes that help with XML transformations. Mostly for internal use by the * framework. */ +@NullMarked package org.springframework.xml.transform; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-xml/src/main/java/org/springframework/xml/validation/Jaxp13ValidatorFactory.java b/spring-xml/src/main/java/org/springframework/xml/validation/Jaxp13ValidatorFactory.java index aedf9320..9379c68f 100644 --- a/spring-xml/src/main/java/org/springframework/xml/validation/Jaxp13ValidatorFactory.java +++ b/spring-xml/src/main/java/org/springframework/xml/validation/Jaxp13ValidatorFactory.java @@ -24,6 +24,7 @@ import javax.xml.transform.Source; import javax.xml.validation.Schema; import javax.xml.validation.Validator; +import org.jspecify.annotations.Nullable; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; @@ -62,7 +63,8 @@ abstract class Jaxp13ValidatorFactory { } @Override - public SAXParseException[] validate(Source source, ValidationErrorHandler errorHandler) throws IOException { + public SAXParseException[] validate(Source source, @Nullable ValidationErrorHandler errorHandler) + throws IOException { if (errorHandler == null) { errorHandler = new DefaultValidationErrorHandler(); } diff --git a/spring-xml/src/main/java/org/springframework/xml/validation/Jaxp15ValidatorFactory.java b/spring-xml/src/main/java/org/springframework/xml/validation/Jaxp15ValidatorFactory.java index 29ffb2b1..fdcec4ce 100644 --- a/spring-xml/src/main/java/org/springframework/xml/validation/Jaxp15ValidatorFactory.java +++ b/spring-xml/src/main/java/org/springframework/xml/validation/Jaxp15ValidatorFactory.java @@ -27,6 +27,7 @@ import javax.xml.validation.Validator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; @@ -70,7 +71,8 @@ abstract class Jaxp15ValidatorFactory { } @Override - public SAXParseException[] validate(Source source, ValidationErrorHandler errorHandler) throws IOException { + public SAXParseException[] validate(Source source, @Nullable ValidationErrorHandler errorHandler) + throws IOException { if (errorHandler == null) { errorHandler = new DefaultValidationErrorHandler(); } diff --git a/spring-xml/src/main/java/org/springframework/xml/validation/SchemaLoaderUtils.java b/spring-xml/src/main/java/org/springframework/xml/validation/SchemaLoaderUtils.java index 1955bed7..b732e93d 100644 --- a/spring-xml/src/main/java/org/springframework/xml/validation/SchemaLoaderUtils.java +++ b/spring-xml/src/main/java/org/springframework/xml/validation/SchemaLoaderUtils.java @@ -22,6 +22,7 @@ import javax.xml.transform.Source; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; +import org.jspecify.annotations.Nullable; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; @@ -91,7 +92,7 @@ public abstract class SchemaLoaderUtils { * Retrieves the URL from the given resource as System ID. Returns {@code null} if it * cannot be opened. */ - public static String getSystemId(Resource resource) { + public static @Nullable String getSystemId(Resource resource) { try { return resource.getURL().toString(); } diff --git a/spring-xml/src/main/java/org/springframework/xml/validation/XmlValidator.java b/spring-xml/src/main/java/org/springframework/xml/validation/XmlValidator.java index 6ec5b07b..ce0531d2 100644 --- a/spring-xml/src/main/java/org/springframework/xml/validation/XmlValidator.java +++ b/spring-xml/src/main/java/org/springframework/xml/validation/XmlValidator.java @@ -20,6 +20,7 @@ import java.io.IOException; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; import org.xml.sax.SAXParseException; /** @@ -56,6 +57,6 @@ public interface XmlValidator { * @throws IOException if the {@code source} cannot be read * @throws XmlValidationException if the {@code source} cannot be validated */ - SAXParseException[] validate(Source source, ValidationErrorHandler errorHandler) throws IOException; + SAXParseException[] validate(Source source, @Nullable ValidationErrorHandler errorHandler) throws IOException; } diff --git a/spring-xml/src/main/java/org/springframework/xml/validation/package-info.java b/spring-xml/src/main/java/org/springframework/xml/validation/package-info.java index ea3da014..f6bfbd00 100644 --- a/spring-xml/src/main/java/org/springframework/xml/validation/package-info.java +++ b/spring-xml/src/main/java/org/springframework/xml/validation/package-info.java @@ -18,4 +18,7 @@ * Provides classes for XML validation in JAXP 1.0 and JAXP 1.3. Mostly for internal use * by the framework. */ +@NullMarked package org.springframework.xml.validation; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/AbstractXPathTemplate.java b/spring-xml/src/main/java/org/springframework/xml/xpath/AbstractXPathTemplate.java index 2146dd22..75d5c1a6 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/AbstractXPathTemplate.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/AbstractXPathTemplate.java @@ -16,12 +16,14 @@ package org.springframework.xml.xpath; +import java.util.Collections; import java.util.Map; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMResult; +import org.jspecify.annotations.Nullable; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -38,7 +40,7 @@ import org.springframework.xml.transform.TransformerObjectSupport; */ public abstract class AbstractXPathTemplate extends TransformerObjectSupport implements XPathOperations { - private Map namespaces; + private Map namespaces = Collections.emptyMap(); /** Returns namespaces used in the XPath expression. */ public Map getNamespaces() { @@ -81,7 +83,7 @@ public abstract class AbstractXPathTemplate extends TransformerObjectSupport imp } @Override - public Object mapNode(Node node, int nodeNum) throws DOMException { + public @Nullable Object mapNode(Node node, int nodeNum) throws DOMException { this.callbackHandler.processNode(node); return null; } diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/JaxenXPathExpressionFactory.java b/spring-xml/src/main/java/org/springframework/xml/xpath/JaxenXPathExpressionFactory.java index d2d1c344..a3983ec0 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/JaxenXPathExpressionFactory.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/JaxenXPathExpressionFactory.java @@ -24,6 +24,7 @@ import org.jaxen.JaxenException; import org.jaxen.SimpleNamespaceContext; import org.jaxen.XPath; import org.jaxen.dom.DOMXPath; +import org.jspecify.annotations.Nullable; import org.w3c.dom.DOMException; import org.w3c.dom.Node; @@ -92,7 +93,7 @@ abstract class JaxenXPathExpressionFactory { } @Override - public Node evaluateAsNode(Node node) { + public @Nullable Node evaluateAsNode(Node node) { try { return (Node) this.xpath.selectSingleNode(node); } @@ -125,7 +126,7 @@ abstract class JaxenXPathExpressionFactory { } @Override - public String evaluateAsString(Node node) { + public @Nullable String evaluateAsString(Node node) { try { return this.xpath.stringValueOf(node); } @@ -148,7 +149,7 @@ abstract class JaxenXPathExpressionFactory { } @Override - public T evaluateAsObject(Node context, NodeMapper nodeMapper) throws XPathException { + public @Nullable T evaluateAsObject(Node context, NodeMapper nodeMapper) throws XPathException { try { Node result = (Node) this.xpath.selectSingleNode(context); if (result != null) { diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/JaxenXPathTemplate.java b/spring-xml/src/main/java/org/springframework/xml/xpath/JaxenXPathTemplate.java index e9c13660..b9fceb45 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/JaxenXPathTemplate.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/JaxenXPathTemplate.java @@ -18,6 +18,7 @@ package org.springframework.xml.xpath; import java.util.ArrayList; import java.util.List; +import java.util.Map; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; @@ -26,6 +27,7 @@ import org.jaxen.JaxenException; import org.jaxen.SimpleNamespaceContext; import org.jaxen.XPath; import org.jaxen.dom.DOMXPath; +import org.jspecify.annotations.Nullable; import org.w3c.dom.DOMException; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -118,7 +120,8 @@ public class JaxenXPathTemplate extends AbstractXPathTemplate { } @Override - public T evaluateAsObject(String expression, Source context, NodeMapper nodeMapper) throws XPathException { + public @Nullable T evaluateAsObject(String expression, Source context, NodeMapper nodeMapper) + throws XPathException { try { XPath xpath = createXPath(expression); Element element = getRootElement(context); @@ -172,8 +175,9 @@ public class JaxenXPathTemplate extends AbstractXPathTemplate { private XPath createXPath(String expression) throws JaxenException { XPath xpath = new DOMXPath(expression); - if (getNamespaces() != null && !getNamespaces().isEmpty()) { - xpath.setNamespaceContext(new SimpleNamespaceContext(getNamespaces())); + Map namespaces = getNamespaces(); + if (!namespaces.isEmpty()) { + xpath.setNamespaceContext(new SimpleNamespaceContext(namespaces)); } return xpath; } diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/Jaxp13XPathExpressionFactory.java b/spring-xml/src/main/java/org/springframework/xml/xpath/Jaxp13XPathExpressionFactory.java index af0ee90c..f9b26210 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/Jaxp13XPathExpressionFactory.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/Jaxp13XPathExpressionFactory.java @@ -26,6 +26,7 @@ import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.jspecify.annotations.Nullable; import org.w3c.dom.DOMException; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -153,18 +154,13 @@ abstract class Jaxp13XPathExpressionFactory { } @Override - public T evaluateAsObject(Node node, NodeMapper nodeMapper) throws XPathException { + public @Nullable T evaluateAsObject(Node node, NodeMapper nodeMapper) throws XPathException { Node result = (Node) evaluate(node, XPathConstants.NODE); - if (result != null) { - try { - return nodeMapper.mapNode(result, 0); - } - catch (DOMException ex) { - throw new XPathException("Mapping resulted in DOMException", ex); - } + try { + return nodeMapper.mapNode(result, 0); } - else { - return null; + catch (DOMException ex) { + throw new XPathException("Mapping resulted in DOMException", ex); } } diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/Jaxp13XPathTemplate.java b/spring-xml/src/main/java/org/springframework/xml/xpath/Jaxp13XPathTemplate.java index 8299082a..46fa7f65 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/Jaxp13XPathTemplate.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/Jaxp13XPathTemplate.java @@ -20,6 +20,7 @@ import java.io.InputStream; import java.io.Reader; import java.util.ArrayList; import java.util.List; +import java.util.Map; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; @@ -34,6 +35,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import javax.xml.xpath.XPathFactoryConfigurationException; +import org.jspecify.annotations.Nullable; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -81,16 +83,18 @@ public class Jaxp13XPathTemplate extends AbstractXPathTemplate { } @Override - public Node evaluateAsNode(String expression, Source context) throws XPathException { + public @Nullable Node evaluateAsNode(String expression, Source context) throws XPathException { return (Node) evaluate(expression, context, XPathConstants.NODE); } @Override public List evaluateAsNodeList(String expression, Source context) throws XPathException { NodeList result = (NodeList) evaluate(expression, context, XPathConstants.NODESET); - List nodes = new ArrayList<>(result.getLength()); - for (int i = 0; i < result.getLength(); i++) { - nodes.add(result.item(i)); + List nodes = new ArrayList<>(); + if (result != null) { + for (int i = 0; i < result.getLength(); i++) { + nodes.add(result.item(i)); + } } return nodes; } @@ -102,46 +106,45 @@ public class Jaxp13XPathTemplate extends AbstractXPathTemplate { } @Override - public String evaluateAsString(String expression, Source context) throws XPathException { + public @Nullable String evaluateAsString(String expression, Source context) throws XPathException { return (String) evaluate(expression, context, XPathConstants.STRING); } @Override - public T evaluateAsObject(String expression, Source context, NodeMapper nodeMapper) throws XPathException { + public @Nullable T evaluateAsObject(String expression, Source context, NodeMapper nodeMapper) + throws XPathException { Node node = evaluateAsNode(expression, context); - if (node != null) { - try { - return nodeMapper.mapNode(node, 0); - } - catch (DOMException ex) { - throw new XPathException("Mapping resulted in DOMException", ex); - } + try { + return (node != null) ? nodeMapper.mapNode(node, 0) : null; } - else { - return null; + catch (DOMException ex) { + throw new XPathException("Mapping resulted in DOMException", ex); } } @Override public List evaluate(String expression, Source context, NodeMapper nodeMapper) throws XPathException { NodeList nodes = (NodeList) evaluate(expression, context, XPathConstants.NODESET); - List results = new ArrayList<>(nodes.getLength()); - for (int i = 0; i < nodes.getLength(); i++) { - try { - results.add(nodeMapper.mapNode(nodes.item(i), i)); - } - catch (DOMException ex) { - throw new XPathException("Mapping resulted in DOMException", ex); + List results = new ArrayList<>(); + if (nodes != null) { + for (int i = 0; i < nodes.getLength(); i++) { + try { + results.add(nodeMapper.mapNode(nodes.item(i), i)); + } + catch (DOMException ex) { + throw new XPathException("Mapping resulted in DOMException", ex); + } } } return results; } - private Object evaluate(String expression, Source context, QName returnType) throws XPathException { + private @Nullable Object evaluate(String expression, Source context, QName returnType) throws XPathException { XPath xpath = createXPath(); - if (getNamespaces() != null && !getNamespaces().isEmpty()) { + Map namespaces = getNamespaces(); + if (!namespaces.isEmpty()) { SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext(); - namespaceContext.setBindings(getNamespaces()); + namespaceContext.setBindings(namespaces); xpath.setNamespaceContext(namespaceContext); } try { @@ -174,7 +177,7 @@ public class Jaxp13XPathTemplate extends AbstractXPathTemplate { private final TransformerHelper transformerHelper = new TransformerHelper(); - private Object result; + private @Nullable Object result; private EvaluationCallback(XPath xpath, String expression, QName returnType) { this.xpath = xpath; diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/NodeMapper.java b/spring-xml/src/main/java/org/springframework/xml/xpath/NodeMapper.java index 46d01369..4a56864e 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/NodeMapper.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/NodeMapper.java @@ -16,6 +16,7 @@ package org.springframework.xml.xpath; +import org.jspecify.annotations.Nullable; import org.w3c.dom.DOMException; import org.w3c.dom.Node; @@ -42,6 +43,6 @@ public interface NodeMapper { * @return object for the current node * @throws DOMException in case of DOM errors */ - T mapNode(Node node, int nodeNum) throws DOMException; + @Nullable T mapNode(Node node, int nodeNum) throws DOMException; } diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/XPathException.java b/spring-xml/src/main/java/org/springframework/xml/xpath/XPathException.java index c9e45a4c..e71d03b5 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/XPathException.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/XPathException.java @@ -16,6 +16,8 @@ package org.springframework.xml.xpath; +import org.jspecify.annotations.Nullable; + import org.springframework.xml.XmlException; /** @@ -42,7 +44,7 @@ public class XPathException extends XmlException { * @param message the detail message * @param throwable the wrapped exception */ - public XPathException(String message, Throwable throwable) { + public XPathException(@Nullable String message, Throwable throwable) { super(message, throwable); } diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpression.java b/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpression.java index cd4babfa..61f199f5 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpression.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpression.java @@ -18,6 +18,7 @@ package org.springframework.xml.xpath; import java.util.List; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Node; /** @@ -58,7 +59,7 @@ public interface XPathExpression { * @throws XPathException in case of XPath errors * @see XPath specification */ - Node evaluateAsNode(Node node) throws XPathException; + @Nullable Node evaluateAsNode(Node node) throws XPathException; /** * Evaluates the given expression, and returns all {@link Node} objects that conform @@ -98,7 +99,7 @@ public interface XPathExpression { * @see XPath specification - * string() function */ - String evaluateAsString(Node node) throws XPathException; + @Nullable String evaluateAsString(Node node) throws XPathException; /** * Evaluates the given expression, mapping a single {@link Node} result to a Java @@ -109,7 +110,7 @@ public interface XPathExpression { * @throws XPathException in case of XPath errors * @see XPath specification */ - T evaluateAsObject(Node node, NodeMapper nodeMapper) throws XPathException; + @Nullable T evaluateAsObject(Node node, NodeMapper nodeMapper) throws XPathException; /** * Evaluates the given expression, mapping each result {@link Node} objects to a Java diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpressionFactory.java b/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpressionFactory.java index 45c67420..ff2737a1 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpressionFactory.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpressionFactory.java @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; @@ -61,7 +62,7 @@ public abstract class XPathExpressionFactory { * @throws IllegalStateException if neither JAXP 1.3+, or Jaxen are available * @throws XPathParseException if the given expression cannot be parsed */ - public static XPathExpression createXPathExpression(String expression, Map namespaces) + public static XPathExpression createXPathExpression(String expression, @Nullable Map namespaces) throws IllegalStateException, XPathParseException { Assert.hasLength(expression, "expression is empty"); if (namespaces == null) { diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpressionFactoryBean.java b/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpressionFactoryBean.java index cf0f04eb..c407e0c2 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpressionFactoryBean.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/XPathExpressionFactoryBean.java @@ -36,10 +36,13 @@ import org.springframework.util.CollectionUtils; */ public class XPathExpressionFactoryBean implements FactoryBean, InitializingBean { + @SuppressWarnings("NullAway.Init") private Map namespaces; + @SuppressWarnings("NullAway.Init") private String expressionString; + @SuppressWarnings("NullAway.Init") private XPathExpression expression; /** Sets the XPath expression. Setting this property is required. */ diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/XPathOperations.java b/spring-xml/src/main/java/org/springframework/xml/xpath/XPathOperations.java index fec2f066..f6640a7b 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/XPathOperations.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/XPathOperations.java @@ -20,6 +20,7 @@ import java.util.List; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Node; /** @@ -65,7 +66,7 @@ public interface XPathOperations { * @throws XPathException in case of XPath errors * @see XPath specification */ - Node evaluateAsNode(String expression, Source context) throws XPathException; + @Nullable Node evaluateAsNode(String expression, Source context) throws XPathException; /** * Evaluates the given expression as a list of {@link Node} objects. Returns the @@ -108,7 +109,7 @@ public interface XPathOperations { * @see XPath specification - * string() function */ - String evaluateAsString(String expression, Source context) throws XPathException; + @Nullable String evaluateAsString(String expression, Source context) throws XPathException; /** * Evaluates the given expression, mapping a single {@link Node} result to a Java @@ -120,7 +121,7 @@ public interface XPathOperations { * @throws XPathException in case of XPath errors * @see XPath specification */ - T evaluateAsObject(String expression, Source context, NodeMapper nodeMapper) throws XPathException; + @Nullable T evaluateAsObject(String expression, Source context, NodeMapper nodeMapper) throws XPathException; /** * Evaluates the given expression, mapping each result {@link Node} objects to a Java diff --git a/spring-xml/src/main/java/org/springframework/xml/xpath/package-info.java b/spring-xml/src/main/java/org/springframework/xml/xpath/package-info.java index 8114c57d..a1578538 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xpath/package-info.java +++ b/spring-xml/src/main/java/org/springframework/xml/xpath/package-info.java @@ -18,4 +18,7 @@ * Provides XPathTemplate implementations, and various classes for XPath evaluation using * JAXP 1.3, and Jaxen. */ +@NullMarked package org.springframework.xml.xpath; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java b/spring-xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java index 62b46cc7..ebad670e 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java +++ b/spring-xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java @@ -24,6 +24,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.SAXException; @@ -56,9 +57,9 @@ public class SimpleXsdSchema implements XsdSchema, InitializingBean { private static final QName SCHEMA_NAME = new QName(SCHEMA_NAMESPACE, "schema", "xsd"); - private Resource xsdResource; + private @Nullable Resource xsdResource; - private String targetNamespace; + private @Nullable String targetNamespace; static { documentBuilderFactory.setNamespaceAware(true); @@ -127,20 +128,21 @@ public class SimpleXsdSchema implements XsdSchema, InitializingBean { Assert.notNull(this.xsdResource, "'xsd' is required"); Assert.isTrue(this.xsdResource.exists(), "xsd '" + this.xsdResource + "' does not exist"); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); - loadSchema(documentBuilder); + this.targetNamespace = loadSchema(documentBuilder, this.xsdResource); } - private void loadSchema(DocumentBuilder documentBuilder) throws SAXException, IOException { - Document schemaDocument = documentBuilder.parse(SaxUtils.createInputSource(this.xsdResource)); + private static String loadSchema(DocumentBuilder documentBuilder, Resource resource) + throws SAXException, IOException { + Document schemaDocument = documentBuilder.parse(SaxUtils.createInputSource(resource)); Element schemaElement = schemaDocument.getDocumentElement(); - Assert.isTrue(SCHEMA_NAME.getLocalPart().equals(schemaElement.getLocalName()), this.xsdResource - + " has invalid root element : [" + schemaElement.getLocalName() + "] instead of [schema]"); + Assert.isTrue(SCHEMA_NAME.getLocalPart().equals(schemaElement.getLocalName()), + resource + " has invalid root element : [" + schemaElement.getLocalName() + "] instead of [schema]"); Assert.isTrue(SCHEMA_NAME.getNamespaceURI().equals(schemaElement.getNamespaceURI()), - this.xsdResource + " has invalid root element: [" + schemaElement.getNamespaceURI() + "] instead of [" + resource + " has invalid root element: [" + schemaElement.getNamespaceURI() + "] instead of [" + SCHEMA_NAME.getNamespaceURI() + "]"); String targetNamespace = schemaElement.getAttribute("targetNamespace"); - Assert.hasText(targetNamespace, this.xsdResource + " has no targetNamespace"); - this.targetNamespace = targetNamespace; + Assert.hasText(targetNamespace, resource + " has no targetNamespace"); + return targetNamespace; } public String toString() { diff --git a/spring-xml/src/main/java/org/springframework/xml/xsd/XsdSchemaException.java b/spring-xml/src/main/java/org/springframework/xml/xsd/XsdSchemaException.java index 082bee79..71f14999 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xsd/XsdSchemaException.java +++ b/spring-xml/src/main/java/org/springframework/xml/xsd/XsdSchemaException.java @@ -16,6 +16,8 @@ package org.springframework.xml.xsd; +import org.jspecify.annotations.Nullable; + import org.springframework.xml.XmlException; /** @@ -32,7 +34,7 @@ public class XsdSchemaException extends XmlException { super(message); } - public XsdSchemaException(String message, Throwable throwable) { + public XsdSchemaException(@Nullable String message, Throwable throwable) { super(message, throwable); } diff --git a/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java b/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java index f669a814..2ea926dc 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java +++ b/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java @@ -31,6 +31,7 @@ import javax.xml.transform.stream.StreamSource; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaCollection; import org.apache.ws.commons.schema.XmlSchemaSerializer; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.springframework.beans.BeanInstantiationException; @@ -54,7 +55,7 @@ public class CommonsXsdSchema implements XsdSchema { private final XmlSchema schema; - private final XmlSchemaCollection collection; + private final @Nullable XmlSchemaCollection collection; /** * Create a new instance of the {@code CommonsXsdSchema} class with the specified @@ -74,7 +75,7 @@ public class CommonsXsdSchema implements XsdSchema { * {@code null} * @throws IllegalArgumentException if the supplied {@code schema} is {@code null} */ - protected CommonsXsdSchema(XmlSchema schema, XmlSchemaCollection collection) { + protected CommonsXsdSchema(XmlSchema schema, @Nullable XmlSchemaCollection collection) { Assert.notNull(schema, "'schema' must not be null"); this.schema = schema; this.collection = collection; diff --git a/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollection.java b/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollection.java index 3f06c499..7cd18263 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollection.java +++ b/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollection.java @@ -32,6 +32,7 @@ import org.apache.ws.commons.schema.XmlSchemaInclude; import org.apache.ws.commons.schema.XmlSchemaObject; import org.apache.ws.commons.schema.resolver.DefaultURIResolver; import org.apache.ws.commons.schema.resolver.URIResolver; +import org.jspecify.annotations.Nullable; import org.xml.sax.InputSource; import org.springframework.beans.factory.InitializingBean; @@ -74,7 +75,7 @@ public class CommonsXsdSchemaCollection implements XsdSchemaCollection, Initiali private URIResolver uriResolver = new ClasspathUriResolver(); - private ResourceLoader resourceLoader; + private @Nullable ResourceLoader resourceLoader; /** * Constructs a new, empty instance of the {@code CommonsXsdSchemaCollection}. @@ -82,6 +83,7 @@ public class CommonsXsdSchemaCollection implements XsdSchemaCollection, Initiali * A subsequent call to the {@link #setXsds(Resource[])} is required. */ public CommonsXsdSchemaCollection() { + this(new Resource[0]); } /** diff --git a/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaException.java b/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaException.java index 6bcaf14d..35449cde 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaException.java +++ b/spring-xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaException.java @@ -16,6 +16,8 @@ package org.springframework.xml.xsd.commons; +import org.jspecify.annotations.Nullable; + import org.springframework.xml.xsd.XsdSchemaException; /** @@ -31,7 +33,7 @@ public class CommonsXsdSchemaException extends XsdSchemaException { super(message); } - public CommonsXsdSchemaException(String message, Throwable exception) { + public CommonsXsdSchemaException(@Nullable String message, Throwable exception) { super(message, exception); } diff --git a/spring-xml/src/main/java/org/springframework/xml/xsd/commons/package-info.java b/spring-xml/src/main/java/org/springframework/xml/xsd/commons/package-info.java index a126cf07..aa579869 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xsd/commons/package-info.java +++ b/spring-xml/src/main/java/org/springframework/xml/xsd/commons/package-info.java @@ -18,4 +18,7 @@ * Contains a implementation of the {@code XsdSchema} interfaces that uses Apache * WS-Commons XML Schema. */ +@NullMarked package org.springframework.xml.xsd.commons; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-xml/src/main/java/org/springframework/xml/xsd/package-info.java b/spring-xml/src/main/java/org/springframework/xml/xsd/package-info.java index 91cfca19..01352650 100644 --- a/spring-xml/src/main/java/org/springframework/xml/xsd/package-info.java +++ b/spring-xml/src/main/java/org/springframework/xml/xsd/package-info.java @@ -18,4 +18,7 @@ * Provides an abstraction over XSD XML schemas. Contains the {@code XsdSchema} and * related interfaces. */ +@NullMarked package org.springframework.xml.xsd; + +import org.jspecify.annotations.NullMarked;