From 0717e22d33af032af25b2ab9ce638f90bbeff0d8 Mon Sep 17 00:00:00 2001 From: Andreas Penski <18-andreas.penski@users.noreply.projekte.kosit.org> Date: Wed, 29 Jul 2020 12:13:18 +0000 Subject: [PATCH] #59 fix unparsed text uri resolving --- CHANGELOG.md | 1 + .../api/ResolvingConfigurationStrategy.java | 17 +++++++++++++---- .../validationtool/impl/ContentRepository.java | 12 ++++++++++-- .../kosit/validationtool/impl/DefaultCheck.java | 3 ++- .../impl/tasks/CreateReportAction.java | 9 +++++++-- .../impl/xml/RelativeUriResolver.java | 15 +++++++++++++-- .../xml/StrictRelativeResolvingStrategy.java | 5 +++++ .../impl/tasks/CreateReportActionTest.java | 8 +++----- .../examples/simple/repository/report.xsl | 3 +++ .../examples/simple/repository/some.txt | 1 + 10 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 src/test/resources/examples/simple/repository/some.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d77973..cfc1296 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - `getFailedAsserts()` and `isSchematronValid()` in [DefaultResult.java](https://github.com/itplr-kosit/validator/blob/master/src/main/java/de/kosit/validationtool/impl/DefaultResult.java) do not reflect actual schematron validation result +- exception while resolving when using XSLT's `unparsed-text()` function within report generation ### Changed - engine info contains version number of the validator (configurations can output this in the report for maintainance puposes) diff --git a/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java b/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java index 86cad76..c6fd194 100644 --- a/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java +++ b/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java @@ -7,6 +7,7 @@ import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; +import net.sf.saxon.lib.UnparsedTextURIResolver; import net.sf.saxon.s9api.Processor; /** @@ -28,7 +29,7 @@ public interface ResolvingConfigurationStrategy { /** * Creates a preconfigured {@link SchemaFactory} for loading {@link javax.xml.validation.Schema} objects. The * implementation is responsible for xml security. Take care - * + * * @return preconfigured {@link SchemaFactory} */ SchemaFactory createSchemaFactory(); @@ -37,9 +38,9 @@ public interface ResolvingConfigurationStrategy { * Returns a preconfigured {@link Processor Saxon Processor} for various tasks within the Validator. The validator * leverages the saxon s9api for internal processing e.g. xml reading and writing. So this is the main object to secure * for reading, transforming and writing xml files. - * + * * Note: you need exactly one instance for all validator related processing. - * + * * @return a preconfigured {@link Processor} */ Processor getProcessor(); @@ -52,12 +53,20 @@ public interface ResolvingConfigurationStrategy { * This URIResolver is used to dereference the URIs appearing in xsl:import, xsl:include, and * xsl:import-schema declarations. *

- * + * * @param scenarioRepository an optional repository, your implementation might not need this * @return a preconfigured {@link URIResolver} */ URIResolver createResolver(URI scenarioRepository); + /** + * Creates a specific implementation for resolving objects referenced via XSLT's unparsed-text() function. + * + * @param scenarioRepository an optional repository, your implementation might not need this + * @return a preconfigured {@link net.sf.saxon.lib.UnparsedTextURIResolver} or null for using saxons default + */ + UnparsedTextURIResolver createUnparsedTextURIResolver(URI scenarioRepository); + /** * Creates a preconfigured {@link Validator } instance for a given schema for xml file validation. The implementation * takes care about security and reference resolving strategies. diff --git a/src/main/java/de/kosit/validationtool/impl/ContentRepository.java b/src/main/java/de/kosit/validationtool/impl/ContentRepository.java index 84757d4..33a8388 100644 --- a/src/main/java/de/kosit/validationtool/impl/ContentRepository.java +++ b/src/main/java/de/kosit/validationtool/impl/ContentRepository.java @@ -52,6 +52,7 @@ import de.kosit.validationtool.model.scenarios.ResourceType; import de.kosit.validationtool.model.scenarios.ScenarioType; import de.kosit.validationtool.model.scenarios.ValidateWithSchematron; +import net.sf.saxon.lib.UnparsedTextURIResolver; import net.sf.saxon.s9api.Processor; import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.XPathCompiler; @@ -77,6 +78,8 @@ public class ContentRepository { private final URIResolver resolver; + private final UnparsedTextURIResolver unparsedTextURIResolver; + private final SchemaFactory schemaFactory; @Getter @@ -94,6 +97,7 @@ public class ContentRepository { this.resolvingConfigurationStrategy = strategy; this.processor = this.resolvingConfigurationStrategy.getProcessor(); this.resolver = this.resolvingConfigurationStrategy.createResolver(repository); + this.unparsedTextURIResolver = this.resolvingConfigurationStrategy.createUnparsedTextURIResolver(repository); this.schemaFactory = this.resolvingConfigurationStrategy.createSchemaFactory(); } @@ -251,14 +255,18 @@ public class ContentRepository { } /** - * Erzeugt einen resolver für dieses Repository, der nur relativ auflösen kann + * Returns the {@link URIResolver} to use for resolving xml artifacts. * - * @return ein neuer Resolver + * @return the resolver */ public URIResolver getResolver() { return this.resolver; } + public UnparsedTextURIResolver getUnparsedTextURIResolver() { + return this.unparsedTextURIResolver; + } + /** * Gibt eine Transformation zurück. * diff --git a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java index 8fee021..e985b24 100644 --- a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java +++ b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java @@ -85,7 +85,8 @@ public class DefaultCheck implements Check { this.checkSteps.add(new SchemaValidationAction(content.getResolvingConfigurationStrategy(), processor)); this.checkSteps.add(new SchematronValidationAction(content.getResolver(), this.conversionService)); this.checkSteps.add(new ValidateReportInputAction(this.conversionService, content.getReportInputSchema())); - this.checkSteps.add(new CreateReportAction(processor, this.conversionService, content.getResolver())); + this.checkSteps.add( + new CreateReportAction(processor, this.conversionService, content.getResolver(), content.getUnparsedTextURIResolver())); this.checkSteps.add(new ComputeAcceptanceAction()); } diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java index 014bae7..83e9554 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java @@ -28,7 +28,6 @@ import javax.xml.bind.Marshaller; import javax.xml.bind.util.JAXBSource; import javax.xml.transform.URIResolver; -import lombok.extern.slf4j.Slf4j; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.EntityResolver; @@ -41,6 +40,7 @@ import org.xml.sax.XMLReader; import org.xml.sax.helpers.AttributesImpl; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import de.kosit.validationtool.impl.CollectingErrorEventHandler; import de.kosit.validationtool.impl.ConversionService; @@ -48,6 +48,7 @@ import de.kosit.validationtool.impl.EngineInformation; import de.kosit.validationtool.impl.Scenario; import de.kosit.validationtool.model.reportInput.XMLSyntaxError; +import net.sf.saxon.lib.UnparsedTextURIResolver; import net.sf.saxon.s9api.BuildingContentHandler; import net.sf.saxon.s9api.DocumentBuilder; import net.sf.saxon.s9api.Processor; @@ -175,6 +176,8 @@ public class CreateReportAction implements CheckAction { private final URIResolver resolver; + private final UnparsedTextURIResolver unparsedTextURIResolver; + private static XsltExecutable loadFromScenario(final Scenario object) { return object.getReportTransformation().getExecutable(); } @@ -198,7 +201,9 @@ public class CreateReportAction implements CheckAction { final CollectingErrorEventHandler e = new CollectingErrorEventHandler(); transformer.setMessageListener(e); transformer.setURIResolver(this.resolver); - // transformer.getUnderlyingController().setUnparsedTextURIResolver(resolver); + if (this.unparsedTextURIResolver != null) { + transformer.getUnderlyingController().setUnparsedTextURIResolver(this.unparsedTextURIResolver); + } if (parsedDocument != null) { transformer.setParameter(new QName("input-document"), parsedDocument); } diff --git a/src/main/java/de/kosit/validationtool/impl/xml/RelativeUriResolver.java b/src/main/java/de/kosit/validationtool/impl/xml/RelativeUriResolver.java index 5b5d731..5c5d3b0 100644 --- a/src/main/java/de/kosit/validationtool/impl/xml/RelativeUriResolver.java +++ b/src/main/java/de/kosit/validationtool/impl/xml/RelativeUriResolver.java @@ -20,7 +20,6 @@ package de.kosit.validationtool.impl.xml; import java.io.IOException; -import java.io.InputStreamReader; import java.io.Reader; import java.net.URI; @@ -32,6 +31,8 @@ import javax.xml.transform.stream.StreamSource; import lombok.RequiredArgsConstructor; import net.sf.saxon.Configuration; +import net.sf.saxon.lib.StandardUnparsedTextResolver; +import net.sf.saxon.lib.UnparsedTextURIResolver; import net.sf.saxon.trans.XPathException; /** @@ -41,7 +42,7 @@ import net.sf.saxon.trans.XPathException; * @author Andreas Penski */ @RequiredArgsConstructor() -public class RelativeUriResolver implements URIResolver { +public class RelativeUriResolver implements URIResolver, UnparsedTextURIResolver { /** the base uri */ private final URI baseUri; @@ -93,6 +94,16 @@ public class RelativeUriResolver implements URIResolver { return r.startsWith(base); } + // from UnparsedTextURIResolver + @Override + public Reader resolve(final URI absoluteURI, final String encoding, final Configuration config) throws XPathException { + if (isUnderBaseUri(absoluteURI, this.baseUri)) { + return new StandardUnparsedTextResolver().resolve(absoluteURI, encoding, config); + } else { + throw new XPathException(String.format("The resolved transformation artifact %s is not within the configured repository %s", + absoluteURI, this.baseUri)); + } + } } \ No newline at end of file diff --git a/src/main/java/de/kosit/validationtool/impl/xml/StrictRelativeResolvingStrategy.java b/src/main/java/de/kosit/validationtool/impl/xml/StrictRelativeResolvingStrategy.java index 26361e3..f88229a 100644 --- a/src/main/java/de/kosit/validationtool/impl/xml/StrictRelativeResolvingStrategy.java +++ b/src/main/java/de/kosit/validationtool/impl/xml/StrictRelativeResolvingStrategy.java @@ -109,6 +109,11 @@ public class StrictRelativeResolvingStrategy extends BaseResolvingStrategy { return new RelativeUriResolver(repositoryURI); } + @Override + public UnparsedTextURIResolver createUnparsedTextURIResolver(final URI scenarioRepository) { + return new RelativeUriResolver(scenarioRepository); + } + @Override public Validator createValidator(final Schema schema) { if (schema == null) { diff --git a/src/test/java/de/kosit/validationtool/impl/tasks/CreateReportActionTest.java b/src/test/java/de/kosit/validationtool/impl/tasks/CreateReportActionTest.java index ae23151..afaaee4 100644 --- a/src/test/java/de/kosit/validationtool/impl/tasks/CreateReportActionTest.java +++ b/src/test/java/de/kosit/validationtool/impl/tasks/CreateReportActionTest.java @@ -9,11 +9,8 @@ import static org.mockito.Mockito.when; import javax.xml.transform.Source; -import org.hamcrest.Matchers; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import de.kosit.validationtool.api.InputFactory; import de.kosit.validationtool.impl.ContentRepository; @@ -42,7 +39,8 @@ public class CreateReportActionTest { @Before public void setup() { this.repository = Simple.createContentRepository(); - this.action = new CreateReportAction(this.repository.getProcessor(), new ConversionService(), this.repository.getResolver()); + this.action = new CreateReportAction(this.repository.getProcessor(), new ConversionService(), this.repository.getResolver(), + this.repository.getUnparsedTextURIResolver()); } @Test @@ -72,7 +70,7 @@ public class CreateReportActionTest { public void testExecutionException() throws SaxonApiException { final Processor p = mock(Processor.class); final DocumentBuilder documentBuilder = mock(DocumentBuilder.class); - this.action = new CreateReportAction(p, new ConversionService(), null); + this.action = new CreateReportAction(p, new ConversionService(), null, null); when(p.newDocumentBuilder()).thenReturn(documentBuilder); when(documentBuilder.build(any(Source.class))).thenThrow(new SaxonApiException("mocked")); diff --git a/src/test/resources/examples/simple/repository/report.xsl b/src/test/resources/examples/simple/repository/report.xsl index a402938..fdb6006 100644 --- a/src/test/resources/examples/simple/repository/report.xsl +++ b/src/test/resources/examples/simple/repository/report.xsl @@ -37,6 +37,9 @@ + + + diff --git a/src/test/resources/examples/simple/repository/some.txt b/src/test/resources/examples/simple/repository/some.txt new file mode 100644 index 0000000..38671ab --- /dev/null +++ b/src/test/resources/examples/simple/repository/some.txt @@ -0,0 +1 @@ +This content should be transferred to the result document \ No newline at end of file