diff --git a/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverDecorator.java b/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverDecorator.java new file mode 100644 index 0000000..aff2e1f --- /dev/null +++ b/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverDecorator.java @@ -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 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 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); +} diff --git a/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverDecoratorProvider.java b/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverDecoratorProvider.java new file mode 100644 index 0000000..03b1ac8 --- /dev/null +++ b/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverDecoratorProvider.java @@ -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 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 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; + } +} diff --git a/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverDecoratorS9.java b/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverDecoratorS9.java new file mode 100644 index 0000000..8e80682 --- /dev/null +++ b/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverDecoratorS9.java @@ -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 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 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)); + } +} diff --git a/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/Resolver.java b/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverS9.java similarity index 97% rename from src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/Resolver.java rename to src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverS9.java index 5c7dc97..5d59ab3 100644 --- a/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/Resolver.java +++ b/src/main/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverS9.java @@ -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; @@ -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; diff --git a/src/main/java/io/xspec/maven/xspecMavenPlugin/utils/XmlStuff.java b/src/main/java/io/xspec/maven/xspecMavenPlugin/utils/XmlStuff.java index 431beee..7d96c11 100644 --- a/src/main/java/io/xspec/maven/xspecMavenPlugin/utils/XmlStuff.java +++ b/src/main/java/io/xspec/maven/xspecMavenPlugin/utils/XmlStuff.java @@ -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; @@ -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; @@ -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(); @@ -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); } @@ -207,14 +210,12 @@ 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"); @@ -222,7 +223,7 @@ private URIResolver buildUriResolver(final URIResolver saxonUriResolver) throws 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 { diff --git a/src/test/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverTest.java b/src/test/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverS9Test.java similarity index 91% rename from src/test/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverTest.java rename to src/test/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverS9Test.java index fa81560..f0ab7d8 100644 --- a/src/test/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverTest.java +++ b/src/test/java/io/xspec/maven/xspecMavenPlugin/resolver/ResolverS9Test.java @@ -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; @@ -49,22 +49,19 @@ * 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 @@ -72,7 +69,7 @@ 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); @@ -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 @@ -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 @@ -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 diff --git a/src/test/java/io/xspec/maven/xspecMavenPlugin/resources/impl/DefaultXSpecImplResourceResolveTest.java b/src/test/java/io/xspec/maven/xspecMavenPlugin/resources/impl/DefaultXSpecImplResourceResolveTest.java index 6d6199d..b640c78 100644 --- a/src/test/java/io/xspec/maven/xspecMavenPlugin/resources/impl/DefaultXSpecImplResourceResolveTest.java +++ b/src/test/java/io/xspec/maven/xspecMavenPlugin/resources/impl/DefaultXSpecImplResourceResolveTest.java @@ -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; @@ -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 @@ -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; } } diff --git a/src/test/java/io/xspec/maven/xspecMavenPlugin/utils/IndexGeneratorTest.java b/src/test/java/io/xspec/maven/xspecMavenPlugin/utils/IndexGeneratorTest.java index b718a98..cd66fda 100644 --- a/src/test/java/io/xspec/maven/xspecMavenPlugin/utils/IndexGeneratorTest.java +++ b/src/test/java/io/xspec/maven/xspecMavenPlugin/utils/IndexGeneratorTest.java @@ -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(), @@ -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 tag + nbLines--; + } assertEquals("index should have "+nbLines+" lines", nbLines, Files.lines(expected.toPath()).count()); } @@ -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 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()); }