From ef2697e8b6905186034accec139e1c1a02263039 Mon Sep 17 00:00:00 2001 From: Romain Deltour Date: Wed, 7 Dec 2022 01:36:27 +0100 Subject: [PATCH] feat: update Saxon library to v11.4 This commit updates the Saxon-HE dependency to version 11.4. It refactors the Saxon-related code as follows: - update the function+registration code to the latest API changes - extract the Saxon schema reader factory (used by Jing) in its own class - the Saxon schema reader factory is made available to Jing via the SPI mechanism (declared in `META-INF/services/com.thaiopensource.validate.SchemaReaderFactory`). This notably allows Jing to find and use our factory for both Schematron and NVDL. - the Saxon schema reader factory no longer extends Jing's `NewSaxonSchemaReaderFactory`, which set the feature "XSLT_VERSION" to "2.0" and caused a Warning to be issued by Saxon 11. Fix #1341 --- pom.xml | 6 +- .../com/adobe/epubcheck/xml/XMLValidator.java | 106 +++++------------- .../util/saxon/ColumnNumberFunction.java | 6 +- .../util/saxon/Int64ValueSequence.java | 4 +- .../util/saxon/LineNumberFunction.java | 6 +- .../util/saxon/SaxonSchemaReaderFactory.java | 55 +++++++++ .../util/saxon/SystemIdFunction.java | 11 +- ...haiopensource.validate.SchemaReaderFactory | 1 + 8 files changed, 91 insertions(+), 104 deletions(-) create mode 100644 src/main/java/org/idpf/epubcheck/util/saxon/SaxonSchemaReaderFactory.java create mode 100644 src/main/resources/META-INF/services/com.thaiopensource.validate.SchemaReaderFactory diff --git a/pom.xml b/pom.xml index b88fb9f65..817a65547 100644 --- a/pom.xml +++ b/pom.xml @@ -178,7 +178,7 @@ net.sf.saxon Saxon-HE - 9.8.0-8 + 11.4 nu.validator @@ -368,7 +368,7 @@ - net.sf.saxon.*;version="[9.8.0,9.8.1)", + net.sf.saxon.*;version="[11.4.0,11.4.1)", * org.w3c.epubcheck @@ -444,7 +444,7 @@ net.sf.saxon Saxon-HE - 9.4 + 11.4 diff --git a/src/main/java/com/adobe/epubcheck/xml/XMLValidator.java b/src/main/java/com/adobe/epubcheck/xml/XMLValidator.java index b3de45318..9277017bd 100755 --- a/src/main/java/com/adobe/epubcheck/xml/XMLValidator.java +++ b/src/main/java/com/adobe/epubcheck/xml/XMLValidator.java @@ -28,11 +28,6 @@ import java.net.URISyntaxException; import java.net.URL; -import javax.xml.transform.TransformerFactory; - -import org.idpf.epubcheck.util.saxon.ColumnNumberFunction; -import org.idpf.epubcheck.util.saxon.LineNumberFunction; -import org.idpf.epubcheck.util.saxon.SystemIdFunction; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -48,16 +43,7 @@ import com.thaiopensource.validate.SchemaReader; import com.thaiopensource.validate.ValidateProperty; import com.thaiopensource.validate.auto.AutoSchemaReader; -import com.thaiopensource.validate.auto.SchemaReaderFactorySchemaReceiverFactory; import com.thaiopensource.validate.rng.CompactSchemaReader; -import com.thaiopensource.validate.schematron.NewSaxonSchemaReaderFactory; - -import net.sf.saxon.Configuration; -import net.sf.saxon.TransformerFactoryImpl; -import net.sf.saxon.sxpath.IndependentContext; -import net.sf.saxon.sxpath.XPathStaticContext; -import net.sf.saxon.trans.SymbolicName; - public class XMLValidator { @@ -84,9 +70,9 @@ public static BasicResolver getInstance() return theInstance; } - public void resolve(Identifier id, Input input) throws - IOException, - ResolverException + public void resolve(Identifier id, Input input) + throws IOException, + ResolverException { if (!input.isResolved()) { @@ -94,9 +80,9 @@ public void resolve(Identifier id, Input input) throws } } - public void open(Input input) throws - IOException, - ResolverException + public void open(Input input) + throws IOException, + ResolverException { if (!input.isUriDefinitive()) { @@ -106,8 +92,7 @@ public void open(Input input) throws try { uri = new URI(input.getUri()); - } - catch (URISyntaxException e) + } catch (URISyntaxException e) { throw new ResolverException(e); } @@ -122,8 +107,8 @@ public void open(Input input) throws input.setByteStream(url.openStream()); } - public static String resolveUri(Identifier id) throws - ResolverException + public static String resolveUri(Identifier id) + throws ResolverException { try { @@ -153,74 +138,40 @@ public static String resolveUri(Identifier id) throws } return uriRef; - } - catch (URISyntaxException e) + } catch (URISyntaxException e) { throw new ResolverException(e); - } - catch (MalformedURLException e) + } catch (MalformedURLException e) { throw new ResolverException(e); } } } - /** - * Extends Jing's Saxon 9 schema reader factory by registering - * extension functions. - */ - static public class ExtendedSaxonSchemaReaderFactory extends NewSaxonSchemaReaderFactory - { - public void initTransformerFactory(TransformerFactory factory) - { - super.initTransformerFactory(factory); - SymbolicName.F lineNumberFn = new SymbolicName.F(LineNumberFunction.QNAME, 0); - SymbolicName.F columnNumberFn = new SymbolicName.F(ColumnNumberFunction.QNAME, 0); - SymbolicName.F systemIdFn = new SymbolicName.F(SystemIdFunction.QNAME, 0); - if (factory instanceof TransformerFactoryImpl) - { - Configuration configuration = ((TransformerFactoryImpl) factory).getConfiguration(); - XPathStaticContext xpathContext = new IndependentContext(configuration); - if (!xpathContext.getFunctionLibrary().isAvailable(lineNumberFn)) - { - configuration.registerExtensionFunction(new LineNumberFunction()); - } - if (!xpathContext.getFunctionLibrary().isAvailable(columnNumberFn)) - { - configuration.registerExtensionFunction(new ColumnNumberFunction()); - } - if (!xpathContext.getFunctionLibrary().isAvailable(systemIdFn)) - { - configuration.registerExtensionFunction(new SystemIdFunction()); - } - } - } - } - // handles errors in schemas private class ErrorHandlerImpl implements ErrorHandler { - public void error(SAXParseException exception) throws - SAXException + public void error(SAXParseException exception) + throws SAXException { exception.printStackTrace(); } - public void fatalError(SAXParseException exception) throws - SAXException + public void fatalError(SAXParseException exception) + throws SAXException { exception.printStackTrace(); } - public void warning(SAXParseException exception) throws - SAXException + public void warning(SAXParseException exception) + throws SAXException { exception.printStackTrace(); } } - + public XMLValidator(String schemaName, boolean isNormative) { this.isNormative = isNormative; @@ -245,36 +196,31 @@ public XMLValidator(String schemaName, boolean isNormative) if (schemaName.endsWith(".rnc")) { schemaReader = CompactSchemaReader.getInstance(); - } else if (schemaName.endsWith(".sch")) { - schemaReader = new AutoSchemaReader( - new SchemaReaderFactorySchemaReceiverFactory( - new ExtendedSaxonSchemaReaderFactory())); } else { - schemaReader = new AutoSchemaReader(); } schema = schemaReader.createSchema(schemaSource, mapBuilder.toPropertyMap()); - } - catch (RuntimeException e) + } catch (RuntimeException e) { throw e; - } - catch (Exception e) + } catch (Exception e) { e.printStackTrace(); throw new Error("Internal error: " + e + " " + schemaName); } } - - public Schema getSchema() { + + public Schema getSchema() + { return schema; } - - public boolean isNormative() { + + public boolean isNormative() + { return isNormative; } } diff --git a/src/main/java/org/idpf/epubcheck/util/saxon/ColumnNumberFunction.java b/src/main/java/org/idpf/epubcheck/util/saxon/ColumnNumberFunction.java index dd6527721..152a02a9a 100644 --- a/src/main/java/org/idpf/epubcheck/util/saxon/ColumnNumberFunction.java +++ b/src/main/java/org/idpf/epubcheck/util/saxon/ColumnNumberFunction.java @@ -13,8 +13,6 @@ public class ColumnNumberFunction extends ExtensionFunctionDefinition { - private static final long serialVersionUID = -4202710868367933385L; - public static StructuredQName QNAME = new StructuredQName("saxon", "http://saxon.sf.net/", "column-number"); @Override @@ -64,9 +62,7 @@ public ExtensionFunctionCall makeCallExpression() { return new ExtensionFunctionCall() { - private static final long serialVersionUID = -4202710868367933385L; - - public Sequence call(XPathContext context, @SuppressWarnings("rawtypes") Sequence[] arguments) throws XPathException + public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { if (context.getContextItem() instanceof NodeInfo) { diff --git a/src/main/java/org/idpf/epubcheck/util/saxon/Int64ValueSequence.java b/src/main/java/org/idpf/epubcheck/util/saxon/Int64ValueSequence.java index 498f79ff4..4e73e3833 100644 --- a/src/main/java/org/idpf/epubcheck/util/saxon/Int64ValueSequence.java +++ b/src/main/java/org/idpf/epubcheck/util/saxon/Int64ValueSequence.java @@ -3,7 +3,6 @@ import net.sf.saxon.om.Item; import net.sf.saxon.om.Sequence; import net.sf.saxon.om.SequenceIterator; -import net.sf.saxon.trans.XPathException; import net.sf.saxon.value.Int64Value; class Int64ValueSequence implements Sequence @@ -21,8 +20,7 @@ public Item head() } @Override - public SequenceIterator iterate() throws - XPathException + public SequenceIterator iterate() { return item.iterate(); } diff --git a/src/main/java/org/idpf/epubcheck/util/saxon/LineNumberFunction.java b/src/main/java/org/idpf/epubcheck/util/saxon/LineNumberFunction.java index 9e7e82f63..98f948188 100644 --- a/src/main/java/org/idpf/epubcheck/util/saxon/LineNumberFunction.java +++ b/src/main/java/org/idpf/epubcheck/util/saxon/LineNumberFunction.java @@ -13,8 +13,6 @@ public class LineNumberFunction extends ExtensionFunctionDefinition { - private static final long serialVersionUID = -4202710868367933385L; - public static StructuredQName QNAME = new StructuredQName("saxon", "http://saxon.sf.net/", "line-number"); @Override @@ -65,9 +63,7 @@ public ExtensionFunctionCall makeCallExpression() return new ExtensionFunctionCall() { - private static final long serialVersionUID = -4202710868367933385L; - - public Sequence call(XPathContext context, @SuppressWarnings("rawtypes") Sequence[] arguments) throws XPathException + public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { if (context.getContextItem() instanceof NodeInfo) { diff --git a/src/main/java/org/idpf/epubcheck/util/saxon/SaxonSchemaReaderFactory.java b/src/main/java/org/idpf/epubcheck/util/saxon/SaxonSchemaReaderFactory.java new file mode 100644 index 000000000..878d8d0b7 --- /dev/null +++ b/src/main/java/org/idpf/epubcheck/util/saxon/SaxonSchemaReaderFactory.java @@ -0,0 +1,55 @@ +package org.idpf.epubcheck.util.saxon; + +import javax.xml.transform.TransformerFactory; + +import com.thaiopensource.validate.schematron.SchematronSchemaReaderFactory; + +import net.sf.saxon.Configuration; +import net.sf.saxon.TransformerFactoryImpl; +import net.sf.saxon.lib.ErrorReporter; +import net.sf.saxon.lib.FeatureKeys; +import net.sf.saxon.s9api.XmlProcessingError; +import net.sf.saxon.sxpath.IndependentContext; +import net.sf.saxon.sxpath.XPathStaticContext; +import net.sf.saxon.trans.SymbolicName; + +public class SaxonSchemaReaderFactory extends SchematronSchemaReaderFactory +{ + public void initTransformerFactory(TransformerFactory factory) + { + super.initTransformerFactory(factory); + factory.setAttribute(FeatureKeys.LINE_NUMBERING, Boolean.TRUE); + SymbolicName.F lineNumberFn = new SymbolicName.F(LineNumberFunction.QNAME, 0); + SymbolicName.F columnNumberFn = new SymbolicName.F(ColumnNumberFunction.QNAME, 0); + SymbolicName.F systemIdFn = new SymbolicName.F(SystemIdFunction.QNAME, 0); + if (factory instanceof TransformerFactoryImpl) + { + Configuration configuration = ((TransformerFactoryImpl) factory).getConfiguration(); + configuration.setErrorReporterFactory(config -> { + return new ErrorReporter() + { + + @Override + public void report(XmlProcessingError error) + { + System.out.println(error.getMessage()); + + } + }; + }); + XPathStaticContext xpathContext = new IndependentContext(configuration); + if (!xpathContext.getFunctionLibrary().isAvailable(lineNumberFn, 20)) + { + configuration.registerExtensionFunction(new LineNumberFunction()); + } + if (!xpathContext.getFunctionLibrary().isAvailable(columnNumberFn, 20)) + { + configuration.registerExtensionFunction(new ColumnNumberFunction()); + } + if (!xpathContext.getFunctionLibrary().isAvailable(systemIdFn, 20)) + { + configuration.registerExtensionFunction(new SystemIdFunction()); + } + } + } +} diff --git a/src/main/java/org/idpf/epubcheck/util/saxon/SystemIdFunction.java b/src/main/java/org/idpf/epubcheck/util/saxon/SystemIdFunction.java index 2a28fc07c..49ba278cf 100644 --- a/src/main/java/org/idpf/epubcheck/util/saxon/SystemIdFunction.java +++ b/src/main/java/org/idpf/epubcheck/util/saxon/SystemIdFunction.java @@ -5,8 +5,8 @@ import net.sf.saxon.lib.ExtensionFunctionDefinition; import net.sf.saxon.om.Item; import net.sf.saxon.om.NodeInfo; -import net.sf.saxon.om.SequenceIterator; import net.sf.saxon.om.Sequence; +import net.sf.saxon.om.SequenceIterator; import net.sf.saxon.om.StructuredQName; import net.sf.saxon.trans.XPathException; import net.sf.saxon.value.AnyURIValue; @@ -15,8 +15,6 @@ public class SystemIdFunction extends ExtensionFunctionDefinition { - private static final long serialVersionUID = -4202710868367933385L; - public static StructuredQName QNAME = new StructuredQName("saxon", "http://saxon.sf.net/", "system-id"); @Override @@ -66,9 +64,7 @@ public ExtensionFunctionCall makeCallExpression() { return new ExtensionFunctionCall() { - private static final long serialVersionUID = -4202710868367933385L; - - public Sequence call(XPathContext context, @SuppressWarnings("rawtypes") Sequence[] arguments) throws XPathException + public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { if (context.getContextItem() instanceof NodeInfo) { @@ -94,8 +90,7 @@ public Item head() } @Override - public SequenceIterator iterate() throws - XPathException + public SequenceIterator iterate() { return item.iterate(); } diff --git a/src/main/resources/META-INF/services/com.thaiopensource.validate.SchemaReaderFactory b/src/main/resources/META-INF/services/com.thaiopensource.validate.SchemaReaderFactory new file mode 100644 index 000000000..3e52230fd --- /dev/null +++ b/src/main/resources/META-INF/services/com.thaiopensource.validate.SchemaReaderFactory @@ -0,0 +1 @@ +org.idpf.epubcheck.util.saxon.SaxonSchemaReaderFactory \ No newline at end of file