From 7dc62012a6939f3698b6d101fa8f2366584f13a3 Mon Sep 17 00:00:00 2001 From: Andreas Penski <18-andreas.penski@users.noreply.projekte.kosit.org> Date: Sun, 3 May 2020 16:52:55 +0200 Subject: [PATCH] some cleanup --- .idea/compiler.xml | 1 + .idea/misc.xml | 2 +- CHANGELOG.md | 11 +++++-- docs/api.md | 2 +- .../api/AcceptRecommendation.java | 7 ++-- .../validationtool/api/Configuration.java | 28 +++++++++------- .../api/ResolvingConfigurationStrategy.java | 14 +++++--- .../cmd/CommandLineApplication.java | 1 + .../config/ConfigurationBuilder.java | 13 +++++++- .../config/ConfigurationLoader.java | 16 +++++++++ .../config/FallbackBuilder.java | 2 ++ .../validationtool/config/XPathBuilder.java | 2 +- .../impl/EngineInformation.java | 6 ++++ .../impl/tasks/ComputeAcceptanceAction.java | 2 +- .../impl/tasks/CreateReportAction.java | 5 ++- .../impl/xml/RelativeUriResolver.java | 13 +------- .../impl/xml/RemoteResolvingStrategy.java | 7 ++++ .../xml/StrictLocalResolvingStrategy.java | 19 ++++++++--- .../xml/StrictRelativeResolvingStrategy.java | 1 + src/main/model/xsd/daemon.xsd | 1 - .../impl/tasks/CreateReportActionTest.java | 8 ++--- .../resources/examples/simple/assertions.xml | 33 +++++++++++++++++++ 22 files changed, 144 insertions(+), 50 deletions(-) create mode 100644 src/main/java/de/kosit/validationtool/impl/xml/RemoteResolvingStrategy.java create mode 100644 src/test/resources/examples/simple/assertions.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 9f64100..bea581f 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -8,6 +8,7 @@ + diff --git a/.idea/misc.xml b/.idea/misc.xml index f207c86..3ab06a4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -79,7 +79,7 @@ - + diff --git a/CHANGELOG.md b/CHANGELOG.md index ec9e2ce..07e06a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## next version (unreleased) ### Added - -- Support java.xml.transform.Source/java.xml.transform.StreamSource as Input +- Added a builder style configuration API to configure scenarios +- Added an option to configure xml security e.g. to load from http sources or not from a specific repository +(so loading is configurable less restrictive, default strategy is to only load from a local repository) +- Support java.xml.transform.Source as Input ### Changed - - Inputs are NOT read into memory (e.g. Byte-Array) prior processing within the validator. This reduces memory consumption. +- CheckConfiguration is deprecated now. Use Configuration.load(...) or Configuration.build(...) +- Overall processing of xml files is based on Saxon s9api. No JAXP or SAX classes are used by +the validator (this further improves performance and memory consumption) +- ## UNRELEASED ### Fixed diff --git a/docs/api.md b/docs/api.md index 31d05ab..e00f0ea 100644 --- a/docs/api.md +++ b/docs/api.md @@ -56,7 +56,7 @@ public class StandardExample { // Load scenarios.xml from classpath URL scenarios = this.getClass().getClassLoader().getResource("scenarios.xml"); // Load the rest of the specific Validator configuration from classpath - CheckConfiguration config = new CheckConfiguration(scenarios.toURI()); + Configuration config = Configuration.load(scenarios.toURI()); // Use the default validation procedure Check validator = new DefaultCheck(config); // Validate a single document diff --git a/src/main/java/de/kosit/validationtool/api/AcceptRecommendation.java b/src/main/java/de/kosit/validationtool/api/AcceptRecommendation.java index c491201..479733d 100644 --- a/src/main/java/de/kosit/validationtool/api/AcceptRecommendation.java +++ b/src/main/java/de/kosit/validationtool/api/AcceptRecommendation.java @@ -1,21 +1,22 @@ package de.kosit.validationtool.api; /** - * Tri-state describtion of a Recommendation. + * Tri-state recommendation whether to accept the {@link Input} or not. */ public enum AcceptRecommendation { + /** * The evaluation of the overall validation could not be computed. */ UNDEFINED, /** - * Recommendation is to accept input based on the evaluation of the overall validation. + * Recommendation is to accept {@link Input} based on the evaluation of the overall validation. */ ACCEPTABLE, /** - * Recommendation is to reject input based on the evaluation of the overall validation. + * Recommendation is to reject {@link Input} based on the evaluation of the overall validation. */ REJECT } diff --git a/src/main/java/de/kosit/validationtool/api/Configuration.java b/src/main/java/de/kosit/validationtool/api/Configuration.java index dbbb53d..9aa6f70 100644 --- a/src/main/java/de/kosit/validationtool/api/Configuration.java +++ b/src/main/java/de/kosit/validationtool/api/Configuration.java @@ -12,15 +12,15 @@ import de.kosit.validationtool.impl.Scenario; /** * Configuration of the actual {@link Check} instance. This is an interface and can be implemented by custom * configuration classes. There are two implementations supported out of the box: - * + * *
    *
  1. {@link ConfigurationLoader} implements loading {@link Check} configurations from a scenario.xml file
  2. *
  3. Using a builder style api {@link de.kosit.validationtool.config.ConfigurationBuilder}to configure the * {@link Check}
  4. *
- * + *

* Both methods can be used via convinience methods. See below. - * + * * @author Andreas Penski */ @@ -28,51 +28,57 @@ public interface Configuration { /** * Returns a list of configured scenarios. - * + * * @return the list of scenarios */ List getScenarios(); /** * Returns the configured fallback scenario to use, in case no configured scenario match. - * + * * @return the fallback scenario */ Scenario getFallbackScenario(); /** * Returns the author of this configuration. - * + * * @return the author */ String getAuthor(); /** * Returns the name of the specification - * + * * @return the name */ String getName(); /** * The creation date of the config - * + * * @return the date */ String getDate(); + /** + * Add some additional parameters to the validator configuration. Parameter usage depends on actual implementation of + * {@link Check} + * + * @return + */ Map getAdditionalParameters(); /** * The content repository including resolving strategies. - * + * * @return the configured {@link ContentRepository} */ ContentRepository getContentRepository(); /** * Loads an XML based scenario definition from the file specified via URI. - * + * * @param scenarioDefinition the XML file with scenario definition * @return the loaded configuration */ @@ -93,7 +99,7 @@ public interface Configuration { /** * Creates a {@link Configuration} based on a builder style API using {@link ConfigurationBuilder} - * + * * @return the Builder */ static ConfigurationBuilder create() { diff --git a/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java b/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java index 525499a..86cad76 100644 --- a/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java +++ b/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java @@ -10,12 +10,15 @@ import javax.xml.validation.Validator; import net.sf.saxon.s9api.Processor; /** - * Centralized construction and configuration of XML related infrastructore components. The KoSIT Validator provides out - * of the box implementaions with various security levels. + * Centralized construction and configuration of XML related infrastructure components. This interface allows to use + * custom implementations and configurations of internal xml related factories and objects. + * + * The KoSIT Validator provides out of the box implementations with various security levels based on openjdk SAX stack. * * If you decide to implement a custom strategy, please be aware of XML security within your stack. The validator * components beyond this strategy asume secured implementation of the interfaces provided by this strategy. There is no - * effort to mitigate or prevent xml related security issues such as XXE, loading external sources etc. + * effort to mitigate or prevent xml related security issues such as XXE, loading external sources etc. Your would be + * responsible for this! * * @see de.kosit.validationtool.impl.ResolvingMode * @author Andreas Penski @@ -35,12 +38,14 @@ public interface ResolvingConfigurationStrategy { * 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(); /** - * Creates a specific implementation for resolving referenced objects in XML files. The URIResolver, it is used for + * Creates a specific implementation for resolving referenced objects in XML files. The URIResolver is used for * dereferencing an absolute URI (after resolution) to return a {@link javax.xml.transform.Source}. It can be * used for resolving relative URIs against a base URI or restrict access to certain URIs. *

@@ -48,6 +53,7 @@ public interface ResolvingConfigurationStrategy { * xsl:import-schema declarations. *

* + * @param scenarioRepository an optional repository, your implementation might not need this * @return a preconfigured {@link URIResolver} */ URIResolver createResolver(URI scenarioRepository); diff --git a/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java b/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java index 917fe57..ba0e9aa 100644 --- a/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java +++ b/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java @@ -29,6 +29,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; diff --git a/src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java b/src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java index 3de8f12..fab99b4 100644 --- a/src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java +++ b/src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java @@ -64,12 +64,17 @@ public class ConfigurationBuilder { private String description; + /** + * Add a specific author name to this configuration. + * + * @param authorName the name of the author + * @return this + */ public ConfigurationBuilder author(final String authorName) { this.author = authorName; return this; } - public ConfigurationBuilder name(final String name) { this.name = name; return this; @@ -135,6 +140,12 @@ public class ConfigurationBuilder { throw new NotImplementedException("Not yet defined"); } + /** + * Create a named schematron configuration. + * + * @param name the name of the schematron configuration + * @return new {@link SchemaBuilder} + */ public static SchematronBuilder schematron(final String name) { return new SchematronBuilder().name(name); } diff --git a/src/main/java/de/kosit/validationtool/config/ConfigurationLoader.java b/src/main/java/de/kosit/validationtool/config/ConfigurationLoader.java index 684695d..0457459 100644 --- a/src/main/java/de/kosit/validationtool/config/ConfigurationLoader.java +++ b/src/main/java/de/kosit/validationtool/config/ConfigurationLoader.java @@ -175,11 +175,27 @@ public class ConfigurationLoader { return s; } + /** + * Sets actual {@link ResolvingMode}, when the validator needs to resolve stuff on startup. + * @param mode the resolving mode + * @return this + */ public ConfigurationLoader setResolvingMode(final ResolvingMode mode) { this.resolvingMode = mode; return this; } + public ConfigurationLoader setResolvingStrategy(final ResolvingConfigurationStrategy strategy){ + this.resolvingConfigurationStrategy = strategy; + return this; + } + + /** + * Add a parameter to the configuration. + * @param name the name of the parameter + * @param value the parameter value object + * @return this + */ public ConfigurationLoader addParameter(final String name, final Object value) { this.parameters.put(name, value); return this; diff --git a/src/main/java/de/kosit/validationtool/config/FallbackBuilder.java b/src/main/java/de/kosit/validationtool/config/FallbackBuilder.java index 5399f39..d81b096 100644 --- a/src/main/java/de/kosit/validationtool/config/FallbackBuilder.java +++ b/src/main/java/de/kosit/validationtool/config/FallbackBuilder.java @@ -13,6 +13,8 @@ import de.kosit.validationtool.model.scenarios.CreateReportType; import de.kosit.validationtool.model.scenarios.ScenarioType; /** + * Create a fallback {@link Scenario} configuration. + * * @author Andreas Penski */ public class FallbackBuilder implements Builder { diff --git a/src/main/java/de/kosit/validationtool/config/XPathBuilder.java b/src/main/java/de/kosit/validationtool/config/XPathBuilder.java index c65d0ef..83cbe5a 100644 --- a/src/main/java/de/kosit/validationtool/config/XPathBuilder.java +++ b/src/main/java/de/kosit/validationtool/config/XPathBuilder.java @@ -72,7 +72,7 @@ class XPathBuilder implements Builder { extractNamespaces(); } } catch (final IllegalStateException e) { - final String msg = String.format("Error creating %s xpath", this.name, e); + final String msg = String.format("Error creating %s xpath: %s", this.name, e.getMessage()); log.error(msg, e); return new Result<>(Collections.singletonList(msg)); diff --git a/src/main/java/de/kosit/validationtool/impl/EngineInformation.java b/src/main/java/de/kosit/validationtool/impl/EngineInformation.java index 10692ec..d781f94 100644 --- a/src/main/java/de/kosit/validationtool/impl/EngineInformation.java +++ b/src/main/java/de/kosit/validationtool/impl/EngineInformation.java @@ -1,5 +1,7 @@ package de.kosit.validationtool.impl; +import lombok.SneakyThrows; + import java.io.IOException; import java.io.InputStream; import java.util.Properties; @@ -65,6 +67,10 @@ public class EngineInformation { return getFrameworkVersion().substring(0, 1); } + public static String getBuild() { + return PROPERTIES.getProperty("build_number"); + } + /** * Gibt den Namespace des eingesetzten Frameworks zurück. * diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java index 4e7f37b..04ccee2 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java @@ -60,7 +60,7 @@ public class ComputeAcceptanceAction implements CheckAction { } catch (final SaxonApiException e) { final String msg = String.format("Error evaluating accept recommendation: %s", selector.getUnderlyingXPathContext().toString()); log.error(msg, e); - results.addProcessingError(msg); + results.stopProcessing(msg); } } 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 59df0b8..014bae7 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java @@ -28,6 +28,7 @@ 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; @@ -64,6 +65,7 @@ import net.sf.saxon.s9api.XsltTransformer; * @author Andreas Penski */ @RequiredArgsConstructor +@Slf4j public class CreateReportAction implements CheckAction { /** @@ -206,7 +208,8 @@ public class CreateReportAction implements CheckAction { results.setReport(destination.getXdmNode()); } catch (final SaxonApiException | SAXException | JAXBException e) { - throw new IllegalStateException("Can not create final report", e); + log.error("Error creating final report", e); + results.stopProcessing("Can not create final report: " + e.getMessage()); } } 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 ff1d8b3..5b5d731 100644 --- a/src/main/java/de/kosit/validationtool/impl/xml/RelativeUriResolver.java +++ b/src/main/java/de/kosit/validationtool/impl/xml/RelativeUriResolver.java @@ -94,16 +94,5 @@ public class RelativeUriResolver implements URIResolver { } - public Reader resolve(final URI absoluteURI, final String encoding, final Configuration config) throws XPathException { - if (isUnderBaseUri(absoluteURI)) { - try { - return new InputStreamReader(absoluteURI.toURL().openStream(), encoding); - } catch (final IOException e) { - throw new IllegalStateException(String.format("Can not resolve required %s", absoluteURI), e); - } - } else { - throw new IllegalStateException(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/RemoteResolvingStrategy.java b/src/main/java/de/kosit/validationtool/impl/xml/RemoteResolvingStrategy.java new file mode 100644 index 0000000..3be4a65 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/xml/RemoteResolvingStrategy.java @@ -0,0 +1,7 @@ +package de.kosit.validationtool.impl.xml; + +public class RemoteResolvingStrategy extends StrictLocalResolvingStrategy { + + + +} diff --git a/src/main/java/de/kosit/validationtool/impl/xml/StrictLocalResolvingStrategy.java b/src/main/java/de/kosit/validationtool/impl/xml/StrictLocalResolvingStrategy.java index 90750b6..68c27a8 100644 --- a/src/main/java/de/kosit/validationtool/impl/xml/StrictLocalResolvingStrategy.java +++ b/src/main/java/de/kosit/validationtool/impl/xml/StrictLocalResolvingStrategy.java @@ -10,7 +10,9 @@ import javax.xml.validation.Validator; import lombok.extern.slf4j.Slf4j; /** - * + * This is a slightly more open implementation that allows resolving artifacts from local filesystems. Your are not + * bound to a specific 'repository'. But your validation artifacts (schema, xsl, etc.) must be available locally. This + * implementation does not allow loading from http sources * * @author Andreas Penski */ @@ -18,16 +20,23 @@ import lombok.extern.slf4j.Slf4j; public class StrictLocalResolvingStrategy extends StrictRelativeResolvingStrategy { /** - * e.g. don't allow any scheme + * Allow loading schema files from any local location. + * + * @return a configured {@link SchemaFactory} */ - @Override public SchemaFactory createSchemaFactory() { final SchemaFactory schemaFactory = super.createSchemaFactory(); - allowExternalSchema(schemaFactory, "file", "jar"); + allowExternalSchema(schemaFactory, "file"); return schemaFactory; } + /** + * The default resolver is able to resolve locally and relative. + * + * @param repository the repository is not used by this strategy + * @return null! + */ @Override public URIResolver createResolver(final URI repository) { // intentionally return 'null', since all resolving is configured with the other objects @@ -37,7 +46,7 @@ public class StrictLocalResolvingStrategy extends StrictRelativeResolvingStrateg @Override public Validator createValidator(final Schema schema) { final Validator validator = super.createValidator(schema); - allowExternalSchema(validator, "file", "jar"); + allowExternalSchema(validator, "file"); return validator; } 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 2db971c..26361e3 100644 --- a/src/main/java/de/kosit/validationtool/impl/xml/StrictRelativeResolvingStrategy.java +++ b/src/main/java/de/kosit/validationtool/impl/xml/StrictRelativeResolvingStrategy.java @@ -95,6 +95,7 @@ public class StrictRelativeResolvingStrategy extends BaseResolvingStrategy { processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(FEATURE_SECURE_PROCESSING), true); processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(DISSALLOW_DOCTYPE_DECL_FEATURE), true); processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(LOAD_EXTERNAL_DTD_FEATURE), false); + processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(XMLConstants.ACCESS_EXTERNAL_DTD), false); return processor; } diff --git a/src/main/model/xsd/daemon.xsd b/src/main/model/xsd/daemon.xsd index 5d1186a..c5f9b8c 100644 --- a/src/main/model/xsd/daemon.xsd +++ b/src/main/model/xsd/daemon.xsd @@ -16,7 +16,6 @@ - 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 fe6acb3..ae23151 100644 --- a/src/test/java/de/kosit/validationtool/impl/tasks/CreateReportActionTest.java +++ b/src/test/java/de/kosit/validationtool/impl/tasks/CreateReportActionTest.java @@ -38,8 +38,6 @@ public class CreateReportActionTest { private ContentRepository repository; - @Rule - public ExpectedException expectedException = ExpectedException.none(); @Before public void setup() { @@ -72,15 +70,15 @@ public class CreateReportActionTest { @Test public void testExecutionException() throws SaxonApiException { - this.expectedException.expect(IllegalStateException.class); - this.expectedException.expectMessage(Matchers.containsString("Can not create final report")); final Processor p = mock(Processor.class); final DocumentBuilder documentBuilder = mock(DocumentBuilder.class); this.action = new CreateReportAction(p, new ConversionService(), null); when(p.newDocumentBuilder()).thenReturn(documentBuilder); when(documentBuilder.build(any(Source.class))).thenThrow(new SaxonApiException("mocked")); - this.action.check(TestBagBuilder.createBag(InputFactory.read(Simple.SIMPLE_VALID), true)); + final Bag bag = TestBagBuilder.createBag(InputFactory.read(Simple.SIMPLE_VALID), true); + this.action.check(bag); + assertThat(bag.isStopped()).isTrue(); } } diff --git a/src/test/resources/examples/simple/assertions.xml b/src/test/resources/examples/simple/assertions.xml new file mode 100644 index 0000000..40a4242 --- /dev/null +++ b/src/test/resources/examples/simple/assertions.xml @@ -0,0 +1,33 @@ + + + + + + http://www.xoev.de/de/validator/varl/1 + + + Schema wurde validiert + + + + +