Skip to content

Commit

Permalink
Merge pull request #75 from philippn/feature/saxon11-compat
Browse files Browse the repository at this point in the history
Fix compatibility with Saxon 11 and 12
  • Loading branch information
cmarchand authored Feb 19, 2024
2 parents ff6c20b + 5f39029 commit 6e0c050
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright © 2023, Philipp Nanz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package io.xspec.maven.xspecMavenPlugin.resolver;

import net.sf.saxon.s9api.XsltCompiler;
import org.apache.maven.plugin.logging.Log;

import java.io.File;

public interface ResolverDecorator {

void decorate(final XsltCompiler compiler, final File catalog, final Log log);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright © 2023, Philipp Nanz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package io.xspec.maven.xspecMavenPlugin.resolver;

import net.sf.saxon.s9api.Processor;

public class ResolverDecoratorProvider {

private ResolverDecorator resolverDecorator;

public ResolverDecorator getDecorator(Processor processor) {
if (resolverDecorator == null) {
// String version = processor.getSaxonProductVersion();
// if (version.startsWith("9.")) {
// resolverDecorator = new ResolverDecoratorS9();
// } else {
// resolverDecorator = new ResolverDecoratorS11();
// }
resolverDecorator = new ResolverDecoratorS9();
}
return resolverDecorator;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Copyright © 2023, Philipp Nanz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package io.xspec.maven.xspecMavenPlugin.resolver;

import net.sf.saxon.lib.StandardURIResolver;
import net.sf.saxon.s9api.XsltCompiler;
import org.apache.maven.plugin.logging.Log;

import javax.xml.transform.URIResolver;
import java.io.File;

public class ResolverDecoratorS9 implements ResolverDecorator {
@Override
public void decorate(final XsltCompiler compiler, final File catalog, final Log log) {
URIResolver saxonResolver = compiler.getURIResolver();
if (saxonResolver == null) {
saxonResolver = new StandardURIResolver();
}
compiler.setURIResolver(new ResolverS9(saxonResolver, catalog, log));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
* Saxon URI Resolver should never be used.
* @author cmarchand
*/
public class Resolver implements javax.xml.transform.URIResolver, EntityResolver {
public class ResolverS9 implements javax.xml.transform.URIResolver, EntityResolver {
private final URIResolver saxonResolver;
private final Log log;
org.xmlresolver.Resolver cr;
Expand All @@ -63,7 +63,7 @@ public class Resolver implements javax.xml.transform.URIResolver, EntityResolver
* @param catalog
* @param log
*/
public Resolver(final URIResolver saxonResolver, final File catalog, final Log log) {
public ResolverS9(final URIResolver saxonResolver, final File catalog, final Log log) {
super();
this.saxonResolver=saxonResolver;
this.log=log;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
*/
package io.xspec.maven.xspecMavenPlugin.utils;

import io.xspec.maven.xspecMavenPlugin.resolver.Resolver;
import io.xspec.maven.xspecMavenPlugin.resolver.ResolverDecorator;
import io.xspec.maven.xspecMavenPlugin.resolver.ResolverDecoratorProvider;
import io.xspec.maven.xspecMavenPlugin.resources.SchematronImplResources;
import io.xspec.maven.xspecMavenPlugin.resources.XSpecImplResources;
import io.xspec.maven.xspecMavenPlugin.resources.XSpecPluginResources;
Expand Down Expand Up @@ -64,6 +65,7 @@ public class XmlStuff {
private final XsltCompiler xsltCompiler;
private final XQueryCompiler xqueryCompiler;
private final XPathCompiler xpathCompiler;
private final ResolverDecorator resolverDecorator;

private XsltExecutable xspec4xsltCompiler;
private XsltExecutable xspec4xqueryCompiler;
Expand Down Expand Up @@ -122,6 +124,7 @@ public XmlStuff(
throw new XSpecPluginException("Illegal value in Saxon configuration property", ex);
}
}
resolverDecorator = new ResolverDecoratorProvider().getDecorator(processor);
documentBuilder = processor.newDocumentBuilder();
try {
xsltCompiler = processor.newXsltCompiler();
Expand All @@ -136,7 +139,7 @@ public XmlStuff(
throw new XSpecPluginException(ex);
}
try {
xsltCompiler.setURIResolver(buildUriResolver(xsltCompiler.getURIResolver()));
decorateXsltCompiler();
} catch(IOException ex) {
throw new XSpecPluginException("while constructing URIResolver", ex);
}
Expand Down Expand Up @@ -207,22 +210,20 @@ private void registerSaxonExtension(String className) {
}

/**
* Creates the URI Resolver. It also generates the catalog with all
* Decorates the XsltCompiler with a custom resolver. It also generates the catalog with all
* dependencies
* @param saxonUriResolver
* @return
* @throws IOException
* @throws XSpecPluginException
*/
private URIResolver buildUriResolver(final URIResolver saxonUriResolver) throws IOException, XSpecPluginException {
private void decorateXsltCompiler() throws IOException, XSpecPluginException {
getLog().debug("buildUriResolver");
CatalogWriter cw = new CatalogWriter(this.getClass().getClassLoader());
getLog().debug("CatalogWriter instanciated");
File catalog = cw.writeCatalog(options.catalogFile, executionProperties, options.keepGeneratedCatalog);
if(options.keepGeneratedCatalog) {
getLog().info("keeping generated catalog: "+catalog.toURI().toURL().toExternalForm());
}
return new Resolver(saxonUriResolver, catalog, getLog());
resolverDecorator.decorate(xsltCompiler, catalog, getLog());
}

private void createXPathExecutables() throws SaxonApiException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
*/
package io.xspec.maven.xspecMavenPlugin.resolver;

import net.sf.saxon.Configuration;
import net.sf.saxon.lib.StandardURIResolver;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugin.logging.SystemStreamLog;
import org.assertj.core.api.SoftAssertions;
Expand All @@ -49,30 +49,27 @@
* Tests Resolver class
* @author cmarchand
*/
public class ResolverTest {
public class ResolverS9Test {

private Configuration configuration;
private URIResolver saxonResolver;
private Log log = new SystemStreamLog();

@Before
public void before() {
configuration = Configuration.newConfiguration();
saxonResolver = configuration.getURIResolver();
saxonResolver = new StandardURIResolver();
}

@After
public void after() {
saxonResolver = null;
configuration = null;
}

@Test
public void testSaxonResources() throws TransformerException {
URL catalogUrl = this.getClass().getResource("/catalogs/empty-catalog.xml");
assertNotNull("/catalogs/empty-catalog.xml not found in classpath", catalogUrl);
File catalogFile = new File(catalogUrl.getFile());
Resolver resolver = new Resolver(saxonResolver, catalogFile, log);
ResolverS9 resolver = new ResolverS9(saxonResolver, catalogFile, log);
Source saxonResolution = saxonResolver.resolve("http://www.w3.org/2002/xmlspec/dtd/2.10/xmlspec.dtd", null);
Source dtd = resolver.resolve("http://www.w3.org/2002/xmlspec/dtd/2.10/xmlspec.dtd", null);
assertNotNull("xmlspec.dtd not resolved", dtd);
Expand All @@ -86,7 +83,7 @@ public void given_a_catalog_resolve_should_use_this_catalog() throws Transformer
URL log4jUrl = this.getClass().getResource("/log4j.properties");
String log4jUrlWithoutProtocol = log4jUrl.toExternalForm().substring("file:".length());
File catalogFile = new File(catalogUrl.getFile());
Resolver resolver = new Resolver(saxonResolver, catalogFile, log);
ResolverS9 resolver = new ResolverS9(saxonResolver, catalogFile, log);
// When
Source log4j = resolver.resolve("dependency:/fake+toto/log4j.properties", null);
// Then
Expand All @@ -108,7 +105,7 @@ public void given_a_cp_url_resolver_should_resolve_from_classpath() throws IOExc
log.warn(expected.toString());
URL catalogUrl = this.getClass().getResource("/catalogs/empty-catalog.xml");
File catalogFile = new File(catalogUrl.getFile());
Resolver resolver = new Resolver(saxonResolver, catalogFile, log);
ResolverS9 resolver = new ResolverS9(saxonResolver, catalogFile, log);
// When
Source actual = resolver.resolve(toResolver, null);
// Then
Expand All @@ -130,7 +127,7 @@ public void given_a_cp_url_and_a_base_uri_resolver_should_resolve_from_classpath
log.warn(expected.toString());
URL catalogUrl = this.getClass().getResource("/catalogs/empty-catalog.xml");
File catalogFile = new File(catalogUrl.getFile());
Resolver resolver = new Resolver(saxonResolver, catalogFile, log);
ResolverS9 resolver = new ResolverS9(saxonResolver, catalogFile, log);
// When
Source actual = resolver.resolve(toResolve, projectDir.toURI().toURL().toExternalForm());
// Then
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.xspec.maven.xspecMavenPlugin.resources.impl;

import io.xspec.maven.xspecMavenPlugin.resolver.Resolver;
import io.xspec.maven.xspecMavenPlugin.resolver.ResolverS9;
import io.xspec.maven.xspecMavenPlugin.resources.XSpecImplResources;
import io.xspec.maven.xspecMavenPlugin.utils.CatalogWriter;
import net.sf.saxon.Configuration;
import net.sf.saxon.lib.StandardURIResolver;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugin.logging.SystemStreamLog;
import org.assertj.core.api.SoftAssertions;
Expand All @@ -22,7 +22,7 @@ public void given_default_xspec_impl_res_abnd_standard_catalog_compile_xsl_shoul
// Given
CatalogWriter catalogWriter = new CatalogWriter(DefaultXSpecImplResources.class.getClassLoader());
File catalogFile = catalogWriter.writeCatalog(null, null, false);
Resolver resolver = new Resolver(saxonResolver, catalogFile, log);
ResolverS9 resolver = new ResolverS9(saxonResolver, catalogFile, log);
XSpecImplResources resources = new DefaultXSpecImplResources();

// When
Expand All @@ -34,19 +34,16 @@ public void given_default_xspec_impl_res_abnd_standard_catalog_compile_xsl_shoul
}


private Configuration configuration;
private URIResolver saxonResolver;
private Log log = new SystemStreamLog();

@Before
public void before() {
configuration = Configuration.newConfiguration();
saxonResolver = configuration.getURIResolver();
saxonResolver = new StandardURIResolver();
}

@After
public void after() {
saxonResolver = null;
configuration = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,14 @@
public class IndexGeneratorTest extends TestUtils {
private final RunnerOptions options = new RunnerOptions(new File("target/tests"));
private XmlStuff xmlStuff;
private boolean isDoctypeAndHtmlTagOnSameLine;

@Before
public void before() {
Configuration saxonConfiguration = Configuration.newConfiguration();
Processor proc = new Processor(saxonConfiguration);
isDoctypeAndHtmlTagOnSameLine = proc.getSaxonProductVersion().startsWith("10.")
|| proc.getSaxonProductVersion().startsWith("11.");
try {
xmlStuff = new XmlStuff(
new SaxonOptions(),
Expand Down Expand Up @@ -86,6 +89,10 @@ public void indexFileTest() throws Exception {
assertTrue("index file is not a file", expected.isFile());
// WARNING: with Saxon 9.8, there are only 38 lines
long nbLines = 41;
if (isDoctypeAndHtmlTagOnSameLine) {
// Saxon 10 and 11 have DOCTYPE on same line as <html> tag
nbLines--;
}
assertEquals("index should have "+nbLines+" lines", nbLines, Files.lines(expected.toPath()).count());
}

Expand All @@ -102,6 +109,10 @@ public void tableContentTest() throws Exception {
File expected = new File(options.reportDir, "index.html");
// WARNING : with Saxon 9.8, there are only 39 lines
long nbLines = 42 + 3 + 8;
if (isDoctypeAndHtmlTagOnSameLine) {
// Saxon 10 and 11 have DOCTYPE on same line as <html> tag
nbLines--;
}
assertEquals("index should have "+nbLines+" lines", nbLines, Files.lines(expected.toPath()).count());
assertEquals("table should contain 1 red row", 1, Files.lines(expected.toPath()).filter(l -> l.contains("class=\"error\"")).count());
}
Expand Down

0 comments on commit 6e0c050

Please sign in to comment.