getAdditionalParameters() {
- return this.delegate.getAdditionalParameters();
- }
-
- @Override
- public String getName() {
- return getDelegate().getName();
- }
-
- @Override
- public String getAuthor() {
- return getDelegate().getAuthor();
- }
-
- @Override
- public ContentRepository getContentRepository() {
- return getDelegate().getContentRepository();
- }
}
diff --git a/src/main/java/de/kosit/validationtool/api/Configuration.java b/src/main/java/de/kosit/validationtool/api/Configuration.java
deleted file mode 100644
index 039bf2a..0000000
--- a/src/main/java/de/kosit/validationtool/api/Configuration.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.api;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-
-import de.kosit.validationtool.config.ConfigurationBuilder;
-import de.kosit.validationtool.config.ConfigurationLoader;
-import de.kosit.validationtool.impl.ContentRepository;
-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:
- *
- *
- * - {@link ConfigurationLoader} implements loading {@link Check} configurations from a scenario.xml file
- * - Using a builder style api {@link de.kosit.validationtool.config.ConfigurationBuilder}to configure the
- * {@link Check}
- *
- *
- * Both methods can be used via convinience methods. See below.
- *
- * @author Andreas Penski
- */
-
-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 A Map containing the additional Parameters to be added.
- */
- 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
- */
- static ConfigurationLoader load(final URI scenarioDefinition) {
- return load(scenarioDefinition, null);
- }
-
- /**
- * Loads an XML based scenario definition from the file with an specific repository / source location specified via
- * URIs.
- *
- * @param scenarioDefinition the XML file with scenario definition
- * @return the loaded configuration
- */
- static ConfigurationLoader load(final URI scenarioDefinition, final URI repository) {
- return new ConfigurationLoader(scenarioDefinition, repository);
- }
-
- /**
- * Creates a {@link Configuration} based on a builder style API using {@link ConfigurationBuilder}
- *
- * @return the Builder
- */
- static ConfigurationBuilder create() {
- return new ConfigurationBuilder();
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/api/Input.java b/src/main/java/de/kosit/validationtool/api/Input.java
index 8d93c7a..69f9c22 100644
--- a/src/main/java/de/kosit/validationtool/api/Input.java
+++ b/src/main/java/de/kosit/validationtool/api/Input.java
@@ -1,60 +1,42 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.api;
-import java.io.IOException;
-
-import javax.xml.transform.Source;
+import lombok.*;
/**
- * An input for the validator.
+ * Eine Datei in eingelesener Form.
*
* @author apenski
*/
+@Getter
+@RequiredArgsConstructor (access = AccessLevel.PACKAGE)
+@AllArgsConstructor (access = AccessLevel.PACKAGE)
+public class Input {
-public interface Input {
+ private final byte[] content;
- /**
- * The name of the input for document identification
- *
- * @return the name
- */
- String getName();
+ private final String name;
- /**
- * The hashcode for document identification
- *
- * @return the computed hashcode
- */
- byte[] getHashCode();
+ private byte[] hashCode;
- /**
- * The digest algorithm used for computing the {@link #getHashCode()}
- *
- * @return the name of the digest algorithm
- */
- String getDigestAlgorithm();
-
- /**
- * Creates a new {@link Source } for this input which carries the actual data
- *
- * @return an open {@link Source}
- * @throws IOException on I/O while opening the source
- */
- Source getSource() throws IOException;
+ private String digestAlgorithm;
}
diff --git a/src/main/java/de/kosit/validationtool/api/InputFactory.java b/src/main/java/de/kosit/validationtool/api/InputFactory.java
index c6457d6..5e93fd3 100644
--- a/src/main/java/de/kosit/validationtool/api/InputFactory.java
+++ b/src/main/java/de/kosit/validationtool/api/InputFactory.java
@@ -1,49 +1,48 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.api;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
-import java.net.URLConnection;
+import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.UUID;
+import java.security.DigestInputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
+import javax.xml.bind.DatatypeConverter;
import org.apache.commons.lang3.StringUtils;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
-import de.kosit.validationtool.impl.input.ByteArrayInput;
-import de.kosit.validationtool.impl.input.ResourceInput;
-import de.kosit.validationtool.impl.input.SourceInput;
-import de.kosit.validationtool.impl.input.StreamHelper;
-import de.kosit.validationtool.impl.input.XdmNodeInput;
-
-import net.sf.saxon.s9api.XdmNode;
-
/**
* Service zum Einlesen des Test-Objekts in den Speicher. Beim Einlesen wird gleichzeitig eine Prüfsumme ermittelt und
* mit dem Ergebnis mitgeführt.
@@ -55,10 +54,9 @@ public class InputFactory {
static final String DEFAULT_ALGORITH = "SHA-256";
- /**
- * Pseudo hashcode algorithm name, which indicates, thate the hashcode of the {@link Input} is actually the name.
- */
- static final String PSEUDO_NAME_ALGORITHM = "NAME";
+ private static final int EOF = -1;
+
+ private static final int DEFAULT_BUFFER_SIZE = 4096;
private static final String MESSAGE_OPEN_STREAM_ERROR = "Can not open stream from";
@@ -71,13 +69,12 @@ public class InputFactory {
InputFactory(final String specifiedAlgorithm) {
this.algorithm = isNotEmpty(specifiedAlgorithm) ? specifiedAlgorithm : DEFAULT_ALGORITH;
- // check validity
- StreamHelper.createDigest(this.algorithm);
+ createDigest();
}
/**
- * Liest einen Prüfling von dem übergebenen Pfad. Es wird der Default-Prüfsummenalgorithmus zur Ermittlung der
- * Prüfsumme genutzt.
+ * Liest einen Prüfling von dem übergebenen Pfad. Es wird der Default-Prüfsummenalgorithmus zur Ermittlung der Prüfsumme
+ * genutzt.
*
* @param path der Prüflings
* @return ein Prüf-Eingabe-Objekt
@@ -96,7 +93,11 @@ public class InputFactory {
*/
public static Input read(final Path path, final String digestAlgorithm) {
checkNull(path);
- return read(path.toUri(), digestAlgorithm);
+ try ( final InputStream stream = Files.newInputStream(path) ) {
+ return read(stream, path.toString(), digestAlgorithm);
+ } catch (final IOException e) {
+ throw new IllegalArgumentException(MESSAGE_OPEN_STREAM_ERROR + path, e);
+ }
}
/**
@@ -111,36 +112,9 @@ public class InputFactory {
}
/**
- * Liest einen Prüfling von der übergebenen URI. Es wird der Default-Prüfsummenalgorithmus zur Ermittlung der
- * Prüfsumme genutzt.
- *
- * @param uri URI des Prüflings
- * @return ein Prüf-Eingabe-Objekt
- */
- public static Input read(final URI uri) {
- return read(uri, DEFAULT_ALGORITH);
- }
-
- /**
- * Liest einen Prüfling von der übergebenen URL. Es wird ein definierter Algorithmis zur Ermittlung der Prüfsumme
+ * Liest einen Prüfling von der übergebenen URL. Es wird der Default-Prüfsummenalgorithmus zur Ermittlung der Prüfsumme
* genutzt.
- *
- * @param uri URI des Prüflings
- * @param digestAlgorithm der Prüfsummenalgorithmus
- * @return ein Prüf-Eingabe-Objekt
- */
- public static Input read(final URI uri, final String digestAlgorithm) {
- try {
- return read(uri.toURL(), digestAlgorithm);
- } catch (final MalformedURLException e) {
- throw new IllegalArgumentException(String.format("URL invalid or protocol not supported: %s", uri), e);
- }
- }
-
- /**
- * Liest einen Prüfling von der übergebenen URL. Es wird der Default-Prüfsummenalgorithmus zur Ermittlung der
- * Prüfsumme genutzt.
- *
+ *
* @param url URL des Prüflings
* @return ein Prüf-Eingabe-Objekt
*/
@@ -148,8 +122,16 @@ public class InputFactory {
return read(url, DEFAULT_ALGORITH);
}
+ public static Input read(final URI uri) {
+ try {
+ return read(uri.toURL(), DEFAULT_ALGORITH);
+ } catch (final MalformedURLException e) {
+ throw new IllegalArgumentException(String.format("Can not read from uri %s Not a valid uri supplied", uri));
+ }
+ }
+
/**
- * Liest einen Prüfling von der übergebenen URL. Es wird ein definierter Algorithmus zur Ermittlung der Prüfsumme
+ * Liest einen Prüfling von der übergebenen URL. Es wird ein definierter Algorithmis zur Ermittlung der Prüfsumme
* genutzt.
*
* @param url URL des Prüflings
@@ -158,67 +140,11 @@ public class InputFactory {
*/
public static Input read(final URL url, final String digestAlgorithm) {
checkNull(url);
- checkNotEmpty(url.getFile());
try {
- final URLConnection urlConnection = url.openConnection();
- urlConnection.connect();
+ return read(url.openStream(), url.getFile(), digestAlgorithm);
} catch (final IOException e) {
throw new IllegalArgumentException(MESSAGE_OPEN_STREAM_ERROR + url, e);
}
- return new ResourceInput(url, url.getFile(), digestAlgorithm);
-
- }
-
- /**
- * Reads a test document from a {@link Source}. Note: computing the hashcode is only supported for
- * {@link StreamSource}. You can not directly use other {@link Source Soures}. You need to supply the hashcode for
- * identification then.
- *
- * @param source source
- * @return an {@link Input}
- */
- public static Input read(final Source source) {
- if (source instanceof StreamSource) {
- return read(source, source.getSystemId(), DEFAULT_ALGORITH);
- }
- final String name = UUID.randomUUID().toString();
- return read(source, name, PSEUDO_NAME_ALGORITHM, name.getBytes());
- }
-
- /**
- * Reads a test document from a {@link Source} using a specified digest algorithm.
- *
- * Note: computing the hashcode is only supported for {@link StreamSource}. You can not directly use other
- * {@link Source Soures}. You need to supply the hashcode for identification then.
- *
- * @param source source
- * @param name the digest algorithm
- * @return an {@link Input}
- */
- public static Input read(final Source source, final String name) {
- checkNotEmpty(name);
- return read(source, name, PSEUDO_NAME_ALGORITHM, name.getBytes());
- }
-
- public static Input read(final Source source, final String name, final String digestAlgorithm) {
- return read(source, name, digestAlgorithm, null);
- }
-
- /**
- * Reads a test document from a {@link Source} using a specified digest algorithm.
- *
- * @param source source
- * @param digestAlgorithm the digest algorithm
- * @return an {@link Input}
- */
- public static Input read(final Source source, final String digestAlgorithm, final byte[] hashcode) {
- checkNull(source);
- return read(source, source.getSystemId(), digestAlgorithm, hashcode);
- }
-
- public static Input read(final Source source, final String name, final String digestAlgorithm, final byte[] hashcode) {
- checkNull(source);
- return new SourceInput(source, name, digestAlgorithm, hashcode);
}
/**
@@ -236,7 +162,6 @@ public class InputFactory {
} catch (final IOException e) {
throw new IllegalArgumentException(MESSAGE_OPEN_STREAM_ERROR + file, e);
}
-
}
/**
@@ -261,14 +186,7 @@ public class InputFactory {
*/
public static Input read(final byte[] input, final String name, final String digestAlgorithm) {
checkNull(input);
- checkNotEmpty(name);
- return new ByteArrayInput(input, name, digestAlgorithm);
- }
-
- private static void checkNotEmpty(final String name) {
- if (StringUtils.isBlank(name)) {
- throw new IllegalArgumentException("Input name can not be null");
- }
+ return read(new ByteArrayInputStream(input), name, digestAlgorithm);
}
private static void checkNull(final Object input) {
@@ -297,21 +215,45 @@ public class InputFactory {
* @return einen Prüfling in eingelesener Form
*/
public static Input read(final InputStream inputStream, final String name, final String digestAlgorithm) {
- checkNull(inputStream);
- return read(new StreamSource(inputStream, name), name, digestAlgorithm);
+ return new InputFactory(digestAlgorithm).readStream(inputStream, name);
}
- /**
- * Reads a saxon {@link XdmNode} with a given name. Hashcode identification is based on the name of the supplied
- * input. Now real hashcode is computed.
- *
- * @param node the node to read
- * @param name the name of the {@link Input}
- * @return an {@link Input} to validate
- */
- public static Input read(final XdmNode node, final String name) {
- checkNull(node);
- return new XdmNodeInput(node, name, PSEUDO_NAME_ALGORITHM, name.getBytes());
+ private Input readStream(final InputStream inputStream, final String name) {
+ if (StringUtils.isNotBlank(name)) {
+ log.debug("Generating hashcode for {} using {} algorithm", name, getAlgorithm());
+ final MessageDigest digest = createDigest();
+ final byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+ try ( final BufferedInputStream bis = new BufferedInputStream(inputStream);
+ final DigestInputStream dis = new DigestInputStream(bis, digest);
+ final ByteArrayOutputStream out = new ByteArrayOutputStream() ) {
+
+ // read the file and update the hash calculation
+ int n;
+ while (EOF != (n = dis.read(buffer))) {
+ out.write(buffer, 0, n);
+ }
+ // get the hash value as byte array
+ final byte[] hash = digest.digest();
+ log.debug("Generated hashcode for {} is {}", name, DatatypeConverter.printHexBinary(hash));
+ out.flush();
+ return new Input(out.toByteArray(), name, hash, digest.getAlgorithm());
+ } catch (final IOException e) {
+ throw new IllegalArgumentException(MESSAGE_OPEN_STREAM_ERROR + name, e);
+ }
+ } else {
+ throw new IllegalArgumentException("Must supply a valid name/identifier for the input");
+ }
+ }
+
+ private MessageDigest createDigest() {
+ try {
+ final MessageDigest digest;
+ digest = MessageDigest.getInstance(getAlgorithm());
+ return digest;
+ } catch (final NoSuchAlgorithmException e) {
+ // should not happen
+ throw new IllegalStateException(String.format("Specified method %s is not available", getAlgorithm()), e);
+ }
}
}
diff --git a/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java b/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java
deleted file mode 100644
index 37be24f..0000000
--- a/src/main/java/de/kosit/validationtool/api/ResolvingConfigurationStrategy.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.api;
-
-import java.net.URI;
-
-import javax.xml.transform.URIResolver;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-import javax.xml.validation.Validator;
-
-import net.sf.saxon.lib.UnparsedTextURIResolver;
-
-/**
- * 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. Your would be
- * responsible for this!
- *
- * @see de.kosit.validationtool.impl.ResolvingMode
- * @author Andreas Penski
- */
-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();
-
- /**
- * 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.
- *
- * 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.
- *
- * @param schema the scheme to create a {@link Validator} for
- * @return a preconfigured {@link Validator}
- */
- Validator createValidator(Schema schema);
-
-}
diff --git a/src/main/java/de/kosit/validationtool/api/Result.java b/src/main/java/de/kosit/validationtool/api/Result.java
index f3ed697..dcbe19d 100644
--- a/src/main/java/de/kosit/validationtool/api/Result.java
+++ b/src/main/java/de/kosit/validationtool/api/Result.java
@@ -1,19 +1,3 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package de.kosit.validationtool.api;
import java.util.List;
@@ -22,19 +6,18 @@ import org.oclc.purl.dsdl.svrl.FailedAssert;
import org.oclc.purl.dsdl.svrl.SchematronOutput;
import org.w3c.dom.Document;
-import de.kosit.validationtool.impl.model.CustomFailedAssert;
import net.sf.saxon.s9api.XdmNode;
/**
- * API result object holding various information of the validation process results.
+ * API Rückgabe Objekt des Ergebnisses des Validierungsprozesses.
*
* @author Andreas Penski
*/
public interface Result {
/**
- * Zeigt an, ob die Verarbeitung durch den Validator erfolgreich durchlaufen wurde. Diese Funktion macht
- * ausdrücklich keine Aussage über die zur Akzeptanz.
+ * Zeigt an, ob die Verarbeitung durch den Validator erfolgreich durchlaufen wurde. Diese Funktion macht ausdrücklich
+ * keine Aussage über die zur Akzeptanz.
*
* @return true, wenn die Verarbeitung komplett und erfolgreich durchlaufen wurde
* @see #getAcceptRecommendation()
@@ -70,34 +53,26 @@ public interface Result {
/**
* Schnellzugriff auf die Empfehlung zur Weiterverarbeitung des Dokuments.
*
- * @return true wenn {@link AcceptRecommendation#ACCEPTABLE}
+ * @return true wenn {@link AcceptRecommendation#ACCEPTABLE}
*/
boolean isAcceptable();
/**
* Gibt eine Liste mit gefundenen Schema-Validation-Fehler zurück. Diese Liste ist leer, wenn keine Fehler gefunden
* wurden.
- *
- * @return List of schema validation errors.
*/
List getSchemaViolations();
/**
* Liefert die Ergebnisse der Schematron-Prüfungen, in der Reihenfolge der Szenario-Konfiguration.
*
- * @return List with Schematron results
+ * @return Liste mit Schematron-Ergebnissen
*/
List getSchematronResult();
- /**
- * @return List of custom failed asserts per Schematron level. Only failed assertions with a custom level are
- * contained. Never null but maybe empty.
- */
- List getCustomFailedAsserts();
-
/**
* Returns {@link org.oclc.purl.dsdl.svrl.FailedAssert FailedAsserts} of a schematron evaluation.
- *
+ *
* @return list of {@link org.oclc.purl.dsdl.svrl.FailedAssert FailedAsserts}, if any, empty list otherwise
*/
List getFailedAsserts();
@@ -105,22 +80,21 @@ public interface Result {
/**
* Liefert ein true, wenn keine Schema-Violations vorhanden sind.
*
- * @return true if XML Schema compliant
+ * @return true wenn Schema-valide
*/
boolean isSchemaValid();
/**
* Liefert ein true, wenn der Prüfling eine well-formed XML-Datei ist.
*
- * @return true if wellformed
+ * @return true wenn well-formed
*/
boolean isWellformed();
/**
- * Returns true, if schematron has been checked and the result does not contain any {@link FailedAssert
- * FailedAsserts}.
- *
- * @return true, if valid
+ * Returns true, if schematron has been checked and the result does not contain any {@link FailedAssert FailedAsserts}.
+ *
+ * @return true, if valid
*/
boolean isSchematronValid();
}
diff --git a/src/main/java/de/kosit/validationtool/api/XmlError.java b/src/main/java/de/kosit/validationtool/api/XmlError.java
index 5432b0b..962b61e 100644
--- a/src/main/java/de/kosit/validationtool/api/XmlError.java
+++ b/src/main/java/de/kosit/validationtool/api/XmlError.java
@@ -1,19 +1,3 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package de.kosit.validationtool.api;
/**
diff --git a/src/main/java/de/kosit/validationtool/cmd/CheckAssertionAction.java b/src/main/java/de/kosit/validationtool/cmd/CheckAssertionAction.java
index 655c080..79d4d24 100644
--- a/src/main/java/de/kosit/validationtool/cmd/CheckAssertionAction.java
+++ b/src/main/java/de/kosit/validationtool/cmd/CheckAssertionAction.java
@@ -1,17 +1,20 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.cmd;
@@ -23,14 +26,16 @@ import java.util.Map;
import org.apache.commons.lang3.StringUtils;
-import de.kosit.validationtool.cmd.assertions.AssertionType;
-import de.kosit.validationtool.cmd.assertions.Assertions;
-import de.kosit.validationtool.impl.model.Result;
-import de.kosit.validationtool.impl.tasks.CheckAction;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+
+import de.kosit.validationtool.cmd.assertions.AssertionType;
+import de.kosit.validationtool.cmd.assertions.Assertions;
+import de.kosit.validationtool.impl.model.Result;
+import de.kosit.validationtool.impl.tasks.CheckAction;
+
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XPathCompiler;
@@ -54,12 +59,12 @@ class CheckAssertionAction implements CheckAction {
private Map> mappedAssertions;
- private static boolean matches(final String key, final String name) {
+ private static boolean matches(String key, String name) {
return key.startsWith(name) || (name + ".xml").endsWith(key);
}
@Override
- public void check(final Bag results) {
+ public void check(Bag results) {
log.info("Checking assertions for {}", results.getInput().getName());
final List toCheck = findAssertions(results.getName());
final List errors = new ArrayList<>();
@@ -82,28 +87,29 @@ class CheckAssertionAction implements CheckAction {
}
}
- private List findAssertions(final String name) {
+ private List findAssertions(String name) {
return getMapped().entrySet().stream().filter(e -> matches(e.getKey(), name)).map(Map.Entry::getValue).findFirst().orElse(null);
}
- private boolean check(final XdmNode document, final AssertionType assertion) {
+
+ private boolean check(XdmNode document, AssertionType assertion) {
try {
final XPathSelector selector = createSelector(assertion);
selector.setContextItem(document);
return selector.effectiveBooleanValue();
- } catch (final SaxonApiException e) {
+ } catch (SaxonApiException e) {
log.error("Error evaluating assertion {} for {}", assertion.getTest(), assertion.getReportDoc(), e);
}
return false;
}
- private XPathSelector createSelector(final AssertionType assertion) {
+ private XPathSelector createSelector(AssertionType assertion) throws SaxonApiException {
try {
final XPathCompiler compiler = getProcessor().newXPathCompiler();
assertions.getNamespace().forEach(ns -> compiler.declareNamespace(ns.getPrefix(), ns.getValue()));
return compiler.compile(assertion.getTest()).load();
- } catch (final SaxonApiException e) {
+ } catch (SaxonApiException e) {
throw new IllegalStateException(String.format("Can not compile xpath match expression '%s'",
StringUtils.isNotBlank(assertion.getTest()) ? assertion.getTest() : "EMPTY EXPRESSION"), e);
}
@@ -112,8 +118,8 @@ class CheckAssertionAction implements CheckAction {
private Map> getMapped() {
if (mappedAssertions == null) {
mappedAssertions = new HashMap<>();
- for (final AssertionType assertionType : assertions.getAssertion()) {
- final List list = mappedAssertions.computeIfAbsent(assertionType.getReportDoc(), k -> new ArrayList<>());
+ for (AssertionType assertionType : assertions.getAssertion()) {
+ List list = mappedAssertions.computeIfAbsent(assertionType.getReportDoc(), k -> new ArrayList<>());
list.add(assertionType);
}
}
diff --git a/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java b/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java
index 37b9ed7..a7224d7 100644
--- a/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java
+++ b/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java
@@ -1,112 +1,378 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.cmd;
-import static de.kosit.validationtool.impl.Printer.writeErr;
-import static org.apache.commons.lang3.StringUtils.isNotEmpty;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.stream.Collectors;
-import org.apache.commons.lang3.ObjectUtils;
-import org.fusesource.jansi.AnsiConsole;
-import org.fusesource.jansi.AnsiRenderer.Code;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
-import de.kosit.validationtool.cmd.report.Line;
-import de.kosit.validationtool.impl.Printer;
-import picocli.CommandLine;
-import picocli.CommandLine.ParseResult;
+import lombok.extern.slf4j.Slf4j;
+
+import de.kosit.validationtool.api.CheckConfiguration;
+import de.kosit.validationtool.api.Input;
+import de.kosit.validationtool.api.InputFactory;
+import de.kosit.validationtool.cmd.assertions.Assertions;
+import de.kosit.validationtool.impl.ConversionService;
+import de.kosit.validationtool.impl.ObjectFactory;
/**
- * Commandline interface of the validator. It parses the commandline args and hands over actual execution to
- * {@link Validator}.
- *
- * This separated from {@link Validator} to configure the slf4j simple logging.
+ * Commandline Version des Prüftools. Parsed die Kommandozeile und führt die konfigurierten Aktionen aus.
*
* @author Andreas Penski
*/
-// performance is not a problem here
+@Slf4j
public class CommandLineApplication {
+ private static final Option HELP = Option.builder("?").longOpt("help").argName("Help").desc("Displays this help").build();
+
+ private static final Option SCENARIOS = Option.builder("s").required().longOpt("scenarios").hasArg()
+ .desc("Location of scenarios.xml e.g.").build();
+
+ private static final Option REPOSITORY = Option.builder("r").longOpt("repository").hasArg()
+ .desc("Directory containing scenario content").build();
+
+ private static final Option PRINT = Option.builder("p").longOpt("print").desc("Prints the check result to stdout").build();
+
+ private static final Option OUTPUT = Option.builder("o").longOpt("output-directory")
+ .desc("Defines the out directory for results. Defaults to cwd").hasArg().build();
+
+ private static final Option EXTRACT_HTML = Option.builder("h").longOpt("html")
+ .desc("Extract and save any html content within result as a separate file ").build();
+
+ private static final Option DEBUG = Option.builder("d").longOpt("debug").desc("Prints some more debug information").build();
+
+ private static final Option SERIALIZE_REPORT_INPUT = Option.builder("c").longOpt("serialize-report-input")
+ .desc("Serializes the report input to the cwd").build();
+
+ private static final Option CHECK_ASSERTIONS = Option.builder("c").longOpt("check-assertions").hasArg()
+ .desc("Check the result using defined assertions").argName("assertions-file").build();
+
+ private static final Option SERVER = Option.builder("D").longOpt("daemon").desc("Starts a daemon listing for validation requests")
+ .build();
+
+ private static final Option HOST = Option.builder("H").longOpt("host").hasArg()
+ .desc("The hostname / IP address to bind the daemon. Default is localhost").build();
+
+ private static final Option PORT = Option.builder("P").longOpt("port").hasArg().desc("The port to bind the daemon. Default is 8080")
+ .build();
+
+ private static final Option WORKER_COUNT = Option.builder("T").longOpt("threads").hasArg()
+ .desc("Number of threads processing validation requests").build();
+
+ public static final int DAEMON_SIGNAL = 100;
+
+ private static final Option PRINT_MEM_STATS = Option.builder("m").longOpt("memory-stats").desc("Prints some memory stats").build();
+
private CommandLineApplication() {
// main class -> hide constructor
}
/**
- * Main.
+ * Main-Funktion für die Kommandozeilen-Applikation.
*
* @param args die Eingabe-Argumente
*/
public static void main(final String[] args) {
- AnsiConsole.systemInstall();
- final ReturnValue resultStatus = mainProgram(args);
- if (!resultStatus.equals(ReturnValue.DAEMON_MODE)) {
- if (!resultStatus.equals(ReturnValue.HELP_REQUEST) && resultStatus.getCode() >= 0) {
- sayGoodby(resultStatus);
- }
- System.exit(resultStatus.getCode());
- } else {
- Runtime.getRuntime().addShutdownHook(new Thread(() -> Printer.writeOut("Shutting down daemon ...")));
+ final int resultStatus = mainProgram(args);
+ if (DAEMON_SIGNAL != resultStatus) {
+ System.exit(resultStatus);
}
}
- private static void sayGoodby(final ReturnValue resultStatus) {
- Printer.writeOut("\n##############################");
- if (resultStatus.equals(ReturnValue.SUCCESS)) {
- Printer.writeOut("# " + new Line(Code.GREEN).add("Validation successful!").render(false, false) + " #");
+ /**
+ * Hauptprogramm für die Kommandozeilen-Applikation.
+ *
+ * @param args die Eingabe-Argumente
+ */
+ static int mainProgram(final String[] args) {
+ int returnValue = 0;
+ final Options options = createOptions();
+ if (isHelpRequested(args)) {
+ printHelp(options);
} else {
- Printer.writeOut("# " + new Line(Code.RED).add("Validation failed!").render(false, false) + " #");
- }
- Printer.writeOut("##############################");
- }
-
- // for testing purposes. Unless jvm is terminated during tests. See above
- static ReturnValue mainProgram(final String[] args) {
-
- ReturnValue resultStatus;
- final CommandLine commandLine = new CommandLine(new CommandLineOptions());
- try {
- commandLine.setExecutionExceptionHandler(CommandLineApplication::logExecutionException);
- final int cmdlineRetVal = commandLine.execute(args);
- if (commandLine.isUsageHelpRequested() || cmdlineRetVal == CommandLine.ExitCode.USAGE) {
- resultStatus = ReturnValue.HELP_REQUEST;
- } else {
- resultStatus = ObjectUtils.getIfNull(commandLine.getExecutionResult(), ReturnValue.PARSING_ERROR);
- if (resultStatus.isError()) {
- commandLine.usage(System.out);
+ try {
+ final CommandLineParser parser = new DefaultParser();
+ final CommandLine cmd = parser.parse(options, args);
+ if (cmd.hasOption(SERVER.getOpt())) {
+ returnValue = startDaemonMode(cmd);
+ } else if (cmd.getArgList().isEmpty()) {
+ printHelp(createOptions());
+ } else {
+ returnValue = processActions(cmd);
}
+ } catch (final ParseException e) {
+ log.error("Error processing command line arguments: " + e.getMessage());
+ printHelp(options);
}
+ }
+ return returnValue;
+ }
+
+ private static int determinePort(final CommandLine cmd) {
+ int port = 8080;
+ if (checkOptionWithValue(PORT, cmd)) {
+ port = Integer.parseInt(cmd.getOptionValue(PORT.getOpt()));
+ }
+ return port;
+ }
+
+ private static int determineThreads(final CommandLine cmd) {
+ int threads = Runtime.getRuntime().availableProcessors();
+ if (checkOptionWithValue(WORKER_COUNT, cmd)) {
+ threads = Integer.parseInt(cmd.getOptionValue(WORKER_COUNT.getOpt()));
+ }
+ return threads;
+ }
+
+ private static String determineHost(final CommandLine cmd) {
+ String host = "localhost";
+ if (checkOptionWithValue(HOST, cmd)) {
+ host = cmd.getOptionValue(HOST.getOpt());
+ }
+ return host;
+ }
+
+ private static int startDaemonMode(final CommandLine cmd) {
+ final Option[] unavailable = new Option[] { PRINT, CHECK_ASSERTIONS, DEBUG, OUTPUT, EXTRACT_HTML };
+ warnUnusedOptions(cmd, unavailable, true);
+ final Daemon validDaemon = new Daemon(determineDefinition(cmd), determineRepository(cmd), determineHost(cmd), determinePort(cmd),
+ determineThreads(cmd));
+ validDaemon.startServer();
+ return DAEMON_SIGNAL;
+ }
+
+ private static void warnUnusedOptions(final CommandLine cmd, final Option[] unavailable, final boolean daemon) {
+ Arrays.stream(cmd.getOptions()).filter(o -> ArrayUtils.contains(unavailable, o))
+ .map(o -> "The option " + o.getLongOpt() + " is not available in daemon mode").forEach(log::error);
+ if (daemon && !cmd.getArgList().isEmpty()) {
+ log.info("Ignoring test targets in daemon mode");
+ }
+ }
+
+ private static boolean isHelpRequested(final String[] args) {
+ final Options helpOptions = createHelpOptions();
+ try {
+ final CommandLineParser parser = new DefaultParser();
+ final CommandLine cmd = parser.parse(helpOptions, args, true);
+ if (cmd.hasOption(HELP.getOpt()) || args.length == 0) {
+ return true;
+ }
+ } catch (final ParseException e) {
+ // we can ignore that, we just look for the help parameters
+ }
+ return false;
+ }
+
+ private static int processActions(final CommandLine cmd) {
+ try {
+
+ long start = System.currentTimeMillis();
+ final Option[] unavailable = new Option[] { HOST, PORT, WORKER_COUNT };
+ warnUnusedOptions(cmd, unavailable, false);
+ final CheckConfiguration d = new CheckConfiguration(determineDefinition(cmd));
+ d.setScenarioRepository(determineRepository(cmd));
+ final InternalCheck check = new InternalCheck(d);
+ final Path outputDirectory = determineOutputDirectory(cmd);
+
+ if (cmd.hasOption(EXTRACT_HTML.getOpt())) {
+ check.getCheckSteps().add(new ExtractHtmlContentAction(check.getContentRepository(), outputDirectory));
+ }
+ check.getCheckSteps().add(new SerializeReportAction(outputDirectory));
+ if (cmd.hasOption(SERIALIZE_REPORT_INPUT.getOpt())) {
+ check.getCheckSteps().add(new SerializeReportInputAction(outputDirectory, check.getConversionService()));
+ }
+ if (cmd.hasOption(PRINT.getOpt())) {
+ check.getCheckSteps().add(new PrintReportAction());
+ }
+
+ if (cmd.hasOption(CHECK_ASSERTIONS.getOpt())) {
+ final Assertions assertions = loadAssertions(cmd.getOptionValue(CHECK_ASSERTIONS.getOpt()));
+ check.getCheckSteps().add(new CheckAssertionAction(assertions, ObjectFactory.createProcessor()));
+ }
+ if (cmd.hasOption(PRINT_MEM_STATS.getOpt())) {
+ check.getCheckSteps().add(new PrintMemoryStats());
+ }
+
+ log.info("Setup completed in {}ms\n", System.currentTimeMillis() - start);
+
+ final Collection targets = determineTestTargets(cmd);
+ start = System.currentTimeMillis();
+ for (final Path p : targets) {
+ final Input input = InputFactory.read(p);
+ check.checkInput(input);
+ }
+ final boolean result = check.printAndEvaluate();
+ log.info("Processing {} object(s) completed in {}ms", targets.size(), System.currentTimeMillis() - start);
+ return result ? 0 : 1;
} catch (final Exception e) {
- writeErr("Error processing command line arguments: {0}", e.getMessage(), e);
- resultStatus = ReturnValue.PARSING_ERROR;
+ if (cmd.hasOption(DEBUG.getOpt())) {
+ log.error(e.getMessage(), e);
+ } else {
+ log.error(e.getMessage());
+ }
+ return -1;
}
- return resultStatus;
}
- // The signature is required, because the method is used a lambda
- @SuppressWarnings("unused")
- private static int logExecutionException(final Exception ex, final CommandLine cli, final ParseResult parseResult) {
- final String message = isNotEmpty(ex.getMessage()) ? ex.getMessage() : "Es ist eine Fehler aufgetreten";
- Printer.writeErr(ex, message);
- return 1;
+ private static Assertions loadAssertions(final String optionValue) {
+ final Path p = Paths.get(optionValue);
+ Assertions a = null;
+ if (Files.exists(p)) {
+ final ConversionService c = new ConversionService();
+ c.initialize(de.kosit.validationtool.cmd.assertions.ObjectFactory.class.getPackage());
+ a = c.readXml(p.toUri(), Assertions.class);
+ }
+ return a;
}
- enum Level {
+ private static Path determineOutputDirectory(final CommandLine cmd) {
+ final String value = cmd.getOptionValue(OUTPUT.getOpt());
+ final Path fir;
+ if (StringUtils.isNotBlank(value)) {
+ fir = Paths.get(value);
+ if ((!Files.exists(fir) && !fir.toFile().mkdirs()) || !Files.isDirectory(fir)) {
+ throw new IllegalStateException(String.format("Invalid target directory %s specified", value));
+ }
+ } else {
+ fir = Paths.get(""/* cwd */);
+ }
+ return fir;
+ }
- INFO, WARN, DEBUG, TRACE, ERROR, OFF;
+ private static Collection determineTestTargets(final CommandLine cmd) {
+ final Collection targets = new ArrayList<>();
+ if (!cmd.getArgList().isEmpty()) {
+ cmd.getArgList().forEach(e -> targets.addAll(determineTestTarget(e)));
+ }
+ if (targets.isEmpty()) {
+ throw new IllegalStateException("No test targets found. Nothing to check. Will quit now!");
+ }
+ return targets;
+ }
+
+ private static Collection determineTestTarget(final String s) {
+ final Path d = Paths.get(s);
+ if (Files.isDirectory(d)) {
+ return listDirectoryTargets(d);
+ } else if (Files.exists(d)) {
+ return Collections.singleton(d);
+ }
+ log.warn("The specified test target {} does not exist. Will be ignored", s);
+ return Collections.emptyList();
}
+ private static Collection listDirectoryTargets(final Path d) {
+ try {
+ return Files.list(d).filter(path -> path.toString().endsWith(".xml")).collect(Collectors.toList());
+ } catch (final IOException e) {
+ throw new IllegalStateException("IOException while list directory content. Can not determine test targets.", e);
+ }
+
+ }
+
+ private static URI determineRepository(final CommandLine cmd) {
+ if (checkOptionWithValue(REPOSITORY, cmd)) {
+ final Path d = Paths.get(cmd.getOptionValue(REPOSITORY.getOpt()));
+ if (Files.isDirectory(d)) {
+ return d.toUri();
+ } else {
+ throw new IllegalArgumentException(
+ String.format("Not a valid path for repository definition specified: '%s'", d.toAbsolutePath()));
+ }
+ }
+ return null;
+ }
+
+ private static URI determineDefinition(final CommandLine cmd) {
+ checkOptionWithValue(SCENARIOS, cmd);
+ final Path f = Paths.get(cmd.getOptionValue(SCENARIOS.getOpt()));
+ if (Files.isRegularFile(f)) {
+ return f.toAbsolutePath().toUri();
+ } else {
+ throw new IllegalArgumentException(
+ String.format("Not a valid path for scenario definition specified: '%s'", f.toAbsolutePath()));
+ }
+ }
+
+ private static boolean checkOptionWithValue(final Option option, final CommandLine cmd) {
+ final String opt = option.getOpt();
+ if (cmd.hasOption(opt)) {
+ final String value = cmd.getOptionValue(opt);
+ if (StringUtils.isNoneBlank(value)) {
+ return true;
+ } else {
+ throw new IllegalArgumentException(String.format("Option value required for Option '%s'", option.getLongOpt()));
+ }
+ } else if (option.isRequired()) {
+
+ throw new IllegalArgumentException(String.format("Option '%s' required ", option.getLongOpt()));
+ }
+ return false;
+ }
+
+ private static void printHelp(final Options options) {
+ // automatically generate the help statement
+ final HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("check-tool -s [OPTIONS] [FILE]... ", options, false);
+ }
+
+ private static Options createHelpOptions() {
+ final Options options = new Options();
+ options.addOption(HELP);
+ return options;
+ }
+
+ private static Options createOptions() {
+ final Options options = new Options();
+ options.addOption(HELP);
+ options.addOption(SERVER);
+ options.addOption(HOST);
+ options.addOption(PORT);
+ options.addOption(SCENARIOS);
+ options.addOption(REPOSITORY);
+ options.addOption(PRINT);
+ options.addOption(OUTPUT);
+ options.addOption(EXTRACT_HTML);
+ options.addOption(DEBUG);
+ options.addOption(CHECK_ASSERTIONS);
+ options.addOption(PRINT_MEM_STATS);
+ options.addOption(WORKER_COUNT);
+ return options;
+ }
}
diff --git a/src/main/java/de/kosit/validationtool/cmd/CommandLineOptions.java b/src/main/java/de/kosit/validationtool/cmd/CommandLineOptions.java
deleted file mode 100644
index 99cab94..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/CommandLineOptions.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd;
-
-import java.nio.file.Path;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import de.kosit.validationtool.cmd.CommandLineApplication.Level;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import picocli.CommandLine.ArgGroup;
-import picocli.CommandLine.Command;
-import picocli.CommandLine.Help.Visibility;
-import picocli.CommandLine.Option;
-import picocli.CommandLine.Parameters;
-
-/**
- * Commandline Interface definition.
- *
- * @author Andreas Penski
- */
-@Command(description = "Structural and semantic validation of xml files", name = "KoSIT Validator", mixinStandardHelpOptions = false,
- separator = " ", synopsisHeading = CommandLineOptions.SYNOSIS_HEADING)
-@Getter
-public class CommandLineOptions implements Callable {
-
- static final String SYNOSIS_HEADING = "Usage: ";
-
- /**
- * @author Andreas Penski
- */
- @Getter
- @NoArgsConstructor
- static class DaemonOptions {
-
- @Option(names = { "-D", "--daemon" }, description = "Starts a daemon listing for validation requests", defaultValue = "false",
- required = true)
- private boolean daemonMode;
-
- @Option(names = { "-H", "--host" }, description = "The hostname / IP address to bind the daemon.", defaultValue = "localhost",
- showDefaultValue = Visibility.ALWAYS)
- private String host;
-
- @Option(names = { "-P", "--port" }, description = "The port to bind the daemon.", defaultValue = "8080",
- showDefaultValue = Visibility.ALWAYS)
- private int port;
-
- @Option(names = { "-T", "--threads" },
- description = "Number of threads processing validation requests. Default depends on processor count", defaultValue = "-1",
- showDefaultValue = Visibility.NEVER)
- private int workerCount;
-
- @Option(names = { "-G", "--disable-gui" }, description = "Disables the GUI of the daemon mode")
- private boolean disableGUI;
- }
-
- /**
- * @author Andreas Penski
- */
- @Getter
- @NoArgsConstructor
- static class CliOptions {
-
- @Option(names = { "-o", "--output-directory" }, description = "Defines the out directory for results.", defaultValue = ".",
- required = true)
- private Path outputPath;
-
- @Option(names = { "-h", "--html", "--extract-html" },
- description = "Extract and save any html content within result as a separate file")
- private boolean extractHtml;
-
- @Option(names = { "--serialize-report-input" }, description = "Serializes the report input to the cwd", defaultValue = "false")
- private boolean serializeInput;
-
- @Option(names = { "-c", "--check-assertions" }, paramLabel = "assertions-file",
- description = "Check the result using defined assertions")
- private Path assertions;
-
- @Option(names = { "--report-postfix" }, description = "Postfix of the generated report name")
- private String reportPostfix;
-
- @Option(names = { "--report-prefix" }, description = "Prefix of the generated report name")
- private String reportPrefix;
-
- @Option(names = { "-m", "--memory-stats" }, description = "Prints some memory stats")
- private boolean printMemoryStats;
-
- @Option(names = { "-p", "--print" }, description = "Prints the check result to stdout")
- private boolean printReport;
-
- @Parameters(arity = "1..*", description = "Files to validate")
- private List files;
-
- }
-
- /**
- * Definition of logical name and a path for a configuration artifact.
- *
- * @author Andreas Penski
- */
- @Getter
- @Setter
- public abstract static class Definition {
-
- String name;
-
- Path path;
- }
-
- /**
- * Definition of logical name and a path for a repository.
- *
- * @author Andreas Penski
- */
- public static class RepositoryDefinition extends Definition {
- // just for type safety
- }
-
- /**
- * Definition of logical name and a path for a scenario configuration file.
- *
- * @author Andreas Penski
- */
- public static class ScenarioDefinition extends Definition {
- // just for type safety
- }
-
- @ArgGroup(exclusive = false, heading = "Daemon options\n")
- private DaemonOptions daemonOptions;
-
- @ArgGroup(exclusive = false, heading = "CLI usage options\n")
- private CliOptions cliOptions;
-
- @Option(names = { "-d", "--debug" }, description = "Prints some more debug information")
- private boolean debugOutput;
-
- @Option(names = { "-?", "--help" }, usageHelp = true, description = "display this help message")
- boolean usageHelpRequested;
-
- @Option(names = { "-X", "--debug-logging" }, description = "Enables full debug log. Alias for -l debug")
- private boolean debugLog;
-
- @Option(names = { "-l", "--log-level" }, description = "Enables a certain log level for debugging purposes", defaultValue = "OFF")
- private Level logLevel;
-
- @Option(names = { "-r", "--repository" }, paramLabel = "repository-path", description = "Directory containing scenario content",
- converter = TypeConverter.RepositoryConverter.class)
- private List repositories;
-
- @Option(names = { "-s", "--scenarios" }, description = "Location of scenarios.xml", paramLabel = "scenario.xml", required = true,
- converter = TypeConverter.ScenarioConverter.class)
- private List scenarios;
-
- @Override
- public ReturnValue call() throws Exception {
- configureLogging(this);
- return Validator.mainProgram(this);
- }
-
- private static void configureLogging(final CommandLineOptions cmd) {
- if (cmd.isDebugLog()) {
- System.setProperty(org.slf4j.simple.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "DEBUG");
- } else {
- System.setProperty(org.slf4j.simple.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, cmd.getLogLevel().name());
- }
- }
-
- public boolean isDaemonModeEnabled() {
- return getDaemonOptions() != null;
- }
-
- public boolean isCliModeEnabled() {
- return getCliOptions() != null;
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/cmd/Daemon.java b/src/main/java/de/kosit/validationtool/cmd/Daemon.java
new file mode 100644
index 0000000..0bfaf87
--- /dev/null
+++ b/src/main/java/de/kosit/validationtool/cmd/Daemon.java
@@ -0,0 +1,198 @@
+package de.kosit.validationtool.cmd;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+import de.kosit.validationtool.api.Check;
+import de.kosit.validationtool.api.CheckConfiguration;
+import de.kosit.validationtool.api.Input;
+import de.kosit.validationtool.api.InputFactory;
+import de.kosit.validationtool.impl.DefaultCheck;
+import de.kosit.validationtool.impl.ObjectFactory;
+import de.kosit.validationtool.model.scenarios.Scenarios;
+
+/**
+ * HTTP-Daemon für die Bereitstellung der Prüf-Funktionalität via http.
+ *
+ * @author Roula Antoun
+ */
+@RequiredArgsConstructor
+@Setter
+@Getter
+@Slf4j
+class Daemon {
+
+ /**
+ * Wir benötigen einen Handler, der zur Verarbeitung von HTTP-Anforderungen aufgerufen wird um hier die Verarbeitung des
+ * POST Request zu realisieren.
+ */
+ @Slf4j
+ private static class HttpServerHandler implements HttpHandler {
+
+ private static final AtomicLong counter = new AtomicLong(0);
+
+ private final Check implemenation;
+
+ HttpServerHandler(Check check) {
+ this.implemenation = check;
+ }
+
+ /**
+ * Methode, die eine gegebene Anforderung verarbeitet und eine entsprechende Antwort generiert
+ *
+ * @param httpExchange kapselt eine empfangene HTTP-Anforderung und eine Antwort, die in einem Exchange generiert werden
+ * soll.
+ */
+ @Override
+ public void handle(HttpExchange httpExchange) throws IOException {
+ try {
+ log.debug("Incoming request");
+ String requestMethod = httpExchange.getRequestMethod();
+ if (requestMethod.equals("POST")) {
+ InputStream inputStream = httpExchange.getRequestBody();
+ Input serverInput = InputFactory.read(inputStream, "Prüfling" + counter.incrementAndGet());
+
+ int contentLength = serverInput.getContent().length;
+ if (contentLength != 0) {
+ writeOutputstreamArray(httpExchange, implemenation.check(serverInput));
+ } else {
+ writeError(httpExchange, 400, "XML-Inhalt erforderlich!");
+ }
+ } else {
+ writeError(httpExchange, 405, "Es ist nur die POST-Methode erlaubt!");
+ }
+ } catch (Exception e) {
+ writeError(httpExchange, 500, "Interner Fehler bei der Verarbeitung des Requests: " + e.getMessage());
+ log.error("Es ist ein Fehler aufgetreten. Das Dokument kann nicht geprüft werden", e);
+ }
+ }
+
+ }
+
+ /**
+ * Wir benötigen einen Handler, der zur Verarbeitung von HTTP-Anforderungen aufgerufen wird , und hier für Verarbeitung
+ * das GET Request um Health-Endpunkt zu erstellen. Die Klasse HealthHandler implementiert diese Schnittstelle
+ */
+ @Slf4j
+ static class HealthHandler implements HttpHandler {
+
+ private final Scenarios scenarios;
+
+ HealthHandler(Scenarios scenarios) {
+ this.scenarios = scenarios;
+ }
+
+ @Override
+ public void handle(HttpExchange httpExchange) throws IOException {
+ Health health = new Health(scenarios);
+ Document doc = health.writeHealthXml();
+ try {
+ writeOutputstreamArray(httpExchange, doc);
+ } catch (TransformerException e) {
+ writeError(httpExchange, 500, e.getMessage());
+ log.error("Fehler beim Erzeugen der Status-Information", e);
+ }
+ }
+ }
+
+ private final URI scenarioDefinition;
+
+ private final URI repository;
+
+ private final String hostName;
+
+ private final int port;
+
+ private final int threadCount;
+
+ /**
+ * Methode, die die Antwort als String-Text schreibt
+ *
+ * @param httpExchange um den Antwort Body zu erhalten
+ * @param rCode der Code-Status
+ * @param response die String antwort, die ich anzeigen möchte
+ */
+ private static void writeError(HttpExchange httpExchange, int rCode, String response) throws IOException {
+ httpExchange.sendResponseHeaders(rCode, response.length());
+ OutputStream os = httpExchange.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ }
+
+ /**
+ * Methode, die die Antwort als String-Text schreibt
+ *
+ * @param httpExchange um den Antwort Body zu erhalten
+ * @param doc der Report
+ */
+ private static void writeOutputstreamArray(HttpExchange httpExchange, Document doc) throws IOException, TransformerException {
+ final byte[] bytes = serialize(doc);
+ OutputStream os = httpExchange.getResponseBody();
+ httpExchange.getResponseHeaders().add("Content-Type", "application/xml");
+ httpExchange.sendResponseHeaders(200, bytes.length);
+ os.write(bytes);
+ os.close();
+ log.debug("Xml File erzeugen ist Fertig ");
+ }
+
+ /**
+ * Methode zum Serialisieren des Dokuments.
+ *
+ * @param report Vom Typ Dokument, aka Report .
+ */
+ private static byte[] serialize(Document report) throws TransformerException {
+
+ try ( ByteArrayOutputStream bArrayOS = new ByteArrayOutputStream() ) {
+ DOMSource source = new DOMSource(report);
+ StreamResult streamResult = new StreamResult(bArrayOS);
+ Transformer transformer = ObjectFactory.createTransformer(true);
+ transformer.transform(source, streamResult);
+ return bArrayOS.toByteArray();
+ } catch (IOException e) {
+ log.error("Report {}", e.getMessage(), e);
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Methode zum Starten des Servers
+ */
+ void startServer() {
+ CheckConfiguration config = new CheckConfiguration(scenarioDefinition);
+ config.setScenarioRepository(repository);
+ HttpServer server = null;
+ try {
+ server = HttpServer.create(new InetSocketAddress(hostName, port), 0);
+ DefaultCheck check = new DefaultCheck(config);
+ server.createContext("/", new HttpServerHandler(check));
+ server.createContext("/health", new HealthHandler(check.getRepository().getScenarios()));
+ server.setExecutor(Executors.newFixedThreadPool(threadCount));
+ server.start();
+ log.info("Server unter Port {} ist erfolgreich gestartet", port);
+ } catch (IOException e) {
+ log.error("Fehler beim HttpServer erstellen!", e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/main/java/de/kosit/validationtool/cmd/DefaultNamingStrategy.java b/src/main/java/de/kosit/validationtool/cmd/DefaultNamingStrategy.java
deleted file mode 100644
index e5aca79..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/DefaultNamingStrategy.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd;
-
-import static org.apache.commons.io.FilenameUtils.isExtension;
-import static org.apache.commons.lang3.StringUtils.isEmpty;
-import static org.apache.commons.lang3.StringUtils.isNotEmpty;
-
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.lang3.StringUtils;
-
-import lombok.Setter;
-
-/**
- * A default {@link NamingStrategy} supporting prefix and postfix configurations for generating report names
- *
- * @author Andreas Penski
- */
-@Setter
-public class DefaultNamingStrategy implements NamingStrategy {
-
- private String prefix;
-
- private String postfix;
-
- @Override
- public String createName(final String name) {
- if (StringUtils.isEmpty(name)) {
- throw new IllegalArgumentException("Can not generate name based on null input");
- }
- final String base = isExtension(name.toLowerCase(), "xml") ? FilenameUtils.getBaseName(name) : name;
- final StringBuilder result = new StringBuilder();
- if (isNotEmpty(this.prefix)) {
- result.append(this.prefix).append("-");
- }
- result.append(base);
- if (isNotEmpty(this.postfix)) {
- result.append("-").append(this.postfix);
- } else if (isEmpty(this.prefix)) {
- result.append("-").append("report");
- }
- result.append(".xml");
- return result.toString();
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/cmd/ExtractHtmlContentAction.java b/src/main/java/de/kosit/validationtool/cmd/ExtractHtmlContentAction.java
index cf4ab86..09e84b6 100644
--- a/src/main/java/de/kosit/validationtool/cmd/ExtractHtmlContentAction.java
+++ b/src/main/java/de/kosit/validationtool/cmd/ExtractHtmlContentAction.java
@@ -1,17 +1,20 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.cmd;
@@ -21,10 +24,10 @@ import java.nio.file.Path;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import de.kosit.validationtool.impl.ContentRepository;
import de.kosit.validationtool.impl.HtmlExtractor;
import de.kosit.validationtool.impl.tasks.CheckAction;
-import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
@@ -46,12 +49,12 @@ class ExtractHtmlContentAction implements CheckAction {
private HtmlExtractor htmlExtraction;
- private Processor processor;
+ private ContentRepository repository;
- public ExtractHtmlContentAction(final Processor p, final Path outputDirectory) {
+ public ExtractHtmlContentAction(final ContentRepository repository, final Path outputDirectory) {
this.outputDirectory = outputDirectory;
- this.htmlExtraction = new HtmlExtractor(p);
- this.processor = p;
+ this.htmlExtraction = new HtmlExtractor(repository);
+ this.repository = repository;
}
@Override
@@ -63,12 +66,12 @@ class ExtractHtmlContentAction implements CheckAction {
final XdmNode node = (XdmNode) xdmItem;
final String name = origName + "-" + node.getAttributeValue(NAME_ATTRIBUTE);
final Path file = this.outputDirectory.resolve(name + ".html");
- final Serializer serializer = this.processor.newSerializer(file.toFile());
+ final Serializer serializer = this.repository.getProcessor().newSerializer(file.toFile());
try {
log.info("Writing report html '{}' to {}", name, file.toAbsolutePath());
serializer.serializeNode(node);
} catch (final SaxonApiException e) {
- log.error("Error extracting html content to {}", file.toAbsolutePath(), e);
+ log.info("Error extracting html content to {}", file.toAbsolutePath(), e);
}
}
diff --git a/src/main/java/de/kosit/validationtool/cmd/Health.java b/src/main/java/de/kosit/validationtool/cmd/Health.java
new file mode 100644
index 0000000..e3056a6
--- /dev/null
+++ b/src/main/java/de/kosit/validationtool/cmd/Health.java
@@ -0,0 +1,117 @@
+package de.kosit.validationtool.cmd;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import lombok.extern.slf4j.Slf4j;
+
+import de.kosit.validationtool.model.scenarios.Scenarios;
+
+/**
+ * Klasse zur Erzeugung Health Xml , die optiamle Status.
+ *
+ * @author Roula Antoun
+ */
+@Slf4j
+class Health {
+
+ private final long freeMemory;
+
+ private final long maxMemory;
+
+ private final long totalMemory;
+
+ private final Scenarios scenarios;
+
+ Health(Scenarios scenarios) {
+
+ Runtime runtime = Runtime.getRuntime();
+ freeMemory = runtime.freeMemory();
+ maxMemory = runtime.maxMemory();
+ totalMemory = runtime.totalMemory();
+ this.scenarios = scenarios;
+ }
+
+ /**
+ * Methode, die schreibt das Health Xml für optimale Status
+ *
+ */
+ Document writeHealthXml() {
+ DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder dBuilder;
+ Document doc = null;
+ try {
+ dBuilder = dbFactory.newDocumentBuilder();
+ doc = dBuilder.newDocument();
+ Element rootElement = doc.createElementNS("https://localhost:8080/Health", "Health");
+ doc.appendChild(rootElement);
+ rootElement.appendChild(getMemory(doc, freeMemory, maxMemory, totalMemory));
+ rootElement.appendChild(getState(doc));
+ rootElement.appendChild(getScenario(doc, scenarios));
+ } catch (ParserConfigurationException e) {
+ log.error("Fehler beim Schreiben der Status-Informationen", e);
+ }
+ return doc;
+ }
+
+ /**
+ * Methode, die schreibt das System Status Node im Xml File
+ *
+ * @param doc Vom Typ Dokument.
+ *
+ */
+ private Node getState(Document doc) {
+ Element state = doc.createElement("state");
+ state.setAttribute("indicator", "OK");
+ Element stateNode = doc.createElement("message");
+ stateNode.appendChild(doc.createTextNode("System is up and running normally"));
+ state.appendChild(stateNode);
+ return state;
+ }
+
+ /**
+ * Methode, die schreibt das Scnarios Information Node im Xml File
+ *
+ * @param doc Vom Typ Dokument .
+ * @param scenarios Vom Typ {@link Scenarios} das verwendete scenario.
+ *
+ */
+ private Node getScenario(Document doc, Scenarios scenarios) {
+ Element scenario = doc.createElement("scenario");
+ Element scenarioNameNode = doc.createElement("name");
+ scenarioNameNode.appendChild(doc.createTextNode(scenarios.getName()));
+ scenario.appendChild(scenarioNameNode);
+ return scenario;
+ }
+
+ /**
+ * Methode, die schreibt das Scnarios Information Node im Xml File
+ *
+ * @param doc Vom Typ Dokument .
+ * @param freeMemory Vom Typ long , der freier Speicher.
+ * @param maxMemory Vom Typ long , der maximaler Speicher
+ * @param totalMemory Vom Typ long , der Gesamte speicher.
+ *
+ */
+ private static Node getMemory(Document doc, long freeMemory, long maxMemory, long totalMemory) {
+ Element memory = doc.createElement("memoryState");
+ String freeM = Long.toString(freeMemory);
+ Element freeMNode = doc.createElement("freeMemory");
+ freeMNode.appendChild(doc.createTextNode(freeM));
+ memory.appendChild(freeMNode);
+ String maxM = Long.toString(maxMemory);
+ Element maxMNode = doc.createElement("maxMemory");
+ maxMNode.appendChild(doc.createTextNode(maxM));
+ memory.appendChild(maxMNode);
+ String totalM = Long.toString(totalMemory);
+ Element totalMNode = doc.createElement("totalMemory");
+ totalMNode.appendChild(doc.createTextNode(totalM));
+ memory.appendChild(totalMNode);
+ return memory;
+ }
+}
diff --git a/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java b/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java
index 6c27a2e..db9a7b1 100644
--- a/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java
+++ b/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java
@@ -1,47 +1,35 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.cmd;
-import java.io.PrintWriter;
-import java.text.MessageFormat;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.stream.Collectors;
-
-import org.fusesource.jansi.AnsiRenderer.Code;
-
import lombok.extern.slf4j.Slf4j;
-import de.kosit.validationtool.api.Configuration;
+import de.kosit.validationtool.api.CheckConfiguration;
import de.kosit.validationtool.api.Input;
import de.kosit.validationtool.api.Result;
-import de.kosit.validationtool.api.XmlError;
-import de.kosit.validationtool.cmd.report.Grid;
-import de.kosit.validationtool.cmd.report.Grid.ColumnDefinition;
-import de.kosit.validationtool.cmd.report.Justify;
-import de.kosit.validationtool.cmd.report.Line;
import de.kosit.validationtool.impl.DefaultCheck;
import de.kosit.validationtool.impl.tasks.CheckAction;
-import net.sf.saxon.s9api.Processor;
-
/**
- * Simple Erweiterung der Klasse {@link DefaultCheck} um das Ergebnis der Assertion-Prüfung auszuwerten und auszugeben.
- * Diese Klasse stellt keine fachliche Erweiterung des eigentlichen Prüfvorganges dar!
+ * Simple Erweiterung der Klasse {@link DefaultCheck} um das Ergebnis der Assertion-Prüfung auszwerten und auszugeben.
+ * Diese Klasse stellt keine fachlicher Erweiterung des eigentlichen Prüfvorganges dar!
*
* @author Andreas Penski
*/
@@ -57,63 +45,13 @@ class InternalCheck extends DefaultCheck {
*
* @param configuration die Konfiguration
*/
- InternalCheck(final Processor processor, final Configuration... configuration) {
- super(processor, configuration);
- }
-
- private static String createStatusLine(final Map results) {
- final long acceptable = results.entrySet().stream().filter(e -> e.getValue().isAcceptable()).count();
- final long rejected = results.entrySet().stream().filter(e -> !e.getValue().isAcceptable()).count();
- final long errors = results.entrySet().stream().filter(e -> !e.getValue().isProcessingSuccessful()).count();
- final Line line = new Line();
- line.add("Acceptable: ").add(acceptable, Code.GREEN);
- line.add(" Rejected: ").add(rejected, Code.RED);
- if (errors > 0) {
- line.add(" Processing errors: ").add(errors, Code.RED);
- }
- return line.render(true, false);
- }
-
- private static Grid createResultGrid(final Map results) {
- final Grid grid = new Grid(
- //@formatter:off
- new ColumnDefinition("File", 60, 10, 1),
- new ColumnDefinition("Schema", 7).justify(Justify.CENTER),
- new ColumnDefinition("Schematron", 10).justify(Justify.CENTER),
- new ColumnDefinition("Acceptance", 10, 5).justify(Justify.CENTER),
- new ColumnDefinition("Error/Description", 60,20,3)
- );
- //@formatter:on
- results.entrySet().stream().sorted(Entry.comparingByKey()).forEach(e -> {
- final Result value = e.getValue();
-
- final Code textcolor = value.isAcceptable() ? Code.GREEN : Code.RED;
- grid.addCell(e.getKey(), textcolor);
- grid.addCell(value.isSchemaValid() ? "Y" : "N", textcolor);
- grid.addCell(value.isSchematronValid() ? "Y" : "N", textcolor);
- grid.addCell(value.getAcceptRecommendation(), textcolor);
- grid.addCell(joinErrors(value));
- });
- return grid;
- }
-
- private static String joinErrors(final Result value) {
- final StringBuilder b = new StringBuilder();
- b.append(String.join(";", value.getProcessingErrors()));
- if (value.getSchemaViolations() != null && !value.getSchemaViolations().isEmpty()) {
- b.append(b.length() > 0 ? ";" : "");
- b.append(value.getSchemaViolations().stream().map(XmlError::getMessage).collect(Collectors.joining(";")));
- }
- if (value.getSchematronResult() != null && !value.getSchematronResult().isEmpty()) {
- b.append(b.length() > 0 ? ";" : "");
- b.append(value.getSchematronResult().stream().flatMap(e -> e.getMessages().stream()).collect(Collectors.joining(";")));
- }
- return b.toString();
+ InternalCheck(final CheckConfiguration configuration) {
+ super(configuration);
}
/**
* Prüft die Prüflinge und gibt Informationen über etwaige Assertions aus.
- *
+ *
* @param input die Prüflinge
* @return false wenn es Assertion-Fehler gibt, sonst true
*/
@@ -128,40 +66,15 @@ class InternalCheck extends DefaultCheck {
return result;
}
- void printResults(final Map results) {
- final PrintWriter writer = new PrintWriter(System.out);// NOSONAR
- writer.write("Results:\n");
- writer.write(createResultGrid(results).render());
- writer.write(createStatusLine(results));
- writer.write(createAssertionStatus());
- writer.flush();
- }
-
- private String createAssertionStatus() {
- final Line line = new Line();
+ boolean printAndEvaluate() {
if (this.failedAssertions > 0) {
log.error("Assertion check failed.\n\nAssertions run: {}, Assertions failed: {}\n", this.checkAssertions,
this.failedAssertions);
- line.add(MessageFormat.format("Assertions run: {0}, Assertions failed: ", this.checkAssertions));
- line.add(this.failedAssertions, Code.RED);
} else if (this.checkAssertions > 0) {
log.info("Assertion check successful.\n\nAssertions run: {}, Assertions failed: {}\n", this.checkAssertions,
this.failedAssertions);
- line.add(MessageFormat.format("Assertions run: {0}, Assertions failed: {1}", this.checkAssertions, this.failedAssertions));
}
- return line.render(true, false);
- }
-
- @Override
- public boolean isSuccessful(final Map results) {
- if (this.checkAssertions > 0) {
- return this.failedAssertions == 0;
- }
- return super.isSuccessful(results);
- }
-
- public int getNotAcceptableCount(final Map results) {
- return (int) (this.failedAssertions + results.values().stream().filter(e -> !e.isAcceptable()).count());
+ return this.failedAssertions == 0;
}
}
diff --git a/src/main/java/de/kosit/validationtool/cmd/NamingStrategy.java b/src/main/java/de/kosit/validationtool/cmd/NamingStrategy.java
deleted file mode 100644
index af83eb7..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/NamingStrategy.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd;
-
-/**
- * Strategy for creating names. This is used for generating the report result name.
- *
- * @author Andreas Penski
- */
-public interface NamingStrategy {
-
- /**
- * Create a name based on a base name
- *
- * @param base the base name
- * @return the generated name
- */
- String createName(String base);
-}
diff --git a/src/main/java/de/kosit/validationtool/cmd/PrintMemoryStats.java b/src/main/java/de/kosit/validationtool/cmd/PrintMemoryStats.java
index dedd5cc..313acd7 100644
--- a/src/main/java/de/kosit/validationtool/cmd/PrintMemoryStats.java
+++ b/src/main/java/de/kosit/validationtool/cmd/PrintMemoryStats.java
@@ -1,17 +1,20 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.cmd;
diff --git a/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java b/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java
index f9de289..2c3faa2 100644
--- a/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java
+++ b/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java
@@ -1,30 +1,31 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.cmd;
import java.io.StringWriter;
-import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import de.kosit.validationtool.impl.Printer;
+import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.tasks.CheckAction;
-import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
@@ -34,19 +35,16 @@ import net.sf.saxon.s9api.Serializer;
* @author Andreas Penski
*/
@Slf4j
-@RequiredArgsConstructor
class PrintReportAction implements CheckAction {
- private final Processor processor;
-
@Override
- public void check(final Bag results) {
+ public void check(Bag results) {
try {
final StringWriter writer = new StringWriter();
- final Serializer serializer = this.processor.newSerializer(writer);
+ final Serializer serializer = ObjectFactory.createProcessor().newSerializer(writer);
serializer.serializeNode(results.getReport());
- Printer.writeOut(writer.toString());
- } catch (final SaxonApiException e) {
+ System.out.print(writer.toString());
+ } catch (SaxonApiException e) {
log.error("Error while printing result to stdout", e);
}
}
diff --git a/src/main/java/de/kosit/validationtool/cmd/ReturnValue.java b/src/main/java/de/kosit/validationtool/cmd/ReturnValue.java
deleted file mode 100644
index 04aa4bd..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/ReturnValue.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-/**
- * CLI return codes. Codes > 0 indicate a processing error. Codes < 0 indicates a configuration error. Code 0
- * indicates a successful processing.
- *
- * @author Andreas Penski
- */
-@RequiredArgsConstructor
-@Getter
-public class ReturnValue {
-
- public static final ReturnValue SUCCESS = new ReturnValue(0);
-
- public static final ReturnValue HELP_REQUEST = new ReturnValue(0);
-
- public static final ReturnValue CONFIGURATION_ERROR = new ReturnValue(-2);
-
- public static final ReturnValue DAEMON_MODE = new ReturnValue(-100);
-
- public static final ReturnValue PARSING_ERROR = new ReturnValue(-1);
-
- private final int code;
-
- public static ReturnValue createFailed(final int count) {
- return new ReturnValue(count);
- }
-
- public boolean isError() {
- return this.code < 0 && this.code != DAEMON_MODE.code;
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/cmd/SerializeReportAction.java b/src/main/java/de/kosit/validationtool/cmd/SerializeReportAction.java
index a03dc99..1c26479 100644
--- a/src/main/java/de/kosit/validationtool/cmd/SerializeReportAction.java
+++ b/src/main/java/de/kosit/validationtool/cmd/SerializeReportAction.java
@@ -1,17 +1,20 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.cmd;
@@ -21,9 +24,9 @@ import java.nio.file.Path;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.tasks.CheckAction;
-import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
@@ -38,24 +41,20 @@ class SerializeReportAction implements CheckAction {
private final Path outputDirectory;
- private final Processor processor;
-
- private final NamingStrategy namingStrategy;
-
@Override
- public void check(final Bag results) {
- final Path file = this.outputDirectory.resolve(this.namingStrategy.createName(results.getName()));
+ public void check(Bag results) {
+ final Path file = outputDirectory.resolve(results.getName() + "-report.xml");
try {
log.info("Serializing result to {}", file.toAbsolutePath());
- final Serializer serializer = this.processor.newSerializer(file.toFile());
+ final Serializer serializer = ObjectFactory.createProcessor().newSerializer(file.toFile());
serializer.serializeNode(results.getReport());
- } catch (final SaxonApiException e) {
+ } catch (SaxonApiException e) {
log.error("Can not serialize result report to {}", file.toAbsolutePath(), e);
}
}
@Override
- public boolean isSkipped(final Bag results) {
+ public boolean isSkipped(Bag results) {
if (results.getReport() == null) {
log.warn("Can not serialize result report. No document found");
return true;
diff --git a/src/main/java/de/kosit/validationtool/cmd/SerializeReportInputAction.java b/src/main/java/de/kosit/validationtool/cmd/SerializeReportInputAction.java
index 506c612..bb58ab7 100644
--- a/src/main/java/de/kosit/validationtool/cmd/SerializeReportInputAction.java
+++ b/src/main/java/de/kosit/validationtool/cmd/SerializeReportInputAction.java
@@ -1,19 +1,3 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package de.kosit.validationtool.cmd;
import java.io.IOException;
diff --git a/src/main/java/de/kosit/validationtool/cmd/TypeConverter.java b/src/main/java/de/kosit/validationtool/cmd/TypeConverter.java
deleted file mode 100644
index cedf29d..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/TypeConverter.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd;
-
-import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
-
-import java.nio.file.Paths;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import de.kosit.validationtool.cmd.CommandLineOptions.Definition;
-import de.kosit.validationtool.cmd.CommandLineOptions.RepositoryDefinition;
-import de.kosit.validationtool.cmd.CommandLineOptions.ScenarioDefinition;
-import de.kosit.validationtool.impl.ScenarioRepository;
-
-import picocli.CommandLine.ITypeConverter;
-
-/**
- * Custom type converters for dealing with command line input.
- *
- * @author Andreas Penski
- */
-class TypeConverter {
-
- final static Map, AtomicInteger> counter = new HashMap<>();
-
- private static String getDefaultName(final Class> type) {
- final AtomicInteger current = counter.computeIfAbsent(type, a -> new AtomicInteger(1));
- return ScenarioRepository.DEFAULT + "_" + current.getAndIncrement();
- }
-
- private static T convert(final Class type, final String value) {
- final T def;
- final String[] splitted = defaultIfBlank(value, "").split("=");
- if (splitted.length == 1) {
- def = createNewInstance(type);
- def.setName(getDefaultName(type));
- def.setPath(Paths.get(splitted[0].trim()));
- } else if (splitted.length == 2) {
- def = createNewInstance(type);
- def.setName(splitted[0].trim());
- def.setPath(Paths.get(splitted[1].trim()));
- } else {
- throw new IllegalArgumentException("Not a valid repository specification " + value);
- }
- return def;
- }
-
- private static T createNewInstance(final Class type) {
- try {
- return type.getConstructor().newInstance();
- } catch (final ReflectiveOperationException e) {
- throw new IllegalStateException("Error creating instance of type " + type);
- }
- }
-
- /**
- * Type converter for a repository definition specification e.g. '-r somelocation.xml OR -r myid=somelocation.xml'
- *
- * @author Andreas Penski
- */
- public static class RepositoryConverter implements ITypeConverter {
-
- @Override
- public RepositoryDefinition convert(final String value) throws Exception {
- return TypeConverter.convert(RepositoryDefinition.class, value);
- }
- }
-
- /**
- * Type converter for a scenario definition specification e.g. '-s somelocation.xml OR -s myid=somelocation.xml'
- *
- * @author Andreas Penski
- */
- public static class ScenarioConverter implements ITypeConverter {
-
- @Override
- public ScenarioDefinition convert(final String value) throws Exception {
- return TypeConverter.convert(ScenarioDefinition.class, value);
- }
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/cmd/Validator.java b/src/main/java/de/kosit/validationtool/cmd/Validator.java
deleted file mode 100644
index 3384768..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/Validator.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd;
-
-import static org.apache.commons.lang3.ObjectUtils.getIfNull;
-import static org.apache.commons.lang3.StringUtils.EMPTY;
-import static org.apache.commons.lang3.StringUtils.isNotEmpty;
-
-import java.io.IOException;
-import java.net.URI;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.fusesource.jansi.AnsiRenderer.Code;
-
-import de.kosit.validationtool.api.Configuration;
-import de.kosit.validationtool.api.Input;
-import de.kosit.validationtool.api.InputFactory;
-import de.kosit.validationtool.api.Result;
-import de.kosit.validationtool.cmd.CommandLineOptions.CliOptions;
-import de.kosit.validationtool.cmd.CommandLineOptions.RepositoryDefinition;
-import de.kosit.validationtool.cmd.CommandLineOptions.ScenarioDefinition;
-import de.kosit.validationtool.cmd.assertions.Assertions;
-import de.kosit.validationtool.cmd.report.Line;
-import de.kosit.validationtool.daemon.Daemon;
-import de.kosit.validationtool.impl.ConversionService;
-import de.kosit.validationtool.impl.EngineInformation;
-import de.kosit.validationtool.impl.Printer;
-import de.kosit.validationtool.impl.ScenarioRepository;
-import de.kosit.validationtool.impl.xml.ProcessorProvider;
-import lombok.extern.slf4j.Slf4j;
-import net.sf.saxon.s9api.Processor;
-
-/**
- * Actual evaluation and processing of CommandLineOptions argumtens.
- *
- * @author Andreas Penski
- */
-@Slf4j
-@SuppressWarnings("squid:S3725")
-public class Validator {
-
- private Validator() {
- // hide
- }
-
- /**
- * Hauptprogramm für die Kommandozeilen-Applikation.
- *
- * @param cmd parsed commandline.
- */
- static ReturnValue mainProgram(final CommandLineOptions cmd) {
- greeting();
- final ReturnValue returnValue;
- try {
- if (cmd.isDaemonModeEnabled()) {
- startDaemonMode(cmd);
- returnValue = ReturnValue.DAEMON_MODE;
- } else if (cmd.isCliModeEnabled() || isPiped()) {
- returnValue = processActions(cmd);
- } else {
- Printer.writeErr("No test target found");
- returnValue = ReturnValue.CONFIGURATION_ERROR;
- }
- } catch (final Exception e) {
- e.printStackTrace();
- Printer.writeErr(e.getMessage());
- if (cmd.isDebugOutput()) {
- log.error(e.getMessage(), e);
- } else {
- log.error(e.getMessage());
- }
- return ReturnValue.CONFIGURATION_ERROR;
- }
- return returnValue;
- }
-
- private static void greeting() {
- Printer.writeOut("{0} version {1}", EngineInformation.getName(), EngineInformation.getVersion());
- }
-
- private static int determineThreads(final CommandLineOptions.DaemonOptions cmd) {
- int threads = Runtime.getRuntime().availableProcessors();
- if (cmd.getWorkerCount() > 0) {
- threads = cmd.getWorkerCount();
- }
- return threads;
- }
-
- private static void startDaemonMode(final CommandLineOptions cmd) {
- if (cmd.isCliModeEnabled()) {
- Printer.writeErr("Mixed mode configuration detected. Use either daemon mode or cli mode commandline options. They are mutual "
- + "exclusive. Will ignore cli mode options");
- }
- final List configuration = getConfiguration(cmd);
- final CommandLineOptions.DaemonOptions daemonOptions = cmd.getDaemonOptions();
- final Daemon validDaemon = new Daemon(daemonOptions.getHost(), daemonOptions.getPort(), determineThreads(daemonOptions));
- validDaemon.setGuiEnabled(!daemonOptions.isDisableGUI());
- Printer.writeOut("\nStarting daemon mode ...");
- validDaemon.startServer(ProcessorProvider.getProcessor(), configuration.toArray(new Configuration[configuration.size()]));
- }
-
- private static ReturnValue processActions(final CommandLineOptions cmd) throws IOException {
- long start = System.currentTimeMillis();
- final Processor processor = ProcessorProvider.getProcessor();
- final List config = getConfiguration(cmd);
- final InternalCheck check = new InternalCheck(processor, config.toArray(new Configuration[0]));
- final CommandLineOptions.CliOptions cliOptions = getIfNull(cmd.getCliOptions(), new CliOptions());
- final Path outputDirectory = determineOutputDirectory(cliOptions);
- if (cliOptions.isExtractHtml()) {
- check.getCheckSteps().add(new ExtractHtmlContentAction(processor, outputDirectory));
- }
- check.getCheckSteps().add(new SerializeReportAction(outputDirectory, processor, determineNamingStrategy(cliOptions)));
- if (cliOptions.isSerializeInput()) {
- check.getCheckSteps().add(new SerializeReportInputAction(outputDirectory, check.getConversionService()));
- }
- if (cliOptions.isPrintReport()) {
- check.getCheckSteps().add(new PrintReportAction(processor));
- }
-
- if (cliOptions.getAssertions() != null) {
- final Assertions assertions = loadAssertions(cliOptions.getAssertions());
- check.getCheckSteps().add(new CheckAssertionAction(assertions, processor));
- }
- if (cliOptions.isPrintMemoryStats()) {
- check.getCheckSteps().add(new PrintMemoryStats());
- }
- log.info("Setup completed in {}ms\n", System.currentTimeMillis() - start);
-
- final Collection targets = determineTestTargets(cliOptions);
- start = System.currentTimeMillis();
- final Map results = new HashMap<>();
- Printer.writeOut("\nProcessing of {0} objects started", targets.size());
- long tick = System.currentTimeMillis();
- for (final Input input : targets) {
- results.put(input.getName(), check.checkInput(input));
- if (((System.currentTimeMillis() - tick) / 1000) > 5) {
- tick = System.currentTimeMillis();
- Printer.writeOut("{0}/{1} objects processed", results.size(), targets.size());
- }
- }
- final long processingTime = System.currentTimeMillis() - start;
- Printer.writeOut("Processing of {0} objects completed in {1}ms", targets.size(), processingTime);
-
- check.printResults(results);
- log.info("Processing {} object(s) completed in {}ms", targets.size(), processingTime);
- return check.isSuccessful(results) ? ReturnValue.SUCCESS : ReturnValue.createFailed(check.getNotAcceptableCount(results));
- }
-
- /**
- * @param cmd the Command Line Options
- *
- * @return a list of configurations of the scenarios and repositories passed in cmd
- */
- private static List getConfiguration(final CommandLineOptions cmd) {
- final List scenarios = getIfNull(cmd.getScenarios(), Collections.emptyList());
- // Map from scenario name to scenario path
- final Map mappedScenarios = scenarios.stream()
- .collect(Collectors.toMap(ScenarioDefinition::getName, ScenarioDefinition::getPath));
- final List repos = getIfNull(cmd.getRepositories(), Collections.emptyList());
- final Map mappedRepos = repos.stream()
- .collect(Collectors.toMap(RepositoryDefinition::getName, RepositoryDefinition::getPath));
- checkUnused(mappedScenarios, mappedRepos);
-
- return mappedScenarios.entrySet().stream().map(e -> {
- assertFileExistance(e.getValue(), "scenario");
- final URI scenarioLocation = e.getValue().toUri();
- final URI repositoryLocation = findRepository(scenarioLocation, e.getKey(), mappedRepos);
-
- reportLoading(scenarioLocation, repositoryLocation);
- final Configuration configuration = Configuration.load(scenarioLocation, repositoryLocation)
- .build(ProcessorProvider.getProcessor());
- reportConfiguration(configuration);
- return configuration;
- }).collect(Collectors.toList());
-
- }
-
- private static void checkUnused(final Map scenarios, final Map repositories) {
- final List> unused = repositories.entrySet().stream().filter(e -> scenarios.get(e.getKey()) == null)
- .collect(Collectors.toList());
- unused.removeIf(e -> e.getKey().equals(ScenarioRepository.DEFAULT_ID));
- unused.forEach(e -> Printer.writeErr("Warning: repository definition \"{0}\" is not used", e.getKey()));
- }
-
- private static URI findRepository(final URI scenarioLocation, final String key, final Map repositories) {
- final Path path = repositories.getOrDefault(key, repositories.get(ScenarioRepository.DEFAULT_ID));
- if (path == null) {
- // If it is an unnamed scenario, use the CWD instead
- if (key.startsWith(ScenarioRepository.DEFAULT)) {
- // Assume directory of scenario location instead
- return Paths.get(scenarioLocation).getParent().toUri();
- }
- throw new IllegalArgumentException(String.format("No repository location for scenario definition '%s' specified", key));
- }
- return determineRepository(path);
- }
-
- private static void reportLoading(final URI scenarioLocation, final URI repositoryLocation) {
- Printer.writeOut("Loading scenarios from {0}", scenarioLocation);
- Printer.writeOut("Using repository {0}", repositoryLocation);
- Printer.writeOut(EMPTY);
- }
-
- private static void reportConfiguration(final Configuration configuration) {
- Printer.writeOut("Loaded \"{0}\" by {1} from {2} ", configuration.getName(), configuration.getAuthor(), configuration.getDate());
- Printer.writeOut("The following scenarios are available:");
- configuration.getScenarios().forEach(e -> {
- final Line line = new Line(Code.GREEN);
- line.add(" * " + e.getName());
- Printer.writeOut(line.render(false, false));
-
- });
- Printer.writeOut(EMPTY);
-
- }
-
- private static NamingStrategy determineNamingStrategy(final CommandLineOptions.CliOptions cmd) {
- final DefaultNamingStrategy namingStrategy = new DefaultNamingStrategy();
- if (isNotEmpty(cmd.getReportPrefix())) {
- namingStrategy.setPrefix(cmd.getReportPrefix());
- }
- if (isNotEmpty(cmd.getReportPostfix())) {
- namingStrategy.setPostfix(cmd.getReportPostfix());
- }
- return namingStrategy;
- }
-
- private static Assertions loadAssertions(final Path p) {
- Assertions a = null;
- if (Files.exists(p)) {
- final ConversionService c = new ConversionService();
- c.initialize(de.kosit.validationtool.cmd.assertions.ObjectFactory.class.getPackage());
- a = c.readXml(p.toUri(), Assertions.class);
- }
- return a;
- }
-
- private static Path determineOutputDirectory(final CommandLineOptions.CliOptions cmd) {
- final Path dir;
- if (cmd.getOutputPath() != null) {
- dir = cmd.getOutputPath();
- if ((!Files.exists(dir) && !dir.toFile().mkdirs()) || !Files.isDirectory(dir)) {
- throw new IllegalStateException(String.format("Invalid target directory %s specified", dir.toString()));
- }
- } else {
- dir = Paths.get(""/* cwd */);
- }
- return dir;
- }
-
- private static Collection determineTestTargets(final CommandLineOptions.CliOptions cmd) throws IOException {
- final Collection targets = new ArrayList<>();
- if (cmd.getFiles() != null && !cmd.getFiles().isEmpty()) {
- cmd.getFiles().forEach(e -> targets.addAll(determineTestTarget(e)));
- }
- if (isPiped()) {
- targets.add(readFromPipe());
- }
- if (targets.isEmpty()) {
- throw new IllegalStateException("No test targets found. Nothing to check. Will quit now!");
- }
- return targets;
- }
-
- @SuppressWarnings("java:S4829") // sanitation is delegated to xml stack
- private static boolean isPiped() throws IOException {
- return System.in.available() > 0;
- }
-
- @SuppressWarnings("java:S4829") // sanitation is delegated to xml stack
- private static Input readFromPipe() {
- return InputFactory.read(System.in, "stdin");
- }
-
- private static Collection determineTestTarget(final Path d) {
- if (Files.isDirectory(d)) {
- return listDirectoryTargets(d);
- } else if (Files.exists(d)) {
- return Collections.singleton(InputFactory.read(d));
- }
- log.warn("The specified test target {} does not exist. Will be ignored", d);
- return Collections.emptyList();
-
- }
-
- private static Collection listDirectoryTargets(final Path d) {
- try ( final Stream stream = Files.list(d) ) {
- return stream.filter(path -> path.toString().toLowerCase().endsWith(".xml")).map(InputFactory::read)
- .collect(Collectors.toList());
- } catch (final IOException e) {
- throw new IllegalStateException("IOException while list directory content. Can not determine test targets.", e);
- }
-
- }
-
- private static URI determineRepository(final Path d) {
- if (Files.isDirectory(d)) {
- return d.toUri();
- }
- throw new IllegalArgumentException(String.format("Not a valid path for repository definition specified: '%s'", d.toAbsolutePath()));
-
- }
-
- private static void assertFileExistance(final Path f, final String type) {
- if (!Files.isRegularFile(f)) {
- throw new IllegalArgumentException(
- String.format("Not a valid path for %s definition specified: '%s'", type, f.toAbsolutePath()));
- }
- }
-
-}
diff --git a/src/main/java/de/kosit/validationtool/cmd/report/Format.java b/src/main/java/de/kosit/validationtool/cmd/report/Format.java
deleted file mode 100644
index 69b30c5..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/report/Format.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd.report;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.apache.commons.lang3.ArrayUtils;
-import org.fusesource.jansi.AnsiRenderer.Code;
-
-import lombok.Getter;
-
-/**
- * Simple value holder for ansi formatting codes.
- *
- * @author Andreas Penski
- */
-@Getter
-public class Format {
-
- private Code textColor;
-
- private Code background;
-
- @Getter
- private final Set codes = new HashSet<>();
-
- public Code[] mergeCodes(final Collection newCodes) {
- return mergeCodes(newCodes.toArray(new Code[newCodes.size()]));
- }
-
- public Code[] mergeCodes(final Code... newCodes) {
- final Code[] allCodes = ArrayUtils.addAll(ArrayUtils.addAll(this.codes.toArray(new Code[0]), newCodes), this.textColor,
- this.background);
-
- final Optional color = Arrays.stream(allCodes).filter(Objects::nonNull).filter(Code::isColor).findFirst();
- final Optional bg = Arrays.stream(allCodes).filter(Objects::nonNull).filter(Code::isBackground).findFirst();
- final List attributes = Arrays.stream(allCodes).filter(Objects::nonNull).filter(Code::isBackground).filter(Code::isColor)
- .collect(Collectors.toList());
- attributes.add(color.orElse(this.textColor));
- attributes.add(bg.orElse(this.background));
- return attributes.stream().filter(Objects::nonNull).toArray(Code[]::new);
- }
-
- /**
- * Sets explicit text color.
- *
- * @param textColor the color.
- *
- * @return this {@link Format}
- */
- public Format color(final Code textColor) {
- this.textColor = textColor;
- return this;
- }
-
- /**
- * Sets explicit background color.
- *
- * @param color the color.
- *
- * @return this {@link Format}
- */
- public Format background(final Code color) {
- this.background = color;
- return this;
- }
-
- /**
- * Fügt weitere Formatierungscodes hinzu.
- *
- * @param codes die Codes
- *
- * @return this {@link Format}
- */
- public Format addCodes(final Code... codes) {
- this.codes.addAll(Arrays.asList(codes));
- return this;
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/cmd/report/Grid.java b/src/main/java/de/kosit/validationtool/cmd/report/Grid.java
deleted file mode 100644
index 944acb6..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/report/Grid.java
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd.report;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
-
-import org.apache.commons.lang3.StringUtils;
-import org.fusesource.jansi.AnsiRenderer.Code;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-/**
- * An text based grid for cli based programs.
- *
- * @author Andreas Penski
- */
-public class Grid {
-
- /**
- * A definition / configuration for a column with a result table.
- */
- @Getter
- public static class ColumnDefinition {
-
- private static final int MAX_LENGTH = 80;
-
- private final String name;
-
- private int length = 0;
-
- private final int maxLength;
-
- private final int minLength;
-
- private final int maxLines;
-
- private Justify justify = Justify.LEFT;
-
- /**
- * Constructor.
- *
- * @param name the name of the column
- */
- public ColumnDefinition(final String name) {
- this(name, -1, -1, 1);
- }
-
- /**
- * Constructor.
- *
- * @param name the name of the column
- * @param maxLength the max length of the column
- */
- public ColumnDefinition(final String name, final int maxLength) {
- this(name, maxLength, -1, 1);
- }
-
- /**
- * Constructor.
- *
- * @param name the name of the column
- * @param maxLength the max length of the column
- * @param minLength the minimum length of the column
- */
- public ColumnDefinition(final String name, final int maxLength, final int minLength) {
- this(name, maxLength, minLength, 1);
- }
-
- /**
- * Constructor.
- *
- * @param name the name of the column
- * @param maxLength the max length of the column
- * @param minLength the minimum length of the column
- * @param maxLines the max lines per cell
- */
- public ColumnDefinition(final String name, final int maxLength, final int minLength, final int maxLines) {
- this.name = name;
- this.maxLength = maxLength;
- this.minLength = minLength;
- this.maxLines = maxLines;
- }
-
- /**
- * Returns the actual max length of the column
- *
- * @return max length
- */
- public int getLength() {
- if (this.minLength > 0 && this.minLength > this.length) {
- return this.minLength;
- }
- if (this.maxLength > 0 && this.length > this.maxLength) {
- return this.maxLength;
- }
- return this.length;
- }
-
- /**
- * Sets a calculated length for the column.
- *
- * @param length the length
- */
- public void setLength(final int length) {
- if (length > this.length) {
- this.length = length;
- }
- if (length > MAX_LENGTH) {
- this.length = MAX_LENGTH;
- }
- }
-
- public ColumnDefinition justify(final Justify justify) {
- this.justify = justify;
- return this;
- }
- }
-
- @RequiredArgsConstructor
- @Getter
- private static class Cell {
-
- private final Format format = DEFAULT_FORMAT;
-
- private final List text;
-
- public Cell(final Text txt) {
- this.text = new ArrayList<>();
- this.text.add(txt);
- }
-
- protected Line getFormattedLine(final int lineNumber, final ColumnDefinition def) {
- final Line line = new Line();
- int startSubstring = lineNumber * def.getLength();
- int currentVisibleLength = 0;
- for (final Text t : this.text) {
- final String part = t.getVisibleText(startSubstring, def.getLength());
- currentVisibleLength += part.length();
- if (StringUtils.isNotBlank(part)) {
- line.add(part, t.getFormat());
- if (currentVisibleLength >= def.getLength()) {
- break;
- }
- startSubstring = 0;
- } else {
- startSubstring = startSubstring - t.getLength();
- }
- }
- return line;
- }
-
- protected List getFormattedLines(final ColumnDefinition def) {
- int count = 0;
- Line line;
- final List lines = new ArrayList<>();
- while ((line = getFormattedLine(count++, def)).isNotEmpty()) {
- lines.add(line);
- }
- return lines;
- }
-
- public String render(final int row, final ColumnDefinition def) {
- final List test = getFormattedLines(def);
- final Line line = test.size() > row ? test.get(row) : null;
- if (line != null) {
- return def.getJustify().apply(line.render(false, row == def.getMaxLines() - 1 && test.size() > def.getMaxLines()),
- def.getLength() + (line.getLength() - line.getVisibleLength()));
- }
- return def.getJustify().apply("", def.getLength());
-
- }
-
- }
-
- private static final Format DEFAULT_FORMAT = new Format();
-
- /**
- * A grid / table for printing results.
- */
-
- private final List definitions = new ArrayList<>();
-
- private final List values = new ArrayList<>();
-
- /**
- * Constructor.
- *
- * @param def {@link ColumnDefinition}s
- */
- public Grid(final ColumnDefinition... def) {
- Stream.of(def).forEach(this::addColumn);
- }
-
- private String generateGridStart() {
- return IntStream.range(0, getLineLength() + this.definitions.size()).mapToObj(i -> "-").collect(Collectors.joining("")) + "\n";
- }
-
- private String generateGridEnd() {
- return IntStream.range(0, getLineLength() + this.definitions.size()).mapToObj(i -> "-").collect(Collectors.joining("")) + "\n";
- }
-
- private String generateHeader() {
- return "|" + this.definitions.stream().map(d -> StringUtils.rightPad(d.getName(), d.getLength())).collect(Collectors.joining("|"))
- + "|\n";
- }
-
- /**
- * Adds new a column definition.
- *
- * @param def definitions
- * @return this grid
- */
- public Grid addColumn(final ColumnDefinition def) {
- this.definitions.add(def);
- return this;
- }
-
- private void calculateLength() {
- IntStream.range(0, this.definitions.size()).forEach(i -> {
- final ColumnDefinition def = this.definitions.get(i);
- final List column = getColumn(i);
- final int maxLength = column.stream().mapToInt(cell -> cell.getText().stream().mapToInt(Text::getLength).sum()).max().orElse(0);
- def.setLength(Math.max(maxLength, def.getName().length()));
-
- });
- }
-
- public List getColumn(final int index) {
-
- return IntStream.range(0, this.values.size()).filter(n -> n % this.definitions.size() == index).mapToObj(this.values::get)
- .collect(Collectors.toList());
- }
-
- public Grid addCell(final Cell cell) {
- this.values.add(cell);
- return this;
- }
-
- public Grid addCell(final Text... text) {
- return addCell(new Cell(Arrays.asList(text)));
- }
-
- public Grid addCell(final Object cell, final Code... codes) {
- final Format f = new Format();
- f.addCodes(codes);
- final Text t = new Text(cell, f);
- return addCell(new Cell(t));
- }
-
- public Grid addCell(final Object cell) {
- return addCell(cell, DEFAULT_FORMAT.getTextColor());
- }
-
- private Collection> prepareLines() {
- final AtomicInteger counter = new AtomicInteger();
- final int chunkSize = this.definitions.size();
- return this.values.stream().collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize)).values();
- }
-
- public String render() {
- final StringBuilder b = new StringBuilder();
- calculateLength();
- b.append(generateGridStart());
- b.append(generateHeader());
- prepareLines().forEach(line -> b.append(printLine(line)));
-
- b.append(generateGridEnd());
- return b.toString();
- }
-
- private String printLine(final List| line) {
- final StringBuilder b = new StringBuilder();
- int virtualLine = 0;
- while (true) {
- final StringBuilder current = new StringBuilder();
- final int bound = this.definitions.size();
- for (int i = 0; i < bound; i++) {
- final ColumnDefinition def = this.definitions.get(i);
- current.append("|");
- current.append(line.get(i).render(virtualLine, def));
- }
- current.append("|");
- if (isEmpty(current) || virtualLine >= getMaxVirtualLine()) {
- break;
- }
- b.append(current.toString());
- virtualLine++;
- b.append("\n");
- }
- return b.toString();
-
- }
-
- private static boolean isEmpty(final StringBuilder current) {
- return current.toString().replace("|", "").trim().length() == 0;
- }
-
- private int getMaxVirtualLine() {
- return this.definitions.stream().mapToInt(ColumnDefinition::getMaxLines).max().orElseThrow(IllegalAccessError::new);
- }
-
- private int getLineLength() {
- return this.definitions.stream().map(ColumnDefinition::getLength).reduce(0, Integer::sum);
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/cmd/report/Justify.java b/src/main/java/de/kosit/validationtool/cmd/report/Justify.java
deleted file mode 100644
index b90b3c7..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/report/Justify.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd.report;
-
-import org.apache.commons.lang3.StringUtils;
-
-/**
- * Justification modes for the text in grid columns.
- *
- * @author Andreas Penski
- */
-public enum Justify {
-
- LEFT {
-
- @Override
- public String apply(final String string, final int length) {
- return StringUtils.rightPad(string, length);
- }
- },
- CENTER {
-
- @Override
- public String apply(final String string, final int length) {
- return StringUtils.center(string, length);
- }
- },
- RIGHT {
-
- @Override
- public String apply(final String string, final int length) {
- return StringUtils.leftPad(string, length);
- }
- };
-
- public abstract String apply(String string, int length);
-}
diff --git a/src/main/java/de/kosit/validationtool/cmd/report/Line.java b/src/main/java/de/kosit/validationtool/cmd/report/Line.java
deleted file mode 100644
index c8233a0..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/report/Line.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd.report;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-import org.fusesource.jansi.AnsiRenderer.Code;
-
-import lombok.NoArgsConstructor;
-
-/**
- * Helper for printing a colored lines (with newline at the end) to the console.
- */
-@NoArgsConstructor
-public class Line {
-
- private final List texts = new ArrayList<>();
-
- private Format baseFormat = new Format();
-
- /**
- * Constructor.
- *
- * @param format the configured base format
- */
- public Line(final Format format) {
- this.baseFormat = format;
- }
-
- /**
- * Constructor.
- *
- * @param codes Ansi escape codes for formatting
- */
- public Line(final Code... codes) {
- this(new Format().addCodes(codes));
- }
-
- /**
- * Add some text to the line.
- *
- * @param text the text
- * @return this line
- */
- public Line add(final Text text) {
- this.texts.add(text);
- return this;
- }
-
- public Line add(final Object t) {
- return add(new Text(t));
- }
-
- public Line add(final Object text, final Code... codes) {
- return add(new Text(text, codes));
- }
-
- public Line add(final Object text, final Format format) {
- return add(new Text(text, format));
- }
-
- public String render() {
- return render(true, false);
- }
-
- public String render(final boolean newLine, final boolean dotted) {
- final List joins = new ArrayList<>();
- final List reversed = new ArrayList<>(this.texts);
- int replace = 0;
- Collections.reverse(reversed);
- if (dotted && getVisibleLength() > replace) {
- replace = 3;
- }
- for (final Text t : reversed) {
- if (replace > 0) {
- final String render = t.render(t.getVisibleText(0, t.getVisibleLength() - replace), this.baseFormat);
- if (StringUtils.isNotEmpty(render)) {
- joins.add(render);
- }
- replace = replace - t.getVisibleLength();
- } else {
- joins.add(t.render(this.baseFormat));
- }
-
- }
- Collections.reverse(joins);
- return String.join(" ", joins) + (dotted ? "..." : "") + (newLine ? "\n" : "");
- }
-
- public int getLength() {
- return this.texts.stream().mapToInt(Text::getLength).sum();
- }
-
- public static String render(final String text, final Code... codes) {
- return new Line().add(text, codes).render();
- }
-
- public boolean isNotEmpty() {
- return !this.texts.isEmpty();
- }
-
- public int getVisibleLength() {
- return this.texts.stream().mapToInt(Text::getVisibleLength).sum();
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/cmd/report/Text.java b/src/main/java/de/kosit/validationtool/cmd/report/Text.java
deleted file mode 100644
index 1db9433..0000000
--- a/src/main/java/de/kosit/validationtool/cmd/report/Text.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.cmd.report;
-
-import java.util.Arrays;
-
-import org.fusesource.jansi.AnsiRenderer;
-import org.fusesource.jansi.AnsiRenderer.Code;
-
-import lombok.Getter;
-
-/**
- * Ansi formatted text for outputting to the console.
- *
- * @author Andreas Penski
- */
-@Getter
-public class Text {
-
- private final String value;
-
- private Format format;
-
- public Text(final Object value) {
- this.value = value != null ? value.toString() : "";
- this.format = new Format();
- }
-
- public Text(final Object value, final Format format) {
- this(value);
- this.format = format;
- }
-
- public Text(final Object value, final Code... codes) {
- this(value, new Format().addCodes(codes));
- }
-
- public String getVisibleText(final int startIndex, final int length) {
- if (startIndex < 0) {
- return "Wrong cell text index";
- }
- if (startIndex > this.value.length()) {
- return "";
- }
- final String substring = this.value.substring(startIndex);
- return substring.length() > length ? substring.substring(0, length) : substring;
- }
-
- public String render(final String text, final Format baseformat) {
- return AnsiRenderer.render(text,
- Arrays.stream(this.format.mergeCodes(baseformat.getCodes())).map(Code::name).toArray(String[]::new));
- }
-
- public int getLength() {
- return render(this.format).length();
- }
-
- public String render(final Format baseFormat) {
- return render(getValue(), baseFormat);
- }
-
- public int getVisibleLength() {
- return this.value.length();
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/config/Builder.java b/src/main/java/de/kosit/validationtool/config/Builder.java
deleted file mode 100644
index 5b7d4f0..0000000
--- a/src/main/java/de/kosit/validationtool/config/Builder.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-import de.kosit.validationtool.impl.ContentRepository;
-import de.kosit.validationtool.impl.model.Result;
-
-/**
- * Internal interface for creating object builders.
- *
- * @author Andreas Penski
- */
-interface Builder {
-
- /**
- * Creates an object based on artifacts provided via a defined {@link ContentRepository}.
- *
- * @param repository the {@link ContentRepository}
- * @return the result of building the object
- */
- Result build(ContentRepository repository);
-}
diff --git a/src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java b/src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java
deleted file mode 100644
index e8d4c67..0000000
--- a/src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-import static de.kosit.validationtool.impl.DateFactory.createTimestamp;
-
-import java.net.URI;
-import java.nio.file.Path;
-import java.time.LocalDate;
-import java.time.ZoneId;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import javax.xml.validation.Schema;
-
-import org.apache.commons.lang3.NotImplementedException;
-import org.apache.commons.lang3.StringUtils;
-
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.api.Configuration;
-import de.kosit.validationtool.api.ResolvingConfigurationStrategy;
-import de.kosit.validationtool.impl.ContentRepository;
-import de.kosit.validationtool.impl.ResolvingMode;
-import de.kosit.validationtool.impl.Scenario;
-import de.kosit.validationtool.impl.model.Result;
-import de.kosit.validationtool.model.scenarios.DescriptionType;
-import de.kosit.validationtool.model.scenarios.NoScenarioReportType;
-import de.kosit.validationtool.model.scenarios.ObjectFactory;
-import de.kosit.validationtool.model.scenarios.Scenarios;
-
-import net.sf.saxon.s9api.Processor;
-
-/**
- * Implements a builder style creation of a {@link Configuration}.
- *
- * @author Andreas Penski
- */
-@Slf4j
-@Getter(AccessLevel.PACKAGE)
-public class ConfigurationBuilder {
-
- private final List scenarios = new ArrayList<>();
-
- private FallbackBuilder fallbackBuilder;
-
- private ResolvingConfigurationStrategy resolvingConfigurationStrategy;
-
- private ResolvingMode resolvingMode = ResolvingMode.STRICT_RELATIVE;
-
- private String author = "API";
-
- private String date = LocalDate.now().toString();
-
- private String name = "Custom";
-
- private final Map parameters = new HashMap<>();
-
- private URI repository;
-
- 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;
- }
-
- /**
- * Add a specific nam to this configuration
- *
- * @param name the name of the configuration
- * @return this
- */
- public ConfigurationBuilder name(final String name) {
- this.name = name;
- return this;
- }
-
- /**
- * Sets the date for this configuration.
- *
- * @param date the date
- * @return this
- */
- public ConfigurationBuilder date(final LocalDate date) {
- if (date != null) {
- this.date = date.toString();
- }
- return this;
- }
-
- /**
- * Sets the date for this configuration.
- *
- * @param date the date
- * @return this
- */
- public ConfigurationBuilder date(final Date date) {
- return date(date != null ? date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() : null);
- }
-
- /**
- * Adds a {@link Scenario} to this list of know scenarios. Note: order of calling this methods defines order of
- * scenarios when determining the target scenario for a given xml file.
- *
- * @param scenarioBuilder the {@link ScenarioBuilder} building the {@link Scenario}
- * @return this
- */
- public ConfigurationBuilder with(final ScenarioBuilder scenarioBuilder) {
- this.scenarios.add(scenarioBuilder);
- return this;
- }
-
- /**
- * Sets a specific fallback scenario configuration. Note: calling this more than once is possible, but the last call
- * will define the actual fallback scenario used. There can be only one
- *
- * @param builder the {@link FallbackBuilder}
- * @return this
- */
- public ConfigurationBuilder with(final FallbackBuilder builder) {
- if (this.fallbackBuilder != null) {
- log.warn("Overriding previously created fallback scenario");
- }
- this.fallbackBuilder = builder;
- return this;
- }
-
- /**
- * Adds a description to this configuration.
- *
- * @param description the descriptioin
- * @return this
- */
- public ConfigurationBuilder description(final String description) {
- this.description = description;
- return this;
- }
-
- /**
- * Create a fallback scenario configuration.
- *
- * @return the builder
- */
- public static FallbackBuilder fallback() {
- return new FallbackBuilder();
- }
-
- /**
- * Create the default fallback configuration if new scenario match. Note: this is public for explicit usage. If no
- * fallback is configured, this is the still default fallback.
- *
- * @return a fallback configuration
- */
- public static FallbackBuilder defaultFallback() {
- 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);
- }
-
- /**
- * Create a new schema validation configuration.
- *
- * @return a configuration builder for schema
- */
- public static SchemaBuilder schema() {
- return new SchemaBuilder();
- }
-
- /**
- * Create a new schema validation configuration.
- *
- * @param name the name of the schema
- * @param schema the actual precompiled schema to use
- * @return a configuration builder for schema
- */
- public static SchemaBuilder schema(final String name, final Schema schema) {
- return new SchemaBuilder().name(name).schema(schema);
- }
-
- /**
- * Create a new schema validation configuration.
- *
- * @param name the name of the schema
- * @return a configuration builder for schema
- */
- public static SchemaBuilder schema(final String name) {
- return new SchemaBuilder().name(name);
- }
-
- /**
- * Create a new schema validation configuration.
- *
- * @param uri the uri location of the schema
- * @return a configuration builder for schema
- */
- public static SchemaBuilder schema(final URI uri) {
- return new SchemaBuilder().schemaLocation(uri);
- }
-
- /**
- * Create a new named scenario configuration.
- *
- * @param name the name of the scenario
- * @return the scenario configuration builder
- */
- public static ScenarioBuilder scenario(final String name) {
- return new ScenarioBuilder().name(name);
- }
-
- /**
- * Create a new scenario configuration.
- *
- * @return the scenario configuration builder
- */
- public static ScenarioBuilder scenario() {
- return scenario(null);
- }
-
- /**
- * Create named report configuration.
- *
- * @param name the name of the report
- * @return the report configuration builder
- */
- public static ReportBuilder report(final String name) {
- return new ReportBuilder().name(name);
- }
-
- /**
- * Builds the actual {@link Configuration} by validating all builder inputs and constructing neccessary objects.
- *
- * @return a valid configuration
- * @throws IllegalStateException when the configuration is not valid/complete
- */
- public Configuration build(final Processor processor) {
- final ResolvingConfigurationStrategy resolving = getResolvingConfigurationStrategy();
- final ContentRepository contentRepository = new ContentRepository(processor, resolving, this.repository);
-
- final List list = initializeScenarios(contentRepository);
- final Scenario fallbackScenario = initializeFallback(contentRepository);
- final DefaultConfiguration configuration = new DefaultConfiguration(list, fallbackScenario);
- configuration.setAdditionalParameters(this.parameters);
- configuration.setAuthor(this.author);
- configuration.setDate(this.date);
- configuration.setName(this.name);
- configuration.setContentRepository(contentRepository);
- configuration.getAdditionalParameters().put(Keys.SCENARIO_DEFINITION, createDefinition(configuration));
- return (configuration);
- }
-
- private Scenarios createDefinition(final DefaultConfiguration configuration) {
- final Scenarios s = new Scenarios();
- s.setAuthor(configuration.getAuthor());
- s.setDate(createTimestamp());
- final DescriptionType d = new DescriptionType();
- d.getPOrOlOrUl().add(new ObjectFactory().createDescriptionTypeP(StringUtils.defaultIfBlank(this.description, "")));
- s.setDescription(d);
- s.setName(configuration.getName());
- s.getScenario().addAll(configuration.getScenarios().stream().map(Scenario::getConfiguration).collect(Collectors.toList()));
- s.setNoScenarioReport(createNoScenarioReportType(configuration.getFallbackScenario()));
- return s;
- }
-
- private static NoScenarioReportType createNoScenarioReportType(final Scenario fallbackScenario) {
- final NoScenarioReportType no = new NoScenarioReportType();
- no.setResource(fallbackScenario.getConfiguration().getCreateReport().getResource());
- return no;
- }
-
- private Scenario initializeFallback(final ContentRepository contentRepository) {
- if (this.fallbackBuilder == null) {
- throw new IllegalStateException("No fallback configuration specified");
- }
- final Result result = this.fallbackBuilder.build(contentRepository);
- if (result.isInvalid()) {
- throw new IllegalStateException("Invalid fallback configuration: " + String.join(",", result.getErrors()));
- }
- return result.getObject();
- }
-
- private List initializeScenarios(final ContentRepository contentRepository) {
- if (this.scenarios.isEmpty()) {
- throw new IllegalStateException("No scenario specified");
- }
- return this.scenarios.stream().map(s -> {
- final Result result = s.build(contentRepository);
- if (result.isInvalid()) {
- final String msg = String.join(",", result.getErrors());
- throw new IllegalStateException(String.format("Invalid configuration for scenario %s found: %s", s.getName(), msg));
- }
- return result.getObject();
- }).collect(Collectors.toList());
- }
-
- private ResolvingConfigurationStrategy getResolvingConfigurationStrategy() {
- if (this.resolvingConfigurationStrategy != null) {
- log.info("Custom resolving strategy supplied. Please take care of xml security!");
- return this.resolvingConfigurationStrategy;
- }
- log.info("Using resolving strategy {}", this.resolvingMode);
- return this.resolvingMode.getStrategy();
- }
-
- /**
- * Sets a specific resolving mode, for resolving xml artifacts for this configuration. See {@link ResolvingMode} for
- * details.
- *
- * @param mode the mode
- * @return this
- */
- public ConfigurationBuilder resolvingMode(final ResolvingMode mode) {
- this.resolvingMode = mode;
- return this;
- }
-
- /**
- * Sets a specific strategy to use for resolving artefacts for scenarios.
- *
- * @param strategy the strategy
- * @return this
- */
- public ConfigurationBuilder resolvingStrategy(final ResolvingConfigurationStrategy strategy) {
- this.resolvingConfigurationStrategy = strategy;
- return this;
- }
-
- /**
- * Set a specific repository location for resolving artifacts for scenarios.
- *
- * @param repository the repository location
- * @return this
- */
- public ConfigurationBuilder useRepository(final URI repository) {
- this.repository = repository;
- return this;
- }
-
- /**
- * Set a specific repository location for resolving artifacts for scenarios.
- *
- * @param repository the repository location
- * @return this
- */
- public ConfigurationBuilder useRepository(final Path repository) {
- return useRepository(repository.toUri());
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/config/ConfigurationLoader.java b/src/main/java/de/kosit/validationtool/config/ConfigurationLoader.java
deleted file mode 100644
index 0f279d8..0000000
--- a/src/main/java/de/kosit/validationtool/config/ConfigurationLoader.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import javax.xml.validation.Schema;
-
-import org.apache.commons.lang3.Strings;
-
-import de.kosit.validationtool.api.Check;
-import de.kosit.validationtool.api.Configuration;
-import de.kosit.validationtool.api.InputFactory;
-import de.kosit.validationtool.api.ResolvingConfigurationStrategy;
-import de.kosit.validationtool.impl.CollectingErrorEventHandler;
-import de.kosit.validationtool.impl.ContentRepository;
-import de.kosit.validationtool.impl.ConversionService;
-import de.kosit.validationtool.impl.ResolvingMode;
-import de.kosit.validationtool.impl.Scenario;
-import de.kosit.validationtool.impl.SchemaProvider;
-import de.kosit.validationtool.impl.model.Result;
-import de.kosit.validationtool.impl.tasks.DocumentParseAction;
-import de.kosit.validationtool.impl.xml.RelativeUriResolver;
-import de.kosit.validationtool.model.reportInput.XMLSyntaxError;
-import de.kosit.validationtool.model.scenarios.ResourceType;
-import de.kosit.validationtool.model.scenarios.ScenarioType;
-import de.kosit.validationtool.model.scenarios.Scenarios;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import net.sf.saxon.s9api.Processor;
-import net.sf.saxon.s9api.QName;
-import net.sf.saxon.s9api.XdmNode;
-import net.sf.saxon.s9api.XdmNodeKind;
-
-/**
- * Configuration class that loads necessary {@link Check} configuration from an existing scenario.xml specification.
- * This is the recommended option when an official configuration exists as is the case with 'xrechnung'.
- *
- * @author Andreas Penski
- */
-@RequiredArgsConstructor
-@Slf4j
-public class ConfigurationLoader {
-
- private static final String SUPPORTED_MAJOR_VERSION = "1";
-
- private static final String SUPPORTED_MAJOR_VERSION_SCHEMA = "http://www.xoev.de/de/validator/framework/1/scenarios";
-
- protected final Map parameters = new HashMap<>();
-
- /**
- * URL, die auf die scenerio.xml Datei zeigt.
- */
- @Getter(AccessLevel.PACKAGE)
- private final URI scenarioDefinition;
-
- /**
- * Root-Ordner mit den von den einzelnen Szenarien benötigten Dateien
- */
- private final URI scenarioRepository;
-
- protected ResolvingMode resolvingMode = ResolvingMode.STRICT_RELATIVE;
-
- protected ResolvingConfigurationStrategy resolvingConfigurationStrategy;
-
- private static void checkVersion(final URI scenarioDefinition, final Processor processor) {
- try {
- final Result result = new DocumentParseAction(processor)
- .parseDocument(InputFactory.read(scenarioDefinition.toURL()));
- if (result.isValid() && !isSupportedDocument(result.getObject())) {
- throw new IllegalStateException(String.format(
- "Specified scenario configuration %s is not supported.%nThis version only supports definitions of '%s'",
- scenarioDefinition, SUPPORTED_MAJOR_VERSION_SCHEMA));
-
- }
- } catch (final MalformedURLException e) {
- throw new IllegalStateException("Error reading definition file");
- }
- }
-
- private static XdmNode findRoot(final XdmNode doc) {
- for (final XdmNode node : doc.children()) {
- if (node.getNodeKind() == XdmNodeKind.ELEMENT) {
- return node;
- }
- }
- throw new IllegalArgumentException("Kein root element gefunden");
- }
-
- private static boolean isSupportedDocument(final XdmNode doc) {
- final XdmNode root = findRoot(doc);
- final String frameworkVersion = root.getAttributeValue(new QName("frameworkVersion"));
- return Strings.CS.startsWith(frameworkVersion, SUPPORTED_MAJOR_VERSION)
- && root.getNodeName().getNamespace().equals(SUPPORTED_MAJOR_VERSION_SCHEMA);
- }
-
- private static Scenario createFallback(final Scenarios scenarios, final ContentRepository repository) {
- final ResourceType noscenarioResource = scenarios.getNoScenarioReport().getResource();
- return new FallbackBuilder().source(noscenarioResource.getLocation()).name(noscenarioResource.getName()).build(repository)
- .getObject();
-
- }
-
- private static List initializeScenarios(final Scenarios def, final ContentRepository contentRepository) {
- return def.getScenario().stream().map(s -> initialize(s, contentRepository)).collect(Collectors.toList());
- }
-
- private static Scenario initialize(final ScenarioType def, final ContentRepository repository) {
- final Scenario s = new Scenario(def);
- s.setMatchExecutable(repository.createMatchExecutable(def));
- s.setSchema(repository.createSchema(def));
- s.setSchematronValidations(repository.createSchematronTransformations(def));
- if (def.getCreateReport() != null) {
- s.setReportTransformation(repository.createReportTransformation(def));
- } else {
- log.warn("No report configured. Will provide an internal format as report!");
- s.setReportTransformation(repository.createIdentityTransformation());
- }
- s.setFactory(repository.getResolvingConfigurationStrategy());
- s.setUriResolver(repository.getResolver());
- s.setUnparsedTextURIResolver(repository.getUnparsedTextURIResolver());
- if (def.getAcceptMatch() != null) {
- s.setAcceptExecutable(repository.createAccepptExecutable(def));
- }
- return s;
- }
-
- URI getScenarioRepository() {
- if (this.scenarioRepository == null) {
- log.info("Creating default scenario repository (alongside scenario definition)");
- return RelativeUriResolver.resolve(URI.create("."), this.scenarioDefinition);
- }
- return this.scenarioRepository;
- }
-
- public Configuration build(final Processor processor) {
- final ResolvingConfigurationStrategy resolving = getResolvingConfigurationStrategy();
- final ContentRepository contentRepository = new ContentRepository(processor, resolving, getScenarioRepository());
-
- final Scenarios def = loadScenarios(SchemaProvider.getScenarioSchema(), processor);
- final List scenarios = initializeScenarios(def, contentRepository);
- final Scenario fallbackScenario = createFallback(def, contentRepository);
- final DefaultConfiguration configuration = new DefaultConfiguration(scenarios, fallbackScenario);
- configuration.setAdditionalParameters(this.parameters);
- configuration.setAuthor(def.getAuthor());
- configuration.setDate(def.getDate().toString());
- configuration.setName(def.getName());
- configuration.setContentRepository(contentRepository);
- configuration.getAdditionalParameters().put(Keys.SCENARIOS_FILE, this.scenarioDefinition);
- configuration.getAdditionalParameters().put(Keys.SCENARIO_DEFINITION, def);
- return (configuration);
- }
-
- private ResolvingConfigurationStrategy getResolvingConfigurationStrategy() {
- if (this.resolvingConfigurationStrategy != null) {
- log.info("Custom resolving strategy supplied. Please take care of xml security!");
- return this.resolvingConfigurationStrategy;
- }
- log.info("Using resolving strategy {}", this.resolvingMode);
- return this.resolvingMode.getStrategy();
- }
-
- private Scenarios loadScenarios(final Schema scenarioSchema, final Processor processor) {
- checkVersion(this.scenarioDefinition, processor);
- log.info("Loading scenarios from {}", this.scenarioDefinition);
- final CollectingErrorEventHandler handler = new CollectingErrorEventHandler();
- final ConversionService conversionService = new ConversionService();
- final Scenarios scenarios = conversionService.readXml(this.scenarioDefinition, Scenarios.class, scenarioSchema, handler);
- if (!handler.hasErrors()) {
- log.info("Loading scenario content from {}", this.getScenarioRepository());
- } else {
- throw new IllegalStateException(
- String.format("Can not load scenarios from %s due to %s", getScenarioDefinition(), handler.getErrorDescription()));
- }
- return scenarios;
-
- }
-
- /**
- * 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) {
- if (this.resolvingConfigurationStrategy != null) {
- log.warn("Ignoring resolving mode configuration since a custom strategy is already defined");
- }
- 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/DefaultConfiguration.java b/src/main/java/de/kosit/validationtool/config/DefaultConfiguration.java
deleted file mode 100644
index 9771867..0000000
--- a/src/main/java/de/kosit/validationtool/config/DefaultConfiguration.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-import java.util.List;
-import java.util.Map;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.api.Configuration;
-import de.kosit.validationtool.impl.ContentRepository;
-import de.kosit.validationtool.impl.Scenario;
-
-/**
- * Default implementation class for {@link Configuration}. This class contains all information to run a
- * {@link de.kosit.validationtool.impl.DefaultCheck}.
- *
- * @author Andreas Penski
- */
-@Slf4j
-@RequiredArgsConstructor
-@Getter
-@Setter
-public class DefaultConfiguration implements Configuration {
-
- private final List scenarios;
-
- private final Scenario fallbackScenario;
-
- private ContentRepository contentRepository;
-
- private String name;
-
- private String author;
-
- private String date;
-
- private Map additionalParameters;
-}
diff --git a/src/main/java/de/kosit/validationtool/config/FallbackBuilder.java b/src/main/java/de/kosit/validationtool/config/FallbackBuilder.java
deleted file mode 100644
index c58dda0..0000000
--- a/src/main/java/de/kosit/validationtool/config/FallbackBuilder.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-import java.net.URI;
-import java.nio.file.Path;
-
-import org.apache.commons.lang3.tuple.Pair;
-
-import de.kosit.validationtool.impl.ContentRepository;
-import de.kosit.validationtool.impl.Scenario;
-import de.kosit.validationtool.impl.Scenario.Transformation;
-import de.kosit.validationtool.impl.model.Result;
-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 {
-
- private final ReportBuilder internal = new ReportBuilder().name("fallback");
-
- @Override
- public Result build(final ContentRepository repository) {
- final ScenarioType object = createObject();
- final Result, String> build = this.internal.build(repository);
- final Result result;
- if (build.isValid()) {
- object.setCreateReport(build.getObject().getLeft());
- final Scenario s = new Scenario(object);
- s.setFallback(true);
- s.setFactory(repository.getResolvingConfigurationStrategy());
- s.setUriResolver(repository.getResolver());
- s.setUnparsedTextURIResolver(repository.getUnparsedTextURIResolver());
- s.setReportTransformation(build.getObject().getRight());
- result = new Result<>(s);
- } else {
- result = new Result<>(build.getErrors());
- }
- return result;
- }
-
- private static ScenarioType createObject() {
- final ScenarioType t = new ScenarioType();
- t.setName("Fallback-Scenario");
- t.setMatch("count(/)<0");
- // always reject
- t.setAcceptMatch("count(/)<0");
- return t;
- }
-
- /**
- * Specifices a source for this report. This is either used to compile the report transformation or as documentation
- * for a precompiled tranformation.
- *
- * @param source the source
- * @return this
- */
- public FallbackBuilder source(final String source) {
- this.internal.source(source);
- return this;
- }
-
- /**
- * Specifices a source for this report. This is either used to compile the report transformation or as documentation
- * for a precompiled tranformation.
- *
- * @param source the source
- * @return this
- */
- public FallbackBuilder source(final URI source) {
- this.internal.source(source);
- return this;
- }
-
- /**
- * Specifices a source for this report. This is either used to compile the report transformation or as documentation
- * for a precompiled tranformation.
- *
- * @param source the source
- * @return this
- */
- public FallbackBuilder source(final Path source) {
- this.internal.source(source);
- return this;
- }
-
- /**
- * Sets the name of the report source to a specific value.
- *
- * @param name the name
- * @return this
- */
- public FallbackBuilder name(final String name) {
- this.internal.name(name);
- return this;
- }
-
-}
diff --git a/src/main/java/de/kosit/validationtool/config/Keys.java b/src/main/java/de/kosit/validationtool/config/Keys.java
deleted file mode 100644
index f814260..0000000
--- a/src/main/java/de/kosit/validationtool/config/Keys.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-/**
- * Defines some keys used for supplying additional parameters internally.
- *
- * @author Andreas Penski
- */
-public final class Keys {
-
- /**
- * The actual scenarios file location as used with {@link ConfigurationLoader}.
- */
- public static final String SCENARIOS_FILE = "scenarios_file";
-
- /**
- * The actual scenarios configuration represented as serializable tree. This either loaded from file or build
- * manually via {@link ConfigurationBuilder}
- */
- public static final String SCENARIO_DEFINITION = "scenario_definition";
-
- private Keys() {
- // hide
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/config/ReportBuilder.java b/src/main/java/de/kosit/validationtool/config/ReportBuilder.java
deleted file mode 100644
index 2d601cf..0000000
--- a/src/main/java/de/kosit/validationtool/config/ReportBuilder.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-import static org.apache.commons.lang3.ObjectUtils.isNotEmpty;
-
-import java.net.URI;
-import java.nio.file.Path;
-import java.util.Collections;
-
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.impl.ContentRepository;
-import de.kosit.validationtool.impl.Scenario.Transformation;
-import de.kosit.validationtool.impl.model.Result;
-import de.kosit.validationtool.model.scenarios.CreateReportType;
-import de.kosit.validationtool.model.scenarios.ResourceType;
-
-import net.sf.saxon.s9api.XsltExecutable;
-
-/**
- * Builder style configuration for the report transformation.
- *
- * @author Andreas Penski
- */
-@Slf4j
-public class ReportBuilder implements Builder> {
-
- private static final String DEFAULT_NAME = "manually created report";
-
- private XsltExecutable executable;
-
- private URI source;
-
- private String name;
-
- @Override
- public Result, String> build(final ContentRepository repository) {
- if (this.executable == null && this.source == null) {
- return createError(String.format("Must supply source location and/or executable for report '%s'", this.name));
- }
- final CreateReportType object = createObject();
- Result, String> result;
-
- try {
- if (this.executable == null) {
- this.executable = repository.createTransformation(object.getResource()).getExecutable();
- }
- result = new Result<>(new ImmutablePair<>(object, new Transformation(this.executable, object.getResource())));
- } catch (final IllegalStateException e) {
- log.error(e.getMessage(), e);
- result = createError(
- String.format("Can not create report configuration based on %s. Exception is %s", this.source, e.getMessage()));
- }
- return result;
- }
-
- private CreateReportType createObject() {
- final CreateReportType o = new CreateReportType();
- final ResourceType r = new ResourceType();
- r.setLocation(this.source.toASCIIString());
- r.setName(isNotEmpty(this.name) ? this.name : DEFAULT_NAME);
- o.setResource(r);
- return o;
- }
-
- private static Result, String> createError(final String msg) {
- return new Result<>(null, Collections.singletonList(msg));
- }
-
- /**
- * Specifices a source for this report. This is either used to compile the report transformation or as documentation
- * for a precompiled tranformation.
- *
- * @param source the source
- * @return this
- */
- public ReportBuilder source(final String source) {
- return source(URI.create(source));
- }
-
- /**
- * Specifices a source for this report. This is either used to compile the report transformation or as documentation
- * for a precompiled tranformation.
- *
- * @param source the source
- * @return this
- */
- public ReportBuilder source(final URI source) {
- this.source = source;
- return this;
- }
-
- /**
- * Specifices a source for this report. This is either used to compile the report transformation or as documentation
- * for a precompiled tranformation.
- *
- * @param source the source
- * @return this
- */
- public ReportBuilder source(final Path source) {
- return source(source.toUri());
- }
-
- /**
- * Sets the name of the report source to a specific value.
- *
- * @param name the name
- * @return this
- */
- public ReportBuilder name(final String name) {
- this.name = name;
- return this;
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/config/ScenarioBuilder.java b/src/main/java/de/kosit/validationtool/config/ScenarioBuilder.java
deleted file mode 100644
index e2b3632..0000000
--- a/src/main/java/de/kosit/validationtool/config/ScenarioBuilder.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-import static org.apache.commons.lang3.ObjectUtils.isNotEmpty;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import javax.xml.validation.Schema;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
-
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.impl.ContentRepository;
-import de.kosit.validationtool.impl.Scenario;
-import de.kosit.validationtool.impl.Scenario.Transformation;
-import de.kosit.validationtool.impl.model.Result;
-import de.kosit.validationtool.model.scenarios.CreateReportType;
-import de.kosit.validationtool.model.scenarios.DescriptionType;
-import de.kosit.validationtool.model.scenarios.NamespaceType;
-import de.kosit.validationtool.model.scenarios.ObjectFactory;
-import de.kosit.validationtool.model.scenarios.ScenarioType;
-import de.kosit.validationtool.model.scenarios.ValidateWithSchematron;
-import de.kosit.validationtool.model.scenarios.ValidateWithXmlSchema;
-
-import net.sf.saxon.s9api.XPathExecutable;
-
-/**
- * Builder for {@link Scenario} configuration.
- *
- * @author Andreas Penski
- */
-@RequiredArgsConstructor
-@Slf4j
-@Getter(AccessLevel.PACKAGE)
-public class ScenarioBuilder implements Builder {
-
- private static int nameCount = 0;
-
- private static final String DEFAULT_DESCRIPTION = "Dieses Scenario wurde per API erstellt";
-
- private final Map namespaces = new HashMap<>();
-
- private final XPathBuilder matchConfig = new XPathBuilder("match");
-
- private final XPathBuilder acceptConfig = new XPathBuilder("accept");
-
- private String name;
-
- private SchemaBuilder schemaBuilder;
-
- private final List schematronBuilders = new ArrayList<>();
-
- private ReportBuilder reportBuilder;
-
- private String description;
-
- @Override
- public Result build(final ContentRepository repository) {
- final List errors = new ArrayList<>();
- final Scenario scenario = new Scenario(createType());
- buildMatch(repository, errors, scenario);
- buildSchema(repository, errors, scenario);
- buildSchematron(repository, errors, scenario);
- buildReport(repository, errors, scenario);
- buildAccept(repository, errors, scenario);
- buildNamespaces(scenario);
- scenario.setFactory(repository.getResolvingConfigurationStrategy());
- scenario.setUriResolver(repository.getResolver());
- scenario.setUnparsedTextURIResolver(repository.getUnparsedTextURIResolver());
- return new Result<>(scenario, errors);
- }
-
- /**
- * Add a preconfiguration {@link XPathExecutable} to match the scenario
- *
- * @param executable the xpath executable
- * @return this
- */
- public ScenarioBuilder match(final XPathExecutable executable) {
- this.matchConfig.setExecutable(executable);
- return this;
- }
-
- /**
- * Add an xpath expression to match the scenario. You can leverage declared namespaces.
- *
- * @param xpath the expression
- * @return this
- */
- public ScenarioBuilder match(final String xpath) {
- this.matchConfig.setXpath(xpath);
- return this;
- }
-
- /**
- * Declare a namespace to use for match and accept configurations.
- *
- * @param prefix the prefix to use
- * @param uri the uri of this namespace
- * @return this
- */
- public ScenarioBuilder declareNamespace(final String prefix, final String uri) {
- this.namespaces.put(prefix, uri);
- return this;
- }
-
- /**
- * Add a preconfiguration {@link XPathExecutable} to compute acceptance for the scenario
- *
- * @param executable the xpath executable
- * @return this
- */
- public ScenarioBuilder acceptWith(final XPathExecutable executable) {
- this.acceptConfig.setExecutable(executable);
- return this;
- }
-
- /**
- * Add an xpath expression to compute acceptance for the scenario. You can leverage declared namespaces.
- *
- * @param acceptXpath the xpath expresison
- * @return this
- */
- public ScenarioBuilder acceptWith(final String acceptXpath) {
- this.acceptConfig.setXpath(acceptXpath);
- return this;
- }
-
- /**
- * Add a schematron validation configuration for this scenario.
- *
- * @param schematron the schematron configuration
- * @return this
- */
- public ScenarioBuilder validate(final SchematronBuilder schematron) {
- if (schematron != null) {
- this.schematronBuilders.add(schematron);
- }
- return this;
- }
-
- /**
- * Validate matching {@link de.kosit.validationtool.api.Input Inputs} with the specified schema configuration.
- *
- * @param schema the schema configuration
- * @return this
- */
- public ScenarioBuilder validate(final SchemaBuilder schema) {
- this.schemaBuilder = schema;
- return this;
- }
-
- /**
- * Add description for this scenario. This is part of the
- * {@link de.kosit.validationtool.model.reportInput.CreateReportInput} configuration and can be used while creating
- * the report
- *
- * @param description the description
- * @return this
- */
- public ScenarioBuilder description(final String description) {
- this.description = description;
- return this;
- }
-
- /**
- * Add a configuration for generating the final report for the {@link de.kosit.validationtool.api.Input}.
- *
- * @param reportBuilder the report configuration
- * @return this
- */
- public ScenarioBuilder with(final ReportBuilder reportBuilder) {
- this.reportBuilder = reportBuilder;
- return this;
- }
-
- private static String generateName() {
- return "manually created scenario " + nameCount++;
- }
-
- private void buildNamespaces(final Scenario scenario) {
- this.namespaces.putAll(this.acceptConfig.getNamespaces());
- this.namespaces.putAll(this.matchConfig.getNamespaces());
- final List all = this.namespaces.entrySet().stream().map(e -> {
- final NamespaceType n = new NamespaceType();
- n.setPrefix(e.getKey());
- n.setValue(e.getValue());
- return n;
- }).collect(Collectors.toList());
- scenario.getConfiguration().getNamespace().addAll(all);
- }
-
- private void buildMatch(final ContentRepository repository, final List errors, final Scenario scenario) {
- this.matchConfig.setNamespaces(this.namespaces);
- final Result result = this.matchConfig.build(repository);
- if (result.isValid()) {
- scenario.setMatchExecutable(result.getObject());
- scenario.getConfiguration().setMatch(this.matchConfig.getXPath());
- this.namespaces.putAll(this.matchConfig.getNamespaces());
- } else {
- errors.addAll(result.getErrors());
- }
- }
-
- private void buildAccept(final ContentRepository repository, final List errors, final Scenario scenario) {
- this.acceptConfig.setNamespaces(this.namespaces);
- if (this.acceptConfig.isAvailable()) {
- final Result result = this.acceptConfig.build(repository);
- if (result.isValid()) {
- scenario.setAcceptExecutable(result.getObject());
- scenario.getConfiguration().setAcceptMatch(this.acceptConfig.getXPath());
- this.namespaces.putAll(this.acceptConfig.getNamespaces());
- } else {
- errors.addAll(result.getErrors());
- }
- } else {
- log.debug("No accept configuration available");
- }
- }
-
- private void buildReport(final ContentRepository repository, final List errors, final Scenario scenario) {
- if (this.reportBuilder == null) {
- errors.add("Must supply report configuration");
- } else {
- final Result, String> result = this.reportBuilder.build(repository);
- if (result.isValid()) {
- scenario.setReportTransformation(result.getObject().getRight());
- scenario.getConfiguration().setCreateReport(result.getObject().getLeft());
- } else {
- errors.addAll(result.getErrors());
- }
- }
- }
-
- private void buildSchematron(final ContentRepository repository, final List errors, final Scenario scenario) {
- this.schematronBuilders.forEach(e -> {
- final Result, String> result = e.build(repository);
- if (result.isValid()) {
- scenario.getConfiguration().getValidateWithSchematron().add(result.getObject().getLeft());
- scenario.getSchematronValidations().add(result.getObject().getRight());
- } else {
- errors.addAll(result.getErrors());
- }
- });
- }
-
- private void buildSchema(final ContentRepository repository, final List errors, final Scenario scenario) {
- if (this.schemaBuilder == null) {
- errors.add("Must supply schema for validation");
- } else {
- final Result, String> result = this.schemaBuilder.build(repository);
- if (result.isValid()) {
- scenario.setSchema(result.getObject().getRight());
- scenario.getConfiguration().setValidateWithXmlSchema(result.getObject().getLeft());
- } else {
- errors.addAll(result.getErrors());
- }
- }
- }
-
- private ScenarioType createType() {
- final ScenarioType type = new ScenarioType();
- type.setName(isNotEmpty(this.name) ? this.name : generateName());
- final DescriptionType desc = new DescriptionType();
- desc.getPOrOlOrUl()
- .add(new ObjectFactory().createDescriptionTypeP(StringUtils.defaultIfBlank(this.description, DEFAULT_DESCRIPTION)));
- type.setDescription(desc);
- return type;
- }
-
- public ScenarioBuilder name(final String name) {
- this.name = name;
- return this;
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/config/SchemaBuilder.java b/src/main/java/de/kosit/validationtool/config/SchemaBuilder.java
deleted file mode 100644
index b6d4151..0000000
--- a/src/main/java/de/kosit/validationtool/config/SchemaBuilder.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-import static org.apache.commons.lang3.ObjectUtils.isNotEmpty;
-
-import java.net.URI;
-import java.nio.file.Path;
-import java.util.Collections;
-
-import javax.xml.validation.Schema;
-
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.impl.ContentRepository;
-import de.kosit.validationtool.impl.model.Result;
-import de.kosit.validationtool.model.scenarios.ResourceType;
-import de.kosit.validationtool.model.scenarios.ValidateWithXmlSchema;
-
-/**
- * Builder for Schema validation configuration.
- *
- * @author Andreas Penski
- */
-@Slf4j
-public class SchemaBuilder implements Builder> {
-
- private static final String DEFAULT_NAME = "manually configured";
-
- private Schema schema;
-
- private URI schemaLocation;
-
- private String name;
-
- @Override
- public Result, String> build(final ContentRepository repository) {
- if (this.schema == null && this.schemaLocation == null) {
- return createError(String.format("Must supply source location and/or executable for schema '%s'", this.name));
- }
- Result, String> result;
- try {
- if (this.schema == null) {
- this.schema = repository.createSchema(this.schemaLocation);
- }
- result = new Result<>(new ImmutablePair<>(createObject(), this.schema));
- } catch (final IllegalStateException e) {
- log.error(e.getMessage(), e);
- result = createError(String.format("Can not create schema based %s. Exception is %s", this.schemaLocation, e.getMessage()));
- }
-
- return result;
- }
-
- private ValidateWithXmlSchema createObject() {
- final ValidateWithXmlSchema o = new ValidateWithXmlSchema();
- final ResourceType r = new ResourceType();
- r.setName(isNotEmpty(this.name) ? this.name : DEFAULT_NAME);
- r.setLocation(this.schemaLocation != null ? this.schemaLocation.toASCIIString() : "manuelly configured");
- o.getResource().add(r);
- return o;
- }
-
- private static Result, String> createError(final String msg) {
- return new Result<>(null, Collections.singletonList(msg));
- }
-
- /**
- * Set a specific precompiled schema to check.
- *
- * @param schema the {@link Schema}
- * @return this
- */
- public SchemaBuilder schema(final Schema schema) {
- this.schema = schema;
- return this;
- }
-
- /**
- * Set a specific schema location either to compile or to document the precompiled one .
- *
- * @param schemaLocation the schema location as uri
- * @return this
- */
- public SchemaBuilder schemaLocation(final URI schemaLocation) {
- this.schemaLocation = schemaLocation;
- return this;
- }
-
- /**
- * Set a specific schema location either to compile or to document the precompiled one .
- *
- * @param schemaLocation the schema location as uri
- * @return this
- */
- public SchemaBuilder schemaLocation(final String schemaLocation) {
- return schemaLocation(URI.create(schemaLocation));
- }
-
- /**
- * Set a specific schema location either to compile or to document the precompiled one .
- *
- * @param schemaLocation the schema location as uri
- * @return this
- */
- public SchemaBuilder schemaLocation(final Path schemaLocation) {
- return schemaLocation(schemaLocation.toUri());
- }
-
- /**
- * Set a specific name to identify this schema.
- *
- * @param name the name of the schema
- * @return this
- */
- public SchemaBuilder name(final String name) {
- this.name = name;
- return this;
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/config/SchematronBuilder.java b/src/main/java/de/kosit/validationtool/config/SchematronBuilder.java
deleted file mode 100644
index bafcdca..0000000
--- a/src/main/java/de/kosit/validationtool/config/SchematronBuilder.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-import static org.apache.commons.lang3.ObjectUtils.isNotEmpty;
-
-import java.net.URI;
-import java.nio.file.Path;
-import java.util.Collections;
-
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.impl.ContentRepository;
-import de.kosit.validationtool.impl.Scenario.Transformation;
-import de.kosit.validationtool.impl.model.Result;
-import de.kosit.validationtool.model.scenarios.ResourceType;
-import de.kosit.validationtool.model.scenarios.ValidateWithSchematron;
-
-import net.sf.saxon.s9api.XsltExecutable;
-
-/**
- * Builder for schematron validation configuration.
- *
- * @author Andreas Penski
- */
-@Slf4j
-public class SchematronBuilder implements Builder> {
-
- private static final String DEFAULT_NAME = "manually configured";
-
- private XsltExecutable executable;
-
- private URI source;
-
- private String name;
-
- @Override
- public Result, String> build(final ContentRepository repository) {
- if (this.executable == null && this.source == null) {
- return createError(String.format("Must supply source location and/or executable for schematron '%s'", this.name));
- }
- final ValidateWithSchematron object = createObject();
- Result, String> result;
-
- try {
- if (this.executable == null) {
- this.executable = repository.createSchematronTransformation(object).getExecutable();
- }
- result = new Result<>(new ImmutablePair<>(object, new Transformation(this.executable, object.getResource())));
- } catch (final IllegalStateException e) {
- log.error(e.getMessage(), e);
- result = createError(
- String.format("Can not create schematron configuration based on %s. Exception is %s", this.source, e.getMessage()));
- }
- return result;
- }
-
- private ValidateWithSchematron createObject() {
- final ValidateWithSchematron o = new ValidateWithSchematron();
- final ResourceType r = new ResourceType();
- r.setLocation(this.source.toASCIIString());
- r.setName(isNotEmpty(this.name) ? this.name : DEFAULT_NAME);
- o.setResource(r);
- return o;
- }
-
- private static Result, String> createError(final String msg) {
- return new Result<>(null, Collections.singletonList(msg));
- }
-
- /**
- * Specifices a source for this schematron validation. This is either used to compile the schematron transformation
- * or as documentation for a precompiled tranformation.
- *
- * @param source the source
- * @return this
- */
- public SchematronBuilder source(final String source) {
- return source(URI.create(source));
- }
-
- /**
- * Specifices a source for this schematron validation. This is either used to compile the schematron transformation
- * or as documentation for a precompiled tranformation.
- *
- * @param source the source
- * @return this
- */
- public SchematronBuilder source(final URI source) {
- this.source = source;
- return this;
- }
-
- /**
- * Specifices a source for this schematron validation. This is either used to compile the schematron transformation
- * or as documentation for a precompiled tranformation.
- *
- * @param source the source
- * @return this
- */
- public SchematronBuilder source(final Path source) {
- return source(source.toUri());
- }
-
- /**
- * Sets the name of the schematron source to a specific value.
- *
- * @param name the name
- * @return this
- */
- public SchematronBuilder name(final String name) {
- this.name = name;
- return this;
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/config/XPathBuilder.java b/src/main/java/de/kosit/validationtool/config/XPathBuilder.java
deleted file mode 100644
index 713f951..0000000
--- a/src/main/java/de/kosit/validationtool/config/XPathBuilder.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.config;
-
-import static org.apache.commons.lang3.ObjectUtils.isNotEmpty;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.stream.StreamSupport;
-
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.StringUtils;
-
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.impl.ContentRepository;
-import de.kosit.validationtool.impl.model.Result;
-
-import net.sf.saxon.s9api.XPathExecutable;
-
-/**
- * Internal class to represent xpath configuration.
- *
- * @author Andreas Penski
- */
-@RequiredArgsConstructor
-@Getter
-@Setter
-@Slf4j
-class XPathBuilder implements Builder {
-
- private static final String[] IGNORED_PREFIXES = new String[] { "xsd", "saxon", "xsl", "xs", "xml" };
-
- private final String name;
-
- private String xpath;
-
- private XPathExecutable executable;
-
- @Setter(AccessLevel.PACKAGE)
- private Map namespaces;
-
- private static Result createError(final String msg) {
- return new Result<>(null, Collections.singletonList(msg));
- }
-
- Map getNamespaces() {
- if (this.namespaces == null) {
- this.namespaces = new HashMap<>();
- }
- return this.namespaces;
- }
-
- /**
- * Returns the xpath expression.
- *
- * @return xpath expression
- */
- public String getXPath() {
- return this.xpath == null && this.executable != null ? this.executable.getUnderlyingExpression().getInternalExpression().toString()
- : this.xpath;
- }
-
- public boolean isAvailable() {
- return this.executable != null || isNotEmpty(this.xpath);
- }
-
- @Override
- public Result build(final ContentRepository repository) {
- if (!isAvailable()) {
- return createError(String.format("No configuration for %s xpath expression found", this.name));
- }
- try {
- if (this.executable == null) {
- this.executable = repository.createXPath(this.xpath, getNamespaces());
- } else {
- this.xpath = extractExpression();
- extractNamespaces();
- }
- } catch (final IllegalStateException 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));
-
- }
- return new Result<>(this.executable);
- }
-
- private void extractNamespaces() {
-
- final Map ns = new HashMap<>();
- final Iterator iterator = this.executable.getUnderlyingExpression().getInternalExpression().getRetainedStaticContext()
- .iteratePrefixes();
- final Iterable iterable = () -> iterator;
- StreamSupport.stream(iterable.spliterator(), false).filter(e -> !ArrayUtils.contains(IGNORED_PREFIXES, e))
- .filter(StringUtils::isNotBlank).forEach(e -> ns.put(e, this.executable.getUnderlyingExpression().getInternalExpression()
- .getRetainedStaticContext().getURIForPrefix(e, false).toString()));
- getNamespaces().putAll(ns);
-
- }
-
- private String extractExpression() {
- return this.executable.getUnderlyingExpression().getInternalExpression().toString();
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/daemon/BaseHandler.java b/src/main/java/de/kosit/validationtool/daemon/BaseHandler.java
deleted file mode 100644
index e84dd28..0000000
--- a/src/main/java/de/kosit/validationtool/daemon/BaseHandler.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.daemon;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-
-/**
- * Simple base implemenation for http handlers. Doing I/O stuff.
- *
- * @author Andreas Penski
- */
-abstract class BaseHandler implements HttpHandler {
-
- protected static final String APPLICATION_XML = "application/xml";
-
- protected static void write(final HttpExchange exchange, final byte[] content, final String contentType) throws IOException {
- write(exchange, content, contentType, HttpStatus.SC_OK);
- }
-
- protected static void write(final HttpExchange exchange, final byte[] content, final String contentType, final int statusCode)
- throws IOException {
- write(exchange, contentType, os -> os.write(content), statusCode);
- }
-
- protected static void write(final HttpExchange exchange, final String contentType, final Write write, final int statusCode)
- throws IOException {
- exchange.getResponseHeaders().add("Content-Type", contentType);
- exchange.sendResponseHeaders(statusCode, 0);
- try ( final OutputStream os = exchange.getResponseBody() ) {
- write.write(os);
- }
- }
-
- protected static void error(final HttpExchange exchange, final int statusCode, final String message) throws IOException {
- final byte[] bytes = message.getBytes();
- exchange.getResponseHeaders().add("Content-Type", "text/plain");
- exchange.sendResponseHeaders(statusCode, bytes.length);
- try ( final OutputStream os = exchange.getResponseBody() ) {
- os.write(bytes);
- }
- }
-
- @FunctionalInterface
- protected interface Write {
-
- void write(OutputStream out) throws IOException;
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/daemon/CheckHandler.java b/src/main/java/de/kosit/validationtool/daemon/CheckHandler.java
deleted file mode 100644
index 5b44872..0000000
--- a/src/main/java/de/kosit/validationtool/daemon/CheckHandler.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.daemon;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.URI;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.commons.lang3.StringUtils;
-
-import com.sun.net.httpserver.HttpExchange;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.api.Check;
-import de.kosit.validationtool.api.InputFactory;
-import de.kosit.validationtool.api.Result;
-import de.kosit.validationtool.impl.input.SourceInput;
-import de.kosit.validationtool.impl.input.StreamHelper;
-
-import net.sf.saxon.s9api.Processor;
-import net.sf.saxon.s9api.SaxonApiException;
-import net.sf.saxon.s9api.Serializer;
-
-/**
- * Wir benötigen einen Handler, der zur Verarbeitung von HTTP-Anforderungen aufgerufen wird um hier die Verarbeitung des
- * POST Request zu realisieren.
- */
-@Slf4j
-@RequiredArgsConstructor
-class CheckHandler extends BaseHandler {
-
- private static final AtomicLong counter = new AtomicLong(0);
-
- private final Check implemenation;
-
- private final Processor processor;
-
- /**
- * Methode, die eine gegebene Anforderung verarbeitet und eine entsprechende Antwort generiert
- *
- * @param httpExchange kapselt eine empfangene HTTP-Anforderung und eine Antwort, die in einem Exchange generiert
- * werden soll.
- */
- @Override
- public void handle(final HttpExchange httpExchange) throws IOException {
- try {
- log.debug("Incoming request");
- final String requestMethod = httpExchange.getRequestMethod();
- // check neccessary, since gui can be disabled
- if (requestMethod.equals("POST")) {
- final BufferedInputStream buffered = StreamHelper.wrapPeekable(httpExchange.getRequestBody());
- if (!isMultipartFormData(httpExchange) && isContentAvailable(httpExchange, buffered)) {
- final SourceInput serverInput = (SourceInput) InputFactory.read(buffered,
- resolveInputName(httpExchange.getRequestURI()));
- final Result result = this.implemenation.checkInput(serverInput);
- write(httpExchange, serialize(result), APPLICATION_XML, resolveStatus(result));
- } else {
- error(httpExchange, HttpStatus.SC_BAD_REQUEST, "No content supplied");
- }
-
- } else {
- error(httpExchange, HttpStatus.SC_METHOD_NOT_ALLOWED, "Method not supported");
- }
- } catch (final Exception e) {
- log.error("Error checking entity", e);
- error(httpExchange, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal error: " + e.getMessage());
- }
- }
-
- private static boolean isContentAvailable(final com.sun.net.httpserver.HttpExchange httpExchange, final BufferedInputStream buffered)
- throws IOException {
- final String length = httpExchange.getRequestHeaders().getFirst("Content-length");
- if (StringUtils.isNumeric(length)) {
- return Integer.parseInt(length) > 0;
- }
- return streamContainsContent(buffered);
- }
-
- private static boolean isMultipartFormData(final HttpExchange httpExchange) {
- return httpExchange.getRequestHeaders().getFirst("Content-type").startsWith("multipart");
- }
-
- private static boolean streamContainsContent(final BufferedInputStream requestBody) throws IOException {
- return requestBody.available() > 0;
-
- }
-
- private static String resolveInputName(final URI requestURI) {
- final String path = requestURI.getPath();
- if (path.equalsIgnoreCase("/")) {
- return "supplied_instance_" + counter.incrementAndGet();
- }
- return path.substring((path.lastIndexOf('/') + 1));
- }
-
- private static int resolveStatus(final Result result) {
- if (result.isProcessingSuccessful()) {
- return result.isAcceptable() ? HttpStatus.SC_OK : HttpStatus.SC_NOT_ACCEPTABLE;
- }
- return HttpStatus.SC_UNPROCESSABLE_ENTITY;
- }
-
- private byte[] serialize(final Result result) {
- try ( final ByteArrayOutputStream out = new ByteArrayOutputStream() ) {
- final Serializer serializer = this.processor.newSerializer(out);
- serializer.serializeNode(result.getReport());
- return out.toByteArray();
- } catch (final SaxonApiException | IOException e) {
- log.error("Error serializing result", e);
- throw new IllegalStateException("Can not serialize result", e);
- }
- }
-
-}
diff --git a/src/main/java/de/kosit/validationtool/daemon/ConfigHandler.java b/src/main/java/de/kosit/validationtool/daemon/ConfigHandler.java
deleted file mode 100644
index 1e131a4..0000000
--- a/src/main/java/de/kosit/validationtool/daemon/ConfigHandler.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.daemon;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.net.URI;
-import java.util.List;
-import java.util.Optional;
-
-import org.apache.commons.io.IOUtils;
-
-import com.sun.net.httpserver.HttpExchange;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.api.Configuration;
-import de.kosit.validationtool.config.Keys;
-import de.kosit.validationtool.impl.ConversionService;
-import de.kosit.validationtool.model.scenarios.Scenarios;
-
-/**
- * Handler that returns the actual configuration used for this daemon instance.
- *
- * @author Andreas Penski
- */
-@Slf4j
-@RequiredArgsConstructor
-class ConfigHandler extends BaseHandler {
-
- private final List configuration;
-
- private final ConversionService conversionService;
-
- @Override
- public void handle(final HttpExchange exchange) throws IOException {
- try {
- final Optional xml = getSource();
- if (xml.isPresent()) {
- write(exchange, xml.get().getBytes(), APPLICATION_XML);
- } else {
- error(exchange, 404, "No configuration found");
- }
- } catch (final Exception e) {
- log.error("Error grabbing configuration", e);
- error(exchange, 500, "Error grabbing configuration: " + e.getMessage());
- }
- }
-
- private Optional getSource() {
-
- final URI fileUri = (URI) this.configuration.get(0).getAdditionalParameters().get(Keys.SCENARIOS_FILE);
- return fileUri != null ? loadFile(fileUri) : loadFromConfig();
- }
-
- private static Optional loadFile(final URI fileUri) {
- try ( final Reader in = new InputStreamReader(fileUri.toURL().openStream());
- final StringWriter out = new StringWriter() ) {
- IOUtils.copy(in, out);
- return Optional.of(out.toString());
- } catch (final IOException e) {
- return Optional.empty();
- }
- }
-
- private Optional loadFromConfig() {
- final Optional result;
- final Scenarios scenarios = (Scenarios) this.configuration.get(0).getAdditionalParameters().get(Keys.SCENARIO_DEFINITION);
- if (scenarios != null) {
- final String s = this.conversionService.writeXml(scenarios);
- result = Optional.of(s);
- } else {
- result = Optional.empty();
- }
- return result;
- }
-
-}
diff --git a/src/main/java/de/kosit/validationtool/daemon/Daemon.java b/src/main/java/de/kosit/validationtool/daemon/Daemon.java
deleted file mode 100644
index 4ad7fbd..0000000
--- a/src/main/java/de/kosit/validationtool/daemon/Daemon.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.daemon;
-
-import static de.kosit.validationtool.impl.Printer.writeOut;
-import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import com.sun.net.httpserver.HttpHandler;
-import com.sun.net.httpserver.HttpServer;
-
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.api.Configuration;
-import de.kosit.validationtool.impl.ConversionService;
-import de.kosit.validationtool.impl.DefaultCheck;
-import de.kosit.validationtool.model.daemon.HealthType;
-
-import net.sf.saxon.s9api.Processor;
-
-/**
- * HTTP-Daemon für die Bereitstellung der Prüf-Funktionalität via http.
- *
- * @author Roula Antoun
- */
-@RequiredArgsConstructor
-@Setter
-@Slf4j
-public class Daemon {
-
- private static final String DEFAULT_HOST = "localhost";
-
- private static final int DEFAULT_PORT = 8080;
-
- private String bindAddress;
-
- private int port;
-
- private int threadCount;
-
- private boolean guiEnabled = true;
-
- /**
- * Create a new daemon.
- *
- * @param hostname the interface to bind to
- * @param port the port to expose
- * @param threadCount the number of working threads
- */
- public Daemon(final String hostname, final int port, final int threadCount) {
- this.bindAddress = hostname;
- this.port = port;
- this.threadCount = threadCount;
- }
-
- /**
- * Methode zum Starten des Servers
- *
- * @param config the configuration to use
- */
- public void startServer(final Processor processor, final Configuration... config) {
- HttpServer server = null;
- try {
- final ConversionService healthConverter = new ConversionService();
- healthConverter.initialize(HealthType.class.getPackage());
- final ConversionService converter = new ConversionService();
- final DefaultCheck check = new DefaultCheck(processor, config);
-
- server = HttpServer.create(getSocket(), 0);
- server.createContext("/", createRootHandler(check, processor));
- server.createContext("/server/health", new HealthHandler(check.getConfiguration(), healthConverter));
- server.createContext("/server/config", new ConfigHandler(check.getConfiguration(), converter));
- server.setExecutor(createExecutor());
- server.start();
- log.info("Server {} started", server.getAddress());
- writeOut("Daemon started. Visit http://{0}", this.bindAddress + ":" + this.port);
- } catch (final IOException e) {
- log.error("Error starting HttpServer for Valdidator: {}", e.getMessage(), e);
- }
- }
-
- private HttpHandler createRootHandler(final DefaultCheck check, final Processor processor) {
- final HttpHandler rootHandler;
- final CheckHandler checkHandler = new CheckHandler(check, processor);
- if (this.guiEnabled) {
- final GuiHandler gui = new GuiHandler();
- rootHandler = new RoutingHandler(checkHandler, gui);
- } else {
- rootHandler = checkHandler;
- }
- return rootHandler;
- }
-
- private ExecutorService createExecutor() {
- return Executors.newFixedThreadPool(this.threadCount > 0 ? this.threadCount : Runtime.getRuntime().availableProcessors());
- }
-
- private InetSocketAddress getSocket() {
- return new InetSocketAddress(defaultIfBlank(this.bindAddress, DEFAULT_HOST), this.port > 0 ? this.port : DEFAULT_PORT);
- }
-
-}
diff --git a/src/main/java/de/kosit/validationtool/daemon/GuiHandler.java b/src/main/java/de/kosit/validationtool/daemon/GuiHandler.java
deleted file mode 100644
index ce56bac..0000000
--- a/src/main/java/de/kosit/validationtool/daemon/GuiHandler.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.daemon;
-
-import java.io.IOException;
-import java.net.URL;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-
-import org.apache.commons.io.IOUtils;
-
-import com.sun.net.httpserver.HttpExchange;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-public class GuiHandler extends BaseHandler {
-
- private static final URL INDEX_HTML = GuiHandler.class.getClassLoader().getResource("ui/index.html");
-
- public GuiHandler() {
- if (INDEX_HTML == null) {
- throw new IllegalStateException("No html found");
- }
- }
-
- @Override
- public void handle(final HttpExchange exchange) throws IOException {
- assert INDEX_HTML != null;
- final String path = exchange.getRequestURI().toASCIIString();
- if (path.equals("/")) {
- write(exchange, IOUtils.toString(INDEX_HTML, Charset.defaultCharset()).getBytes(), "text/html");
- } else {
- final URL resource = GuiHandler.class.getClassLoader().getResource("ui" + path);
- if (resource != null) {
- write(exchange, IOUtils.toString(resource, Charset.defaultCharset()).getBytes(),
- Mediatype.resolveBySuffix(resource.getPath()).getMimeType());
- } else {
- error(exchange, 404, "not found");
- }
- }
- }
-
- @RequiredArgsConstructor
- @Getter
- protected enum Mediatype {
-
- JS("application/javascript"), MD("text/markdown"), CSS("text/css"), SVG("image/svg+xml"), HTML("text/html"), PNG("image/png");
-
- private final String mimeType;
-
- static Mediatype resolveBySuffix(final String path) {
- return Arrays.stream(values()).filter(e -> path.toUpperCase().endsWith("." + e.name())).findFirst().orElse(Mediatype.MD);
- }
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/daemon/HealthHandler.java b/src/main/java/de/kosit/validationtool/daemon/HealthHandler.java
deleted file mode 100644
index 84a244a..0000000
--- a/src/main/java/de/kosit/validationtool/daemon/HealthHandler.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.daemon;
-
-import java.io.IOException;
-import java.util.List;
-
-import com.sun.net.httpserver.HttpExchange;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.api.Configuration;
-import de.kosit.validationtool.impl.ConversionService;
-import de.kosit.validationtool.impl.EngineInformation;
-import de.kosit.validationtool.model.daemon.ApplicationType;
-import de.kosit.validationtool.model.daemon.HealthType;
-import de.kosit.validationtool.model.daemon.MemoryType;
-
-/**
- * Handler that implements a simple health check. Useful for monitoring the service.
- *
- * @author Andreas Penski
- */
-@Slf4j
-@RequiredArgsConstructor
-class HealthHandler extends BaseHandler {
-
- private final List scenarios;
-
- private final ConversionService conversionService;
-
- @Override
- public void handle(final HttpExchange httpExchange) throws IOException {
- final HealthType health = createHealth();
- final String xml = this.conversionService.writeXml(health);
- write(httpExchange, xml.getBytes(), APPLICATION_XML);
-
- }
-
- private HealthType createHealth() {
- final HealthType h = new HealthType();
- h.setMemory(createMemory());
- h.setApplication(createApplication());
- h.setStatus(this.scenarios.stream().mapToLong(c -> c.getScenarios().size()).sum() > 0 ? "UP" : "DOWN");
- return h;
- }
-
- private static MemoryType createMemory() {
- final MemoryType m = new MemoryType();
- final Runtime runtime = Runtime.getRuntime();
- m.setFreeMemory(runtime.freeMemory());
- m.setMaxMemory(runtime.maxMemory());
- m.setTotalMemory(runtime.totalMemory());
- return m;
- }
-
- private static ApplicationType createApplication() {
- final ApplicationType a = new ApplicationType();
- a.setBuild(EngineInformation.getBuild());
- a.setName(EngineInformation.getName());
- a.setVersion(EngineInformation.getVersion());
- return a;
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/daemon/HttpStatus.java b/src/main/java/de/kosit/validationtool/daemon/HttpStatus.java
deleted file mode 100644
index a4bf079..0000000
--- a/src/main/java/de/kosit/validationtool/daemon/HttpStatus.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.daemon;
-
-/**
- * Status codes for the HTTP daemon.
- *
- * @author Andreas Penski
- */
-public interface HttpStatus {
-
- // --- 2xx Success ---
-
- /** {@code 200 OK} (HTTP/1.0 - RFC 1945) */
- int SC_OK = 200;
-
- // --- 4xx Client Error ---
-
- /** {@code 400 Bad Request} (HTTP/1.1 - RFC 2616) */
- int SC_BAD_REQUEST = 400;
-
- /** {@code 405 Method Not Allowed} (HTTP/1.1 - RFC 2616) */
- int SC_METHOD_NOT_ALLOWED = 405;
-
- /** {@code 406 Not Acceptable} (HTTP/1.1 - RFC 2616) */
- int SC_NOT_ACCEPTABLE = 406;
-
- /** {@code 422 Unprocessable Entity} (WebDAV - RFC 2518) */
- public static final int SC_UNPROCESSABLE_ENTITY = 422;
-
- /** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
- int SC_INTERNAL_SERVER_ERROR = 500;
-
-}
\ No newline at end of file
diff --git a/src/main/java/de/kosit/validationtool/daemon/RoutingHandler.java b/src/main/java/de/kosit/validationtool/daemon/RoutingHandler.java
deleted file mode 100644
index 1e6a81d..0000000
--- a/src/main/java/de/kosit/validationtool/daemon/RoutingHandler.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.daemon;
-
-import java.io.IOException;
-
-import com.sun.net.httpserver.HttpExchange;
-
-import lombok.RequiredArgsConstructor;
-
-/**
- * A simple handler which routes between the {@link CheckHandler} and the {@link GuiHandler} depending on the request.
- */
-@RequiredArgsConstructor
-class RoutingHandler extends BaseHandler {
-
- private final CheckHandler checkHandler;
-
- private final GuiHandler guiHandler;
-
- @Override
- public void handle(final HttpExchange exchange) throws IOException {
- final String requestMethod = exchange.getRequestMethod();
- if (requestMethod.equals("POST")) {
- this.checkHandler.handle(exchange);
- } else if (requestMethod.equals("GET")) {
- this.guiHandler.handle(exchange);
- } else {
- error(exchange, 405, String.format("Method % not supported", requestMethod));
- }
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/xml/ClassPathResourceResolver.java b/src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java
similarity index 74%
rename from src/main/java/de/kosit/validationtool/impl/xml/ClassPathResourceResolver.java
rename to src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java
index d961b2f..50d96d6 100644
--- a/src/main/java/de/kosit/validationtool/impl/xml/ClassPathResourceResolver.java
+++ b/src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java
@@ -1,20 +1,23 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
-package de.kosit.validationtool.impl.xml;
+package de.kosit.validationtool.impl;
import java.io.IOException;
import java.io.InputStream;
@@ -22,7 +25,7 @@ import java.io.Reader;
import java.net.URI;
import java.net.URL;
-import org.apache.commons.lang3.Strings;
+import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
@@ -37,7 +40,7 @@ import lombok.extern.slf4j.Slf4j;
* @author Andreas Penski
*/
@Slf4j
-public class ClassPathResourceResolver implements LSResourceResolver {
+class ClassPathResourceResolver implements LSResourceResolver {
/**
* Simple {@link LSInput}-Implementierung, die einen Stream liefern kann
@@ -90,7 +93,7 @@ public class ClassPathResourceResolver implements LSResourceResolver {
* @param basePath der Basispfad
*/
public ClassPathResourceResolver(final String basePath) {
- if (!Strings.CS.startsWith(basePath, "/")) {
+ if (!StringUtils.startsWith(basePath, "/")) {
throw new IllegalArgumentException("Base path must start with a slash");
}
this.base = URI.create(basePath + (basePath.endsWith("/") == basePath.length() > 1 ? "" : "/"));
@@ -109,9 +112,8 @@ public class ClassPathResourceResolver implements LSResourceResolver {
try {
final URL resource = resolved.isAbsolute() ? resolved.toURL()
: ClassPathResourceResolver.class.getResource(resolved.toASCIIString());
- final LSInputImpl input = new LSInputImpl(publicId, systemId, resolved.toASCIIString());
- // intentionally not closed, since xml stack wants it open upon return
final InputStream in = resource.openStream();
+ final LSInputImpl input = new LSInputImpl(publicId, systemId, resolved.toASCIIString());
input.setByteStream(in);
return input;
diff --git a/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java b/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java
index 042dd95..b1daca8 100644
--- a/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java
+++ b/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java
@@ -1,25 +1,30 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.impl;
import java.util.ArrayList;
-import java.util.List;
+import java.util.Collection;
import java.util.StringJoiner;
+import javax.xml.bind.ValidationEvent;
+import javax.xml.bind.ValidationEventHandler;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.TransformerException;
@@ -28,13 +33,12 @@ import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
+import lombok.Getter;
+
import de.kosit.validationtool.model.reportInput.XMLSyntaxError;
import de.kosit.validationtool.model.reportInput.XMLSyntaxErrorSeverity;
-import jakarta.xml.bind.ValidationEvent;
-import jakarta.xml.bind.ValidationEventHandler;
-import lombok.Getter;
-import net.sf.saxon.s9api.MessageListener2;
-import net.sf.saxon.s9api.QName;
+
+import net.sf.saxon.s9api.MessageListener;
import net.sf.saxon.s9api.XdmNode;
/**
@@ -43,13 +47,13 @@ import net.sf.saxon.s9api.XdmNode;
* @author Andreas Penski
*/
@Getter
-public class CollectingErrorEventHandler implements ValidationEventHandler, ErrorHandler, MessageListener2, ErrorListener {
+public class CollectingErrorEventHandler implements ValidationEventHandler, ErrorHandler, MessageListener, ErrorListener {
private static final int DEFAULT_ABORT_COUNT = 50;
- private final int stopProcessCount = DEFAULT_ABORT_COUNT;
+ private final Collection errors = new ArrayList<>();
- private final List errors = new ArrayList<>();
+ private final int stopProcessCount = DEFAULT_ABORT_COUNT;
private static XMLSyntaxError createError(final XMLSyntaxErrorSeverity severity, final String message) {
final XMLSyntaxError e = new XMLSyntaxError();
@@ -93,7 +97,7 @@ public class CollectingErrorEventHandler implements ValidationEventHandler, Erro
e.setColumnNumber(event.getLocator().getColumnNumber());
e.setRowNumber(event.getLocator().getLineNumber());
this.errors.add(e);
- return stopProcessCount != this.errors.size();
+ return this.stopProcessCount != this.errors.size();
}
/**
@@ -130,7 +134,7 @@ public class CollectingErrorEventHandler implements ValidationEventHandler, Erro
}
@Override
- public void message(final XdmNode content, final QName errorCode, final boolean terminate, final SourceLocator locator) {
+ public void message(final XdmNode content, final boolean terminate, final SourceLocator locator) {
final XMLSyntaxError e = new XMLSyntaxError();
if (locator != null) {
e.setColumnNumber(locator.getColumnNumber());
@@ -157,8 +161,9 @@ public class CollectingErrorEventHandler implements ValidationEventHandler, Erro
public String getErrorDescription() {
final StringJoiner joiner = new StringJoiner("\n");
- this.errors.forEach(e -> joiner.add(
- e.getSeverityCode().value() + " " + e.getMessage() + " At row " + e.getRowNumber() + " at pos " + e.getColumnNumber()));
+ this.errors.forEach(e -> joiner
+ .add(e.getSeverityCode().value() + " " + e.getMessage() + " At row " + e.getRowNumber() + " at pos "
+ + e.getColumnNumber()));
return joiner.toString();
}
}
\ No newline at end of file
diff --git a/src/main/java/de/kosit/validationtool/impl/ContentRepository.java b/src/main/java/de/kosit/validationtool/impl/ContentRepository.java
index e530040..0da0736 100644
--- a/src/main/java/de/kosit/validationtool/impl/ContentRepository.java
+++ b/src/main/java/de/kosit/validationtool/impl/ContentRepository.java
@@ -1,54 +1,44 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.impl;
import java.io.IOException;
-import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
import javax.xml.transform.Source;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.apache.commons.lang3.StringUtils;
+import org.w3c.dom.ls.LSResourceResolver;
import org.xml.sax.SAXException;
-import de.kosit.validationtool.api.ResolvingConfigurationStrategy;
-import de.kosit.validationtool.impl.Scenario.Transformation;
-import de.kosit.validationtool.impl.xml.RelativeUriResolver;
-import de.kosit.validationtool.impl.xml.StringTrimAdapter;
-import de.kosit.validationtool.model.scenarios.NamespaceType;
-import de.kosit.validationtool.model.scenarios.ResourceType;
-import de.kosit.validationtool.model.scenarios.ScenarioType;
-import de.kosit.validationtool.model.scenarios.ValidateWithSchematron;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import net.sf.saxon.lib.UnparsedTextURIResolver;
+
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XPathCompiler;
@@ -70,32 +60,8 @@ public class ContentRepository {
private final URI repository;
- private final URIResolver resolver;
+ private Schema reportInputSchema;
- private final UnparsedTextURIResolver unparsedTextURIResolver;
-
- private final SchemaFactory schemaFactory;
-
- @Getter
- private final ResolvingConfigurationStrategy resolvingConfigurationStrategy;
-
- /**
- * Creates a new {@link ContentRepository} based on configured security and resolving strategy and the specified
- * repository location.
- *
- * @param strategy the security and resolving strategy
- * @param repository the repository.
- */
- public ContentRepository(final Processor processor, final ResolvingConfigurationStrategy strategy, final URI repository) {
- this.repository = repository;
- this.resolvingConfigurationStrategy = strategy;
- this.processor = processor;
- this.resolver = this.resolvingConfigurationStrategy.createResolver(repository);
- this.unparsedTextURIResolver = this.resolvingConfigurationStrategy.createUnparsedTextURIResolver(repository);
- this.schemaFactory = this.resolvingConfigurationStrategy.createSchemaFactory();
- }
-
- @SuppressWarnings("squid:S2095")
private static Source resolve(final URL resource) {
try {
return new StreamSource(resource.openStream(), resource.toURI().getRawPath());
@@ -104,15 +70,20 @@ public class ContentRepository {
}
}
- private Schema createSchema(final Source[] schemaSources) {
+ private static Schema createSchema(final Source[] schemaSources, final LSResourceResolver resourceResolver) {
try {
- this.schemaFactory.setResourceResolver(null);
- return this.schemaFactory.newSchema(schemaSources);
+ final SchemaFactory sf = ObjectFactory.createSchemaFactory();
+ sf.setResourceResolver(resourceResolver);
+ return sf.newSchema(schemaSources);
} catch (final SAXException e) {
throw new IllegalArgumentException("Can not load schema from sources " + schemaSources[0].getSystemId(), e);
}
}
+ private static Schema createSchema(final Source[] schemaSources) {
+ return createSchema(schemaSources, null);
+ }
+
/**
* Lädt ein XSL von der angegebenen URI
*
@@ -125,18 +96,15 @@ public class ContentRepository {
final CollectingErrorEventHandler listener = new CollectingErrorEventHandler();
try {
xsltCompiler.setErrorListener(listener);
- if (getResolver() != null) {
- // otherwise use default resolver
- xsltCompiler.setURIResolver(getResolver());
- }
+ xsltCompiler.setURIResolver(createResolver());
- return xsltCompiler.compile(resolveInRepository(uri));
+ return xsltCompiler.compile(resolve(uri));
} catch (final SaxonApiException e) {
listener.getErrors().forEach(event -> event.log(log));
throw new IllegalStateException("Can not compile xslt executable for uri " + uri, e);
} finally {
if (!listener.hasErrors() && listener.hasEvents()) {
- log.warn("Received warnings or errors while loading a xslt script {}", uri);
+ log.warn("Received warnings while loading a xslt script {}", uri);
listener.getErrors().forEach(e -> e.log(log));
}
}
@@ -148,12 +116,35 @@ public class ContentRepository {
* @param url die url
* @return das erzeugte Schema
*/
- public Schema createSchema(final URL url) {
- return createSchema(new Source[] { resolve(url) });
+ public static Schema createSchema(final URL url) {
+ return createSchema(url, null);
}
- public Schema createSchema(final URI uri) {
- return createSchema(new Source[] { resolveInRepository(uri) });
+ public static Schema createSchema(final URL url, final LSResourceResolver resourceResolver) {
+ log.info("Load schema from source {}", url.getPath());
+ return createSchema(new Source[] { resolve(url) }, resourceResolver);
+ }
+
+ /**
+ * Liefert das definiert Schema für die Szenario-Konfiguration
+ *
+ * @return Scenario-Schema
+ */
+ public static Schema getScenarioSchema() {
+ return createSchema(ContentRepository.class.getResource("/xsd/scenarios.xsd"));
+ }
+
+ /**
+ * Liefert das definierte Schema für die Validierung des [@link CreateReportInput}
+ *
+ * @return ReportInput-Schema
+ */
+ public Schema getReportInputSchema() {
+ if (this.reportInputSchema == null) {
+ final Source source = resolve(ContentRepository.class.getResource("/xsd/createReportInput.xsd"));
+ this.reportInputSchema = createSchema(new Source[] { source }, new ClassPathResourceResolver("/xsd"));
+ }
+ return this.reportInputSchema;
}
/**
@@ -163,37 +154,12 @@ public class ContentRepository {
* @return das Schema
*/
public Schema createSchema(final Collection uris) {
- return createSchema(uris.stream().map(s -> resolveInRepository(URI.create(s))).toArray(Source[]::new));
+ return createSchema(uris.stream().map(s -> resolve(URI.create(s))).toArray(Source[]::new));
}
- /**
- * Liefert das Schema zu diesem Szenario.
- *
- * @return das passende Schema
- */
- public Schema createSchema(final ScenarioType s) {
- Schema schema = null;
- if (s.getValidateWithXmlSchema() != null) {
- final List schemaResources = s.getValidateWithXmlSchema().getResource().stream().map(ResourceType::getLocation)
- .collect(Collectors.toList());
- schema = createSchema(schemaResources);
- }
- return schema;
- }
-
- private Source resolveInRepository(final URI source) {
- try {
- if (this.resolver == null) {
- // TODO wie wird ohne resolver das richtige Artefakt gefunden?
- // assume local
- final URI resolved = RelativeUriResolver.resolve(source, this.repository);
- return new StreamSource(resolved.toASCIIString());
- }
- return this.resolver.resolve(source.toString(), this.repository.toString());
- } catch (final TransformerException e) {
- log.error("Error resolving source {}", source, e);
- throw new IllegalStateException(String.format("Can not resolve %s in repository %s", source, this.repository), e);
- }
+ private Source resolve(final URI source) {
+ final URI resolved = RelativeUriResolver.resolve(source, this.repository);
+ return new StreamSource(resolved.toASCIIString());
}
/**
@@ -217,65 +183,11 @@ public class ContentRepository {
}
/**
- * Returns the {@link URIResolver} to use for resolving xml artifacts.
+ * Erzeugt einen resolver für dieses Repository, der nur relativ auflösen kann
*
- * @return the resolver
+ * @return ein neuer Resolver
*/
- public URIResolver getResolver() {
- return this.resolver;
- }
-
- public UnparsedTextURIResolver getUnparsedTextURIResolver() {
- return this.unparsedTextURIResolver;
- }
-
- /**
- * Gibt eine Transformation zurück.
- *
- * @return initialisierte Transformation
- */
- public Transformation createReportTransformation(final ScenarioType t) {
- final ResourceType resource = t.getCreateReport().getResource();
- return createTransformation(resource);
- }
-
- public Transformation createTransformation(final ResourceType resource) {
- final XsltExecutable executable = loadXsltScript(URI.create(resource.getLocation()));
- return new Transformation(executable, resource);
- }
-
- public XPathExecutable createMatchExecutable(final ScenarioType s) {
- final Map namespaces = s.getNamespace().stream()
- .collect(Collectors.toMap(NamespaceType::getPrefix, ns -> StringTrimAdapter.trim(ns.getValue())));
- return createXPath(s.getMatch(), namespaces);
- }
-
- public XPathExecutable createAccepptExecutable(final ScenarioType s) {
- final Map namespaces = s.getNamespace().stream()
- .collect(Collectors.toMap(NamespaceType::getPrefix, ns -> StringTrimAdapter.trim(ns.getValue())));
- return createXPath(s.getAcceptMatch(), namespaces);
- }
-
- public List createSchematronTransformations(final ScenarioType s) {
- return s.getValidateWithSchematron().isEmpty() ? Collections.emptyList()
- : s.getValidateWithSchematron().stream().map(this::createSchematronTransformation).collect(Collectors.toList());
- }
-
- public Transformation createSchematronTransformation(final ValidateWithSchematron validateWithSchematron) {
- return createTransformation(validateWithSchematron.getResource());
- }
-
- public Transformation createIdentityTransformation() {
- final URL url = ContentRepository.class.getClassLoader().getResource("transform/identity.xsl");
- try ( final InputStream input = url.openStream() ) {
- final XsltCompiler xsltCompiler = getProcessor().newXsltCompiler();
- final XsltExecutable executable = xsltCompiler.compile(new StreamSource(input));
- final ResourceType resource = new ResourceType();
- resource.setName("identity");
- resource.setLocation(url.toString());
- return new Transformation(executable, resource);
- } catch (final IOException | SaxonApiException e) {
- throw new IllegalStateException("Error creating identity transformation", e);
- }
+ public RelativeUriResolver createResolver() {
+ return new RelativeUriResolver(this.repository);
}
}
diff --git a/src/main/java/de/kosit/validationtool/impl/ConversionService.java b/src/main/java/de/kosit/validationtool/impl/ConversionService.java
index bd0ba6c..2bc4185 100644
--- a/src/main/java/de/kosit/validationtool/impl/ConversionService.java
+++ b/src/main/java/de/kosit/validationtool/impl/ConversionService.java
@@ -1,17 +1,20 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.impl;
@@ -24,7 +27,16 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.StringJoiner;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.JAXBIntrospector;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.ValidationEventHandler;
+import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
@@ -35,15 +47,8 @@ import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import org.apache.commons.lang3.StringUtils;
+import org.w3c.dom.Document;
-import jakarta.xml.bind.JAXBContext;
-import jakarta.xml.bind.JAXBElement;
-import jakarta.xml.bind.JAXBException;
-import jakarta.xml.bind.JAXBIntrospector;
-import jakarta.xml.bind.Marshaller;
-import jakarta.xml.bind.Unmarshaller;
-import jakarta.xml.bind.ValidationEventHandler;
-import jakarta.xml.bind.annotation.XmlRegistry;
import lombok.extern.slf4j.Slf4j;
/**
@@ -78,19 +83,9 @@ public class ConversionService {
}
private static final int MAX_LOG_CONTENT = 50;
-
// context setup
private JAXBContext jaxbContext;
- public JAXBContext
-
- getJaxbContext() {
- if (this.jaxbContext == null) {
- initialize();
- }
- return this.jaxbContext;
- }
-
private static QName createQName(final T model) {
return new QName(model.getClass().getSimpleName().toLowerCase());
}
@@ -129,7 +124,7 @@ public class ConversionService {
public void initialize(final Collection context) {
final String[] packages = context != null ? context.stream().map(Package::getName).toArray(String[]::new) : new String[0];
final StringJoiner joiner = new StringJoiner(":");
- Arrays.stream(packages).forEach(joiner::add);
+ Arrays.stream(packages).forEach(p -> joiner.add(p));
initialize(joiner.toString());
}
@@ -140,14 +135,21 @@ public class ConversionService {
*/
private void initialize(final String contextPath) {
try {
- this.jaxbContext = JAXBContext.newInstance(contextPath, ConversionService.class.getClassLoader());
+ this.jaxbContext = JAXBContext.newInstance(contextPath);
} catch (final JAXBException e) {
throw new IllegalStateException(String.format("Can not create JAXB context for given context: %s", contextPath), e);
}
}
+ private JAXBContext getJaxbContext() {
+ if (this.jaxbContext == null) {
+ initialize();
+ }
+ return this.jaxbContext;
+ }
+
/**
- * Unmarshalls a specific XML model into a defined Java object.
+ * Unmarshalls a specifc xml model into a defined java object.
*
* @param xml the xml
* @param type the expected type created
@@ -219,7 +221,6 @@ public class ConversionService {
final XMLOutputFactory xof = XMLOutputFactory.newFactory();
final XMLStreamWriter xmlStreamWriter = xof.createXMLStreamWriter(w);
if (null == introspector.getElementName(model)) {
- @SuppressWarnings({ "rawtypes", "unchecked" })
final JAXBElement jaxbElement = new JAXBElement(createQName(model), model.getClass(), model);
marshaller.marshal(jaxbElement, xmlStreamWriter);
} else {
@@ -232,6 +233,25 @@ public class ConversionService {
}
}
+ public Document writeDocument(final T input) {
+ if (input == null) {
+ throw new ConversionExeption("Can not serialize null");
+ }
+ final DocumentBuilder builder = ObjectFactory.createDocumentBuilder(false);
+ final Document document = builder.newDocument();
+
+ // Marshal the Object to a Document
+ Marshaller marshaller = null;
+ try {
+ marshaller = getJaxbContext().createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ marshaller.marshal(input, document);
+ return document;
+ } catch (final JAXBException e) {
+ throw new ConversionExeption(String.format("Error serializing Object %s to document", input.getClass().getName()), e);
+ }
+ }
+
public T readDocument(final Source source, final Class type) {
try {
final Unmarshaller u = getJaxbContext().createUnmarshaller();
diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/CreateDocumentIdentificationAction.java b/src/main/java/de/kosit/validationtool/impl/CreateDocumentIdentificationAction.java
similarity index 50%
rename from src/main/java/de/kosit/validationtool/impl/tasks/CreateDocumentIdentificationAction.java
rename to src/main/java/de/kosit/validationtool/impl/CreateDocumentIdentificationAction.java
index b65c1ed..d0b87f0 100644
--- a/src/main/java/de/kosit/validationtool/impl/tasks/CreateDocumentIdentificationAction.java
+++ b/src/main/java/de/kosit/validationtool/impl/CreateDocumentIdentificationAction.java
@@ -1,21 +1,6 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl.tasks;
+package de.kosit.validationtool.impl;
+import de.kosit.validationtool.impl.tasks.CheckAction;
import de.kosit.validationtool.model.reportInput.DocumentIdentificationType;
/**
@@ -23,7 +8,7 @@ import de.kosit.validationtool.model.reportInput.DocumentIdentificationType;
*
* @author Andreas Penski
*/
-public class CreateDocumentIdentificationAction implements CheckAction {
+class CreateDocumentIdentificationAction implements CheckAction {
@Override
public void check(final Bag transporter) {
diff --git a/src/main/java/de/kosit/validationtool/impl/DateFactory.java b/src/main/java/de/kosit/validationtool/impl/DateFactory.java
deleted file mode 100644
index 2e9bb9a..0000000
--- a/src/main/java/de/kosit/validationtool/impl/DateFactory.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl;
-
-import java.util.Date;
-import java.util.GregorianCalendar;
-
-import javax.xml.datatype.DatatypeFactory;
-import javax.xml.datatype.XMLGregorianCalendar;
-
-import lombok.SneakyThrows;
-
-/**
- * @author Andreas Penski
- */
-public class DateFactory {
-
- private DateFactory() {
- // hide
- }
-
- @SneakyThrows
- public static XMLGregorianCalendar createTimestamp() {
- final GregorianCalendar cal = new GregorianCalendar();
- cal.setTime(new Date());
- return DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
-
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java
index 26ab801..f47d84c 100644
--- a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java
+++ b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java
@@ -1,63 +1,55 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.impl;
-import static de.kosit.validationtool.impl.DateFactory.createTimestamp;
-
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
+import java.util.Collection;
import java.util.List;
-import java.util.Map;
-import java.util.Optional;
import java.util.stream.Collectors;
-import org.oclc.purl.dsdl.svrl.FailedAssert;
-import org.oclc.purl.dsdl.svrl.SchematronOutput;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.Check;
-import de.kosit.validationtool.api.Configuration;
+import de.kosit.validationtool.api.CheckConfiguration;
import de.kosit.validationtool.api.Input;
import de.kosit.validationtool.api.Result;
import de.kosit.validationtool.api.XmlError;
-import de.kosit.validationtool.impl.model.CustomFailedAssert;
import de.kosit.validationtool.impl.tasks.CheckAction;
import de.kosit.validationtool.impl.tasks.CheckAction.Bag;
import de.kosit.validationtool.impl.tasks.ComputeAcceptanceAction;
-import de.kosit.validationtool.impl.tasks.CreateDocumentIdentificationAction;
import de.kosit.validationtool.impl.tasks.CreateReportAction;
import de.kosit.validationtool.impl.tasks.DocumentParseAction;
import de.kosit.validationtool.impl.tasks.ScenarioSelectionAction;
import de.kosit.validationtool.impl.tasks.SchemaValidationAction;
import de.kosit.validationtool.impl.tasks.SchematronValidationAction;
import de.kosit.validationtool.impl.tasks.ValidateReportInputAction;
-import de.kosit.validationtool.impl.xml.ProcessorProvider;
import de.kosit.validationtool.model.reportInput.CreateReportInput;
import de.kosit.validationtool.model.reportInput.EngineType;
import de.kosit.validationtool.model.reportInput.XMLSyntaxError;
-import de.kosit.validationtool.model.scenarios.ErrorLevelType;
-import de.kosit.validationtool.model.scenarios.ScenarioType;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
+
import net.sf.saxon.s9api.Processor;
/**
- * The reference implementation for the validation process. After initialisation, instances are threadsafe and should be
- * reused since initializing saxon runtime objects is an rather heavyweight process.
+ * Die Referenz-Implementierung für den Prüfprozess. Nach initialer Konfiguration ist diese Klasse threadsafe und kann
+ * in Server-Umgebungen eingesetzt werden
*
* @author Andreas Penski
*/
@@ -65,56 +57,49 @@ import net.sf.saxon.s9api.Processor;
public class DefaultCheck implements Check {
@Getter
- private final ConversionService conversionService;
+ private final ScenarioRepository repository;
@Getter
- private final List configuration;
+ private final ContentRepository contentRepository;
+
+ @Getter
+ private final ConversionService conversionService;
@Getter
private final List checkSteps;
- @Getter
- private final Processor processor;
-
- public DefaultCheck(final Configuration... configuration) {
- this(ProcessorProvider.getProcessor(), configuration);
- }
-
/**
- * Creates a new instance for the {@link Configuration}.
+ * Erzeugt eine neue Instanz mit der angegebenen Konfiguration.
*
- * @param configuration the Configuration
+ * @param configuration die Konfiguration
*/
- public DefaultCheck(final Processor processor, final Configuration... configuration) {
- this.configuration = Arrays.asList(configuration);
- this.processor = processor;
+ public DefaultCheck(final CheckConfiguration configuration) {
+ final Processor processor = ObjectFactory.createProcessor();
this.conversionService = new ConversionService();
-
+ this.contentRepository = new ContentRepository(processor, configuration.getScenarioRepository());
+ this.repository = new ScenarioRepository(this.contentRepository);
+ this.repository.initialize(configuration);
this.checkSteps = new ArrayList<>();
- this.checkSteps.add(new DocumentParseAction(processor));
this.checkSteps.add(new CreateDocumentIdentificationAction());
- this.checkSteps.add(new ScenarioSelectionAction(new ScenarioRepository(configuration)));
- this.checkSteps.add(new SchemaValidationAction(processor));
- this.checkSteps.add(new SchematronValidationAction(this.conversionService));
- this.checkSteps.add(new ValidateReportInputAction(this.conversionService, SchemaProvider.getReportInputSchema()));
- this.checkSteps.add(new CreateReportAction(processor, this.conversionService));
+ this.checkSteps.add(new DocumentParseAction());
+ this.checkSteps.add(new ScenarioSelectionAction(this.repository));
+ this.checkSteps.add(new SchemaValidationAction());
+ this.checkSteps.add(new SchematronValidationAction(this.contentRepository, this.conversionService));
+ this.checkSteps.add(new ValidateReportInputAction(this.conversionService, this.contentRepository.getReportInputSchema()));
+ this.checkSteps.add(new CreateReportAction(processor, this.conversionService, this.repository, this.contentRepository));
this.checkSteps.add(new ComputeAcceptanceAction());
}
protected static CreateReportInput createReport() {
final CreateReportInput type = new CreateReportInput();
final EngineType e = new EngineType();
- e.setName(EngineInformation.getName() + " " + EngineInformation.getVersion());
+ e.setName(EngineInformation.getName());
type.setEngine(e);
- type.setTimestamp(createTimestamp());
+ type.setTimestamp(ObjectFactory.createTimestamp());
type.setFrameworkVersion(EngineInformation.getFrameworkVersion());
return type;
}
- protected boolean isSuccessful(final Map results) {
- return results.entrySet().stream().allMatch(e -> e.getValue().isAcceptable());
- }
-
@Override
public Result checkInput(final Input input) {
final CheckAction.Bag t = new CheckAction.Bag(input, createReport());
@@ -137,42 +122,22 @@ public class DefaultCheck implements Check {
}
private Result createResult(final Bag t) {
- final DefaultResult result = new DefaultResult(t.getReport(), t.getAcceptStatus(), new HtmlExtractor(this.processor));
+ final DefaultResult result = new DefaultResult(t.getReport(), t.getAcceptStatus(), new HtmlExtractor(this.contentRepository));
result.setWellformed(t.getParserResult().isValid());
result.setReportInput(t.getReportInput());
if (t.getSchemaValidationResult() != null) {
result.setSchemaViolations(convertErrors(t.getSchemaValidationResult().getErrors()));
}
result.setProcessingSuccessful(!t.isStopped() && t.isFinished());
- result.setSchematronResult(t.getReportInput().getValidationResultsSchematron().stream().filter(e -> e.getResults() != null)
+ result.setSchematronResult(t.getReportInput().getValidationResultsSchematron().stream()
.map(e -> e.getResults().getSchematronOutput()).collect(Collectors.toList()));
-
- result.setCustomFailedAsserts(buildCustomFailedAssertsList(t, result.getSchematronResult()));
-
return result;
}
- private List buildCustomFailedAssertsList(final Bag t, final List schematronResult) {
- // Get Map of Assertion ID to custom error levels for the current scenario
- final Map customLevels = Optional.ofNullable(t.getScenarioSelectionResult())
- .map(de.kosit.validationtool.impl.model.Result::getObject).map(Scenario::getConfiguration)
- .map(ScenarioType::getCreateReport)
- .map(r -> r.getCustomLevel().stream()
- .flatMap(customLevel -> customLevel.getValue().stream().map(id -> Map.entry(id, customLevel.getLevel())))
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)))
- .orElse(Collections.emptyMap());
-
- // Now check all failed assertions of all schematron validations if they contain a failed assertion with one of
- // the changed IDs
- return schematronResult.stream().flatMap(x -> x.getActivePatternAndFiredRuleAndFailedAssert().stream())
- .filter(FailedAssert.class::isInstance).map(FailedAssert.class::cast).filter(fa -> customLevels.containsKey(fa.getId()))
- .map(fa -> new CustomFailedAssert(fa, customLevels.get(fa.getId()))).collect(Collectors.toList());
- }
-
- @SuppressWarnings("unchecked")
- private static List convertErrors(final List errors) {
+ private static List convertErrors(final Collection errors) {
// noinspection unchecked
return (List) (List>) errors;
}
+
}
diff --git a/src/main/java/de/kosit/validationtool/impl/DefaultResult.java b/src/main/java/de/kosit/validationtool/impl/DefaultResult.java
index 162e3f9..e8be8ac 100644
--- a/src/main/java/de/kosit/validationtool/impl/DefaultResult.java
+++ b/src/main/java/de/kosit/validationtool/impl/DefaultResult.java
@@ -1,19 +1,3 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package de.kosit.validationtool.impl;
import java.util.Collections;
@@ -25,14 +9,15 @@ import org.oclc.purl.dsdl.svrl.SchematronOutput;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import de.kosit.validationtool.api.AcceptRecommendation;
-import de.kosit.validationtool.api.Result;
-import de.kosit.validationtool.api.XmlError;
-import de.kosit.validationtool.impl.model.CustomFailedAssert;
-import de.kosit.validationtool.model.reportInput.CreateReportInput;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
+
+import de.kosit.validationtool.api.AcceptRecommendation;
+import de.kosit.validationtool.api.Result;
+import de.kosit.validationtool.api.XmlError;
+import de.kosit.validationtool.model.reportInput.CreateReportInput;
+
import net.sf.saxon.dom.NodeOverNodeInfo;
import net.sf.saxon.s9api.XdmNode;
@@ -66,11 +51,6 @@ public class DefaultResult implements Result {
@Setter(AccessLevel.PACKAGE)
private List schematronResult;
- /**
- * List of custom failed asserts per Schematron level. Only failed assertions with a custom level are contained.
- */
- private List customFailedAsserts;
-
@Getter
@Setter
private boolean processingSuccessful;
@@ -153,28 +133,13 @@ public class DefaultResult implements Result {
}
private List filterSchematronResult(final Class type) {
- return this.schematronResult != null
- ? this.schematronResult.stream().flatMap(e -> e.getActivePatternAndFiredRuleAndFailedAssert().stream())
- .filter(type::isInstance).map(type::cast).collect(Collectors.toList())
+ return getSchematronResult() != null
+ ? getSchematronResult().stream().filter(type::isInstance).map(type::cast).collect(Collectors.toList())
: Collections.emptyList();
}
- private boolean isSchematronEvaluated() {
- return this.schematronResult != null
- && this.schematronResult.stream().noneMatch(e -> e.getActivePatternAndFiredRuleAndFailedAssert().isEmpty());
- }
-
@Override
public boolean isSchematronValid() {
- return isSchematronEvaluated() && getFailedAsserts().isEmpty();
- }
-
- @Override
- public List getCustomFailedAsserts() {
- return this.customFailedAsserts;
- }
-
- public void setCustomFailedAsserts(List customFailedAsserts) {
- this.customFailedAsserts = customFailedAsserts;
+ return getSchematronResult() != null && getFailedAsserts().isEmpty();
}
}
diff --git a/src/main/java/de/kosit/validationtool/impl/EngineInformation.java b/src/main/java/de/kosit/validationtool/impl/EngineInformation.java
index c5a7bd3..10692ec 100644
--- a/src/main/java/de/kosit/validationtool/impl/EngineInformation.java
+++ b/src/main/java/de/kosit/validationtool/impl/EngineInformation.java
@@ -1,19 +1,3 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package de.kosit.validationtool.impl;
import java.io.IOException;
@@ -81,10 +65,6 @@ 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/HtmlExtractor.java b/src/main/java/de/kosit/validationtool/impl/HtmlExtractor.java
index 0c2677a..59bdc38 100644
--- a/src/main/java/de/kosit/validationtool/impl/HtmlExtractor.java
+++ b/src/main/java/de/kosit/validationtool/impl/HtmlExtractor.java
@@ -1,19 +1,3 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package de.kosit.validationtool.impl;
import java.io.StringWriter;
@@ -22,16 +6,13 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
-import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Element;
import lombok.RequiredArgsConstructor;
import net.sf.saxon.dom.NodeOverNodeInfo;
-import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
-import net.sf.saxon.s9api.XPathCompiler;
import net.sf.saxon.s9api.XPathExecutable;
import net.sf.saxon.s9api.XPathSelector;
import net.sf.saxon.s9api.XdmItem;
@@ -45,51 +26,38 @@ import net.sf.saxon.s9api.XdmNode;
@RequiredArgsConstructor
public class HtmlExtractor {
- private final Processor processor;
+ private final ContentRepository repository;
private XPathExecutable executable;
- public List extract(final XdmNode xdmSource) {
+ public List extract(XdmNode xdmSource) {
try {
final XPathSelector selector = getSelector();
selector.setContextItem(xdmSource);
- return selector.stream().map(HtmlExtractor::castToNode).collect(Collectors.toList());
+ return selector.stream().map(this::castToNode).collect(Collectors.toList());
- } catch (final SaxonApiException e) {
+ } catch (SaxonApiException e) {
throw new IllegalStateException("Can not extract html content", e);
}
}
- private static XdmNode castToNode(final XdmItem xdmItem) {
+ private XdmNode castToNode(final XdmItem xdmItem) {
return (XdmNode) xdmItem;
}
private XPathSelector getSelector() {
- if (this.executable == null) {
- final Map ns = new HashMap<>();
+ if (executable == null) {
+ Map ns = new HashMap<>();
ns.put("html", "http://www.w3.org/1999/xhtml");
- this.executable = createXPath("//html:html", ns);
+ executable = repository.createXPath("//html:html", ns);
}
- return this.executable.load();
+ return executable.load();
}
- private XPathExecutable createXPath(final String expression, final Map namespaces) {
- try {
- final XPathCompiler compiler = this.processor.newXPathCompiler();
- if (namespaces != null) {
- namespaces.forEach(compiler::declareNamespace);
- }
- return compiler.compile(expression);
- } catch (final SaxonApiException e) {
- throw new IllegalStateException(String.format("Can not compile xpath match expression '%s'",
- StringUtils.isNotBlank(expression) ? expression : "EMPTY EXPRESSION"), e);
- }
- }
-
- private String convertToString(final XdmNode element) {
+ private static String convertToString(final XdmNode element) {
try {
final StringWriter writer = new StringWriter();
- final Serializer serializer = this.processor.newSerializer(writer);
+ final Serializer serializer = ObjectFactory.createProcessor().newSerializer(writer);
serializer.serializeNode(element);
return writer.toString();
} catch (final SaxonApiException e) {
@@ -104,7 +72,7 @@ public class HtmlExtractor {
* @return HTML-Fragment als String
*/
public List extractAsString(final XdmNode node) {
- return extract(node).stream().map(this::convertToString).collect(Collectors.toList());
+ return extract(node).stream().map(HtmlExtractor::convertToString).collect(Collectors.toList());
}
public List extractAsElement(final XdmNode node) {
diff --git a/src/main/java/de/kosit/validationtool/impl/ObjectFactory.java b/src/main/java/de/kosit/validationtool/impl/ObjectFactory.java
new file mode 100644
index 0000000..eace869
--- /dev/null
+++ b/src/main/java/de/kosit/validationtool/impl/ObjectFactory.java
@@ -0,0 +1,260 @@
+/*
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package de.kosit.validationtool.impl;
+
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import javax.xml.XMLConstants;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+import lombok.extern.slf4j.Slf4j;
+
+import net.sf.saxon.Configuration;
+import net.sf.saxon.expr.XPathContext;
+import net.sf.saxon.lib.CollectionFinder;
+import net.sf.saxon.lib.FeatureKeys;
+import net.sf.saxon.lib.OutputURIResolver;
+import net.sf.saxon.lib.ResourceCollection;
+import net.sf.saxon.lib.UnparsedTextURIResolver;
+import net.sf.saxon.s9api.Processor;
+import net.sf.saxon.trans.XPathException;
+
+/**
+ * Eine Factory für häufig verwendete Objekte mit XML. Zentralisiert die XML Security Konfiguration. Die Konfiguration
+ * basiert auf den OWASP-Empfehlungen.
+ *
+ * Diese Klasse ist stark abhängig von der Verwendung eines Oracle JDK. Alternative JDKs haben u.U. eine andere SAX- /
+ * StAX- / XML-Implementierug und profitieren entsprechend NICHT von den hier getroffenen Einstellungen.
+ *
+ * @author Andreas Penski
+ */
+@Slf4j
+public class ObjectFactory {
+
+ private static class SecureUriResolver implements CollectionFinder, OutputURIResolver, UnparsedTextURIResolver {
+
+ public static final String MESSAGE = "Configuration error. Resolving ist not allowed";
+
+ @Override
+ public OutputURIResolver newInstance() {
+ return this;
+ }
+
+ @Override
+ public Result resolve(final String href, final String base) throws TransformerException {
+ throw new IllegalStateException(MESSAGE);
+ }
+
+ @Override
+ public void close(final Result result) throws TransformerException {
+ throw new IllegalStateException(MESSAGE);
+ }
+
+ @Override
+ public Reader resolve(final URI absoluteURI, final String encoding, final Configuration config) throws XPathException {
+ throw new IllegalStateException(MESSAGE);
+ }
+
+ @Override
+ public ResourceCollection findCollection(final XPathContext context, final String collectionURI) throws XPathException {
+ throw new IllegalStateException(MESSAGE);
+ }
+ }
+ private static final String ORACLE_XERCES_CLASS = "com.sun.org.apache.xerces.internal.impl.Constants";
+ private static final String DISSALLOW_DOCTYPE_DECL_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
+ private static final String LOAD_EXTERNAL_DTD_FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
+ private static final String FEATURE_SECURE_PROCESSING = "http://javax.xml.XMLConstants/feature/secure-processing";
+ private static Processor processor;
+
+ static {
+ try {
+ Class.forName(ORACLE_XERCES_CLASS);
+ } catch (final ClassNotFoundException e) {
+ log.warn("No oracle JDK version of XERCES found. Configured security features may not have any effect.");
+ log.warn("Please take care of XML security while checking your xml contents");
+ }
+ }
+
+ private ObjectFactory() {
+ // hide, it's a factory
+ }
+
+ private static DocumentBuilderFactory createDocumentBuilderFactory(final boolean validating) {
+ final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ try {
+ dbf.setValidating(validating);
+ dbf.setNamespaceAware(true);
+
+ // explicitly enable secure processing
+ dbf.setFeature(FEATURE_SECURE_PROCESSING, true);
+
+ // This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all XML entity attacks are prevented
+ dbf.setFeature(DISSALLOW_DOCTYPE_DECL_FEATURE, true);
+
+ // Disable external DTDs as well
+ dbf.setFeature(LOAD_EXTERNAL_DTD_FEATURE, false);
+
+ // and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
+ dbf.setXIncludeAware(false);
+ dbf.setExpandEntityReferences(false);
+ return dbf;
+ } catch (final ParserConfigurationException e) {
+ throw new IllegalStateException("Can not create DocumentBuilderFactory due to underlying configuration error", e);
+ }
+
+ }
+
+ /**
+ * Transformer für die Ausgabe. Nutzt nicht Saxon!
+ *
+ * @param prettyPrint pretty-printing der Ausgabe
+ * @return einen vorkonfigurierten Transformer
+ */
+ public static Transformer createTransformer(final boolean prettyPrint) {
+ Transformer transformer = null;
+ try {
+ transformer = TransformerFactory.newInstance().newTransformer();
+ if (prettyPrint) {
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+ }
+ return transformer;
+ } catch (final TransformerConfigurationException e) {
+ throw new IllegalStateException("Can not create Transformer due to underlying configuration error", e);
+ }
+ }
+
+ /**
+ * Erzeugt einen Zeitstempel zur Verwendung in XML-Objekten
+ *
+ * @return eine Instanz {@link XMLGregorianCalendar}
+ */
+ public static XMLGregorianCalendar createTimestamp() {
+ try {
+ final GregorianCalendar cal = new GregorianCalendar();
+ cal.setTime(new Date());
+ return DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
+
+ } catch (final DatatypeConfigurationException e) {
+ throw new IllegalStateException("Can not create timestamp", e);
+ }
+ }
+
+ public static DocumentBuilder createDocumentBuilder(final boolean validating) {
+ try {
+ return createDocumentBuilderFactory(validating).newDocumentBuilder();
+ } catch (final ParserConfigurationException e) {
+ throw new IllegalStateException("Can not create DocumentFactory due to underlying configuration error", e);
+ }
+ }
+
+ private static String encode(final String input) {
+ try {
+ return URLEncoder.encode(input, StandardCharsets.UTF_8.name());
+ } catch (final UnsupportedEncodingException e) {
+ throw new IllegalStateException("Error encoding property while initializing saxon", e);
+ }
+ }
+
+ public static Processor createProcessor() {
+ if (processor == null) {
+ processor = new Processor(false);
+ //verhindere global im Prinzip alle resolving strategien
+ final SecureUriResolver resolver = new SecureUriResolver();
+ processor.getUnderlyingConfiguration().setCollectionFinder(resolver);
+ processor.getUnderlyingConfiguration().setOutputURIResolver(resolver);
+ //hier fehlt eigentlich noch der UriResolver für unparsed text, wird erst ab Saxon 9.8 unterstützt
+
+ //grundsätzlich Feature-konfiguration:
+ processor.setConfigurationProperty(FeatureKeys.DTD_VALIDATION, false);
+ processor.setConfigurationProperty(FeatureKeys.ENTITY_RESOLVER_CLASS, "");
+ processor.setConfigurationProperty(FeatureKeys.XINCLUDE, false);
+ processor.setConfigurationProperty(FeatureKeys.ALLOW_EXTERNAL_FUNCTIONS, false);
+
+ // Konfiguration des zu verwendenden Parsers, wenn Saxon selbst einen erzeugen muss, bspw. beim XSL parsen
+ 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);
+ }
+ return processor;
+ }
+
+ /**
+ * Erzeugt einen Validier für das angegebenen Schema.
+ *
+ * @param schema das Schema mit dem validiert werden soll
+ * @return einen vorkonfigurierten Validator
+ */
+ public static Validator createValidator(final Schema schema) {
+ final Validator validator = schema.newValidator();
+ try {
+ validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+ } catch (final SAXNotRecognizedException | SAXNotSupportedException e) {
+ log.warn("Can not disable external DTD access. Maybe an unsupported JAXP implementation is used.");
+ log.debug(e.getMessage(), e);
+ }
+ try {
+ validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+ } catch (final SAXNotRecognizedException | SAXNotSupportedException e) {
+ log.warn("Can not disable external DTD access. Maybe an unsupported JAXP implementation is used.");
+ log.debug(e.getMessage(), e);
+
+ }
+ return validator;
+ }
+
+ public static SchemaFactory createSchemaFactory() {
+ final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ try {
+ sf.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+ sf.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file");
+ } catch (final SAXException e) {
+ log.warn("Can not disable external DTD access, maybe an unsupported JAXP implementation is used", e);
+ }
+ return sf;
+ }
+}
diff --git a/src/main/java/de/kosit/validationtool/impl/Printer.java b/src/main/java/de/kosit/validationtool/impl/Printer.java
deleted file mode 100644
index cdfbbb4..0000000
--- a/src/main/java/de/kosit/validationtool/impl/Printer.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl;
-
-import java.text.MessageFormat;
-import java.util.Locale;
-
-/**
- * Wrapper for {@link System Systems} printing capability.
- *
- * @author Andreas Penski
- */
-@SuppressWarnings("squid:S106")
-public class Printer {
-
- private Printer() {
- // hide
- }
-
- /**
- * Writes to standard output channel.
- *
- * @param message the message with placeholders
- * @param params the params.
- */
- public static void writeOut(final String message, final Object... params) {
- try {
- System.out.println(new MessageFormat(message, Locale.ENGLISH).format(params));
- } catch (final RuntimeException ex) {
- System.err.println("[Format error!] <" + message + "> with params <" + params + ">");
- }
- }
-
- /**
- * Writes to standard error channel.
- *
- * @param message the message with placeholders
- * @param params the params.
- */
- public static void writeErr(final String message, final Object... params) {
- try {
- System.err.println(new MessageFormat(message, Locale.ENGLISH).format(params));
- } catch (final RuntimeException ex) {
- System.err.println("[Format error!] <" + message + "> with params <" + params + ">");
- }
- }
-
- /**
- * Writes to standard error channel and prints a stacktrace.
- *
- * @param ex the exception
- * @param message the message with placeholders
- * @param params the params
- */
- @SuppressWarnings("squid:S1148")
- public static void writeErr(final Exception ex, final String message, final Object... params) {
- writeErr(message, params);
- if (ex != null) {
- ex.printStackTrace();
- }
- }
-
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/xml/RelativeUriResolver.java b/src/main/java/de/kosit/validationtool/impl/RelativeUriResolver.java
similarity index 52%
rename from src/main/java/de/kosit/validationtool/impl/xml/RelativeUriResolver.java
rename to src/main/java/de/kosit/validationtool/impl/RelativeUriResolver.java
index 132ed7e..e57a05e 100644
--- a/src/main/java/de/kosit/validationtool/impl/xml/RelativeUriResolver.java
+++ b/src/main/java/de/kosit/validationtool/impl/RelativeUriResolver.java
@@ -1,33 +1,37 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
-package de.kosit.validationtool.impl.xml;
+package de.kosit.validationtool.impl;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import javax.xml.transform.Source;
-import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;
+import lombok.AccessLevel;
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;
@@ -37,25 +41,26 @@ import net.sf.saxon.trans.XPathException;
*
* @author Andreas Penski
*/
-@RequiredArgsConstructor()
+@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
public class RelativeUriResolver implements URIResolver, UnparsedTextURIResolver {
/** the base uri */
private final URI baseUri;
@Override
- public Source resolve(final String href, final String base) throws TransformerException {
+ public Source resolve(final String href, final String base) {
final URI resolved = resolve(URI.create(href), URI.create(base));
if (isUnderBaseUri(resolved)) {
try {
return new StreamSource(resolved.toURL().openStream(), resolved.toASCIIString());
} catch (final IOException e) {
- throw new TransformerException(String.format("Can not resolve required %s", href), e);
+ throw new IllegalStateException(String.format("Can not resolve required %s", href), e);
}
+ } else {
+ throw new IllegalStateException(String
+ .format("The resolved transformation artifact %s is not within the configured repository %s", resolved, this.baseUri));
}
- throw new TransformerException(String.format("The resolved transformation artifact %s is not within the configured repository %s",
- resolved, this.baseUri));
}
/**
@@ -77,26 +82,22 @@ public class RelativeUriResolver implements URIResolver, UnparsedTextURIResolver
}
private boolean isUnderBaseUri(final URI resolved) {
- return isUnderBaseUri(resolved, this.baseUri);
- }
-
- private static boolean isUnderBaseUri(final URI resolved, final URI baseUri) {
- if (resolved == null || baseUri == null) {
- return false;
- }
- final String base = baseUri.toASCIIString().replaceAll("file:/+", "");
+ final String base = this.baseUri.toASCIIString().replaceAll("file:/+", "");
final String r = resolved.toASCIIString().replaceAll("file:/+", "");
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);
+ 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));
}
- 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/ResolvingMode.java b/src/main/java/de/kosit/validationtool/impl/ResolvingMode.java
deleted file mode 100644
index 5b9e59c..0000000
--- a/src/main/java/de/kosit/validationtool/impl/ResolvingMode.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-import de.kosit.validationtool.api.ResolvingConfigurationStrategy;
-import de.kosit.validationtool.impl.xml.RemoteResolvingStrategy;
-import de.kosit.validationtool.impl.xml.StrictLocalResolvingStrategy;
-import de.kosit.validationtool.impl.xml.StrictRelativeResolvingStrategy;
-
-/**
- * Defines how artefacts are resolved internally.
- *
- * @author Andreas Penski
- */
-@RequiredArgsConstructor
-public enum ResolvingMode {
-
- /**
- * Resolving using only the configured content repository.
- */
- STRICT_RELATIVE(new StrictRelativeResolvingStrategy()) {
-
- },
-
- STRICT_LOCAL(new StrictLocalResolvingStrategy()),
-
- ALLOW_REMOTE(new RemoteResolvingStrategy()),
-
- CUSTOM(null);
-
- @Getter
- private final ResolvingConfigurationStrategy strategy;
-
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/Scenario.java b/src/main/java/de/kosit/validationtool/impl/Scenario.java
deleted file mode 100644
index d92768a..0000000
--- a/src/main/java/de/kosit/validationtool/impl/Scenario.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-
-import javax.xml.transform.URIResolver;
-import javax.xml.validation.Schema;
-
-import de.kosit.validationtool.api.ResolvingConfigurationStrategy;
-import de.kosit.validationtool.model.scenarios.ResourceType;
-import de.kosit.validationtool.model.scenarios.ScenarioType;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-import net.sf.saxon.lib.UnparsedTextURIResolver;
-import net.sf.saxon.s9api.XPathExecutable;
-import net.sf.saxon.s9api.XPathSelector;
-import net.sf.saxon.s9api.XsltExecutable;
-
-/**
- * @author Andreas Penski
- */
-@RequiredArgsConstructor
-@Setter
-@Getter
-public class Scenario {
-
- /**
- * Runtime objects for a transformation e.g. schematron or report.
- */
- @Getter
- @Setter
- @AllArgsConstructor
- public static class Transformation {
-
- private XsltExecutable executable;
-
- private ResourceType resourceType;
- }
-
- private final ScenarioType configuration;
-
- private Schema schema;
-
- private boolean fallback;
-
- private XPathExecutable matchExecutable;
-
- private XPathExecutable acceptExecutable;
-
- private ResolvingConfigurationStrategy factory;
-
- private URIResolver uriResolver;
-
- private UnparsedTextURIResolver unparsedTextURIResolver;
-
- @Setter
- private List schematronValidations;
-
- private Transformation reportTransformation;
-
- public List getSchematronValidations() {
- // Must return a mutable list
- if (this.schematronValidations == null) {
- this.schematronValidations = new ArrayList<>();
- }
- return this.schematronValidations;
- }
-
- public String getName() {
- return this.configuration.getName();
- }
-
- public XPathSelector getMatchSelector() {
- if (this.matchExecutable == null) {
- throw new IllegalStateException("No match executable supplied");
- }
- return this.matchExecutable.load();
- }
-
- /**
- * Returns a new XPath selector for evaluating the {@link de.kosit.validationtool.api.AcceptRecommendation}.
- *
- * @return new selector
- */
- public Optional getAcceptSelector() {
- final XPathSelector selector = this.acceptExecutable != null ? this.acceptExecutable.load() : null;
- return Optional.ofNullable(selector);
- }
-
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java b/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java
index 267bc23..4903976 100644
--- a/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java
+++ b/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java
@@ -1,31 +1,52 @@
/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package de.kosit.validationtool.impl;
-import java.util.Arrays;
+import static org.apache.commons.lang3.StringUtils.startsWith;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
-import de.kosit.validationtool.api.Configuration;
-import de.kosit.validationtool.impl.model.Result;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
+
+import de.kosit.validationtool.api.CheckConfiguration;
+import de.kosit.validationtool.api.InputFactory;
+import de.kosit.validationtool.impl.model.Result;
+import de.kosit.validationtool.impl.tasks.DocumentParseAction;
+import de.kosit.validationtool.model.reportInput.XMLSyntaxError;
+import de.kosit.validationtool.model.scenarios.CreateReportType;
+import de.kosit.validationtool.model.scenarios.ScenarioType;
+import de.kosit.validationtool.model.scenarios.Scenarios;
+
+import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XPathSelector;
import net.sf.saxon.s9api.XdmNode;
+import net.sf.saxon.s9api.XdmNodeKind;
/**
* Repository for die aktiven Szenario einer Prüfinstanz.
@@ -33,64 +54,129 @@ import net.sf.saxon.s9api.XdmNode;
* @author Andreas Penski
*/
@Slf4j
-
+@RequiredArgsConstructor
public class ScenarioRepository {
- public static final String DEFAULT = "default";
+ private static final String SUPPORTED_MAJOR_VERSION = "1";
- public static final String DEFAULT_ID = DEFAULT + "_1";
+ private static final String SUPPORTED_MAJOR_VERSION_SCHEMA = "http://www.xoev.de/de/validator/framework/1/scenarios";
- private final List configuration;
- public ScenarioRepository(final Configuration... configuration) {
- if (configuration.length == 0) {
- throw new IllegalArgumentException("Must provide at least one configuration");
- }
- this.configuration = Arrays.asList(configuration);
- this.configuration.forEach(v -> log.info("Loaded scenarios for {} by {} from {}.", v.getName(), v.getAuthor(), v.getDate()));
- log.info("The following scenarios are available:\n{}", summarizeScenarios());
+ @Getter(value = AccessLevel.PACKAGE)
+ private final ContentRepository repository;
+
+ @Getter
+ private Scenarios scenarios;
+
+ @Setter(AccessLevel.PACKAGE)
+ @Getter
+ private ScenarioType fallbackScenario;
+
+ private static boolean isSupportedDocument(final XdmNode doc) {
+ final XdmNode root = findRoot(doc);
+ final String frameworkVersion = root.getAttributeValue(new QName("frameworkVersion"));
+ return startsWith(frameworkVersion, SUPPORTED_MAJOR_VERSION)
+ && root.getNodeName().getNamespaceURI().equals(SUPPORTED_MAJOR_VERSION_SCHEMA);
}
- public Scenario getFallbackScenario() {
- if (this.configuration.size() > 1) {
- log.warn("Multiple configurations found. Using fallback scenario from first configuration");
+ private static XdmNode findRoot(final XdmNode doc) {
+ for (final XdmNode node : doc.children()) {
+ if (node.getNodeKind() == XdmNodeKind.ELEMENT) {
+ return node;
+ }
}
- return this.configuration.get(0).getFallbackScenario();
+ throw new IllegalArgumentException("Kein root element gefunden");
}
- public List getScenarios() {
- return this.configuration.stream().flatMap(c -> c.getScenarios().stream()).collect(Collectors.toList());
+ private static void checkVersion(final URI scenarioDefinition) {
+ final DocumentParseAction p = new DocumentParseAction();
+ try {
+ final Result result = DocumentParseAction.parseDocument(InputFactory.read(scenarioDefinition.toURL()));
+ if (result.isValid() && !isSupportedDocument(result.getObject())) {
+ throw new IllegalStateException(String.format(
+ "Specified scenario configuration %s is not supported.%nThis version only supports definitions of '%s'",
+ scenarioDefinition, SUPPORTED_MAJOR_VERSION_SCHEMA));
+
+ }
+ } catch (final MalformedURLException e) {
+ throw new IllegalStateException("Error reading definition file");
+ }
+ }
+
+
+
+ /**
+ * Initialisiert das Repository mit der angegebenen Konfiguration.
+ *
+ * @param config die Konfiguration
+ */
+ public void initialize(final CheckConfiguration config) {
+ final ConversionService conversionService = new ConversionService();
+ checkVersion(config.getScenarioDefinition());
+ log.info("Loading scenarios from {}", config.getScenarioDefinition());
+ final CollectingErrorEventHandler handler = new CollectingErrorEventHandler();
+ this.scenarios = conversionService.readXml(config.getScenarioDefinition(), Scenarios.class, ContentRepository.getScenarioSchema(),
+ handler);
+ if (!handler.hasErrors()) {
+ log.info("Loaded scenarios for {} by {} from {}. The following scenarios are available:\n\n{}", this.scenarios.getName(),
+ this.scenarios.getAuthor(), this.scenarios.getDate(), summarizeScenarios());
+ log.info("Loading scenario content from {}", config.getScenarioRepository());
+ getScenarios().getScenario().forEach(s -> s.initialize(this.repository, false));
+ } else {
+ throw new IllegalStateException(String.format("Can not load scenarios from %s due to %s", config.getScenarioDefinition(),
+ handler.getErrorDescription()));
+ }
+ // initialize fallback report eager
+ this.fallbackScenario = createFallback();
+
}
private String summarizeScenarios() {
final StringBuilder b = new StringBuilder();
- getScenarios().forEach(s -> b.append(s.getName()).append('\n'));
+ this.scenarios.getScenario().forEach(s -> {
+ b.append(s.getName());
+ b.append("\n");
+ });
return b.toString();
}
/**
- * Determine the matching Scenario for the provided input document
+ * Ermittelt für das gegebene Dokument das passende Szenario.
*
- * @param document input document
+ * @param document das Eingabedokument
* @return ein Ergebnis-Objekt zur weiteren Verarbeitung
*/
- public Result selectScenario(final XdmNode document) {
- final Result result;
- final List collect = getScenarios().stream().filter(s -> match(document, s)).collect(Collectors.toList());
+ public Result selectScenario(final XdmNode document) {
+ final Result result;
+ final List collect = this.scenarios.getScenario().stream().filter(s -> match(document, s))
+ .collect(Collectors.toList());
if (collect.size() == 1) {
result = new Result<>(collect.get(0));
} else if (collect.isEmpty()) {
- result = new Result<>(getFallbackScenario(), Arrays.asList("None of the loaded scenarios matches the specified document"));
+ result = new Result<>(getFallbackScenario(),
+ Collections.singleton("None of the loaded scenarios matches the specified document"));
} else {
- result = new Result<>(getFallbackScenario(), Arrays.asList("More than one scenario matches the specified document"));
+ result = new Result<>(getFallbackScenario(), Collections.singleton("More than on scenario matches the specified document"));
}
return result;
}
- private static boolean match(final XdmNode document, final Scenario scenario) {
+ private ScenarioType createFallback() {
+ final ScenarioType t = new ScenarioType();
+ t.setName("Fallback-Scenario");
+ final CreateReportType reportType = new CreateReportType();
+ reportType.setResource(this.scenarios.getNoScenarioReport().getResource());
+ t.initialize(this.repository, true);
+ // always reject
+ t.setAcceptMatch("count(/)<0");
+ t.setCreateReport(reportType);
+ return t;
+ }
+
+ private static boolean match(final XdmNode document, final ScenarioType scenario) {
try {
- final XPathSelector selector = scenario.getMatchSelector();
+ final XPathSelector selector = scenario.getSelector();
selector.setContextItem(document);
return selector.effectiveBooleanValue();
} catch (final SaxonApiException e) {
@@ -99,4 +185,7 @@ public class ScenarioRepository {
return false;
}
+ void initialize(final Scenarios def) {
+ this.scenarios = def;
+ }
}
diff --git a/src/main/java/de/kosit/validationtool/impl/SchemaProvider.java b/src/main/java/de/kosit/validationtool/impl/SchemaProvider.java
deleted file mode 100644
index 4798bff..0000000
--- a/src/main/java/de/kosit/validationtool/impl/SchemaProvider.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-
-import org.w3c.dom.ls.LSResourceResolver;
-import org.xml.sax.SAXException;
-
-import de.kosit.validationtool.impl.xml.ClassPathResourceResolver;
-
-/**
- * @author Andreas Penski
- */
-public class SchemaProvider {
-
- private static Schema reportInputSchema;
-
- /**
- * Liefert das definierte Schema für die Validierung des [@link CreateReportInput}
- *
- * @return ReportInput-Schema
- */
- public static Schema getReportInputSchema() {
- if (reportInputSchema == null) {
- final SchemaFactory sf = ResolvingMode.STRICT_RELATIVE.getStrategy().createSchemaFactory();
- final Source source = resolve(SchemaProvider.class.getResource("/xsd/createReportInput.xsd"));
- reportInputSchema = createSchema(sf, new Source[] { source }, new ClassPathResourceResolver("/xsd"));
- }
- return reportInputSchema;
- }
-
- private static Schema createSchema(final SchemaFactory sf, final Source[] schemaSources, final LSResourceResolver resourceResolver) {
- try {
- sf.setResourceResolver(resourceResolver);
- return sf.newSchema(schemaSources);
- } catch (final SAXException e) {
- throw new IllegalArgumentException("Can not load schema from sources " + schemaSources[0].getSystemId(), e);
- }
- }
-
- private static Schema createSchema(final SchemaFactory sf, final Source... schemaSources) {
- return createSchema(sf, schemaSources, null);
- }
-
- @SuppressWarnings("java:S2095") // xml stack requires not closing the resource here
- private static Source resolve(final URL resource) {
- try {
- final String rawPath = resource.toURI().getRawPath();
- return new StreamSource(resource.openStream(), rawPath);
- } catch (final IOException | URISyntaxException e) {
- throw new IllegalStateException("Can not load schema for resource " + resource.getPath(), e);
- }
- }
-
- /**
- * Liefert das definiert Schema für die Szenario-Konfiguration
- *
- * @return Scenario-Schema
- */
- public static Schema getScenarioSchema() {
- final SchemaFactory sf = ResolvingMode.STRICT_RELATIVE.getStrategy().createSchemaFactory();
- return createSchema(sf, resolve(SchemaProvider.class.getResource("/xsd/scenarios.xsd")));
- }
-
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/input/AbstractInput.java b/src/main/java/de/kosit/validationtool/impl/input/AbstractInput.java
deleted file mode 100644
index 17c2bdf..0000000
--- a/src/main/java/de/kosit/validationtool/impl/input/AbstractInput.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl.input;
-
-import static de.kosit.validationtool.impl.input.StreamHelper.drain;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import lombok.Getter;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-
-import de.kosit.validationtool.api.Input;
-
-/**
- * Base class for all {@link Input Inputs}.
- *
- * @author Andreas Penski
- */
-@Slf4j
-public abstract class AbstractInput implements Input, LazyReadInput {
-
- private byte[] hashCode;
-
- @Getter
- @Setter
- private long length;
-
- @Override
- public byte[] getHashCode() {
- if (this.hashCode == null) {
- log.warn("Extra calculating hashcode. This is in-efficient in most cases");
- computeHashcode();
- }
- return this.hashCode;
- }
-
- protected void computeHashcode() {
- try {
- drain(this);
- } catch (final IOException e) {
- log.error("Error extra computing hashcode", e);
- }
- }
-
- protected InputStream wrap(final InputStream stream) {
- InputStream result = stream;
- if (!isHashcodeComputed()) {
- result = StreamHelper.wrapDigesting(this, result, getDigestAlgorithm());
- }
- if (getLength() == 0) {
- result = StreamHelper.wrapCount(this, result);
- }
- return result;
- }
-
- @Override
- public boolean isHashcodeComputed() {
- return this.hashCode != null;
- }
-
- @Override
- public void setHashCode(final byte[] digest) {
- this.hashCode = digest;
- }
-
- public boolean supportsMultipleReads() {
- return true;
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/input/ByteArrayInput.java b/src/main/java/de/kosit/validationtool/impl/input/ByteArrayInput.java
deleted file mode 100644
index e741cec..0000000
--- a/src/main/java/de/kosit/validationtool/impl/input/ByteArrayInput.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl.input;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * Classical in-memory {@link de.kosit.validationtool.api.Input}. It is not memory efficient to read the whole file into
- * memory prio validating. Consider using the {@link ResourceInput}.
- *
- * @author Andreas Penski
- */
-@Getter
-@AllArgsConstructor
-public class ByteArrayInput extends AbstractInput {
-
- private final byte[] content;
-
- private final String name;
-
- private final String digestAlgorithm;
-
- @Override
- public long getLength() {
- return this.content != null ? this.content.length : 0;
- }
-
- @Override
- public Source getSource() {
- final InputStream stream = wrap(new ByteArrayInputStream(this.content));
- return new StreamSource(stream, getName());
- }
-
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/input/LazyReadInput.java b/src/main/java/de/kosit/validationtool/impl/input/LazyReadInput.java
deleted file mode 100644
index 6ab098f..0000000
--- a/src/main/java/de/kosit/validationtool/impl/input/LazyReadInput.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl.input;
-
-import java.io.InputStream;
-
-import de.kosit.validationtool.api.Input;
-
-/**
- * Internal interface used for lazy generation of the hashcode for document identification.
- *
- * @see StreamHelper#wrapDigesting(LazyReadInput, InputStream, String) for details
- * @author Andreas Penski
- */
-interface LazyReadInput {
-
- /**
- * Sets a hashcode
- *
- * @param digest the digest
- */
- void setHashCode(byte[] digest);
-
- /**
- * Determines whether a hashcode has been computed yet
- *
- * @return true when computed
- */
- boolean isHashcodeComputed();
-
- /**
- * Setting the length of the {@link Input}.
- *
- * @param length the length
- */
- void setLength(long length);
-
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/input/ResourceInput.java b/src/main/java/de/kosit/validationtool/impl/input/ResourceInput.java
deleted file mode 100644
index 234d7a9..0000000
--- a/src/main/java/de/kosit/validationtool/impl/input/ResourceInput.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl.input;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-import de.kosit.validationtool.api.Input;
-
-/**
- * An {@link Input} carries an {@link URL} which can be used for all 'locatable' inputs such as {@link File},
- * {@link java.nio.file.Path} and any other {@link URL}.
- *
- * This stream is NOT read into memory. So this implementation has good in memory efficieny. The validation process MAY
- * read the stream more than once. Make sure, that the {@link URL} points to fast I/O devices
- *
- * @author Andreas Penski
- */
-@Getter
-@RequiredArgsConstructor
-public class ResourceInput extends AbstractInput {
-
- private final URL url;
-
- private final String name;
-
- private final String digestAlgorithm;
-
- @Override
- public Source getSource() throws IOException {
- InputStream stream = this.url.openStream();
- if (!isHashcodeComputed()) {
- stream = StreamHelper.wrapDigesting(this, stream, getDigestAlgorithm());
- }
- return new StreamSource(stream, this.name);
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java b/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java
deleted file mode 100644
index 60c926e..0000000
--- a/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl.input;
-
-import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
-
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.charset.Charset;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamSource;
-
-import org.apache.commons.io.input.ReaderInputStream;
-
-import jakarta.xml.bind.util.JAXBSource;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-import net.sf.saxon.om.TreeInfo;
-
-/**
- * A validator {@link de.kosit.validationtool.api.Input} based on a {@link Source}.
- *
- * Note: The various implementations of {@link Source} varies wether the can be read twice or no. This implementation
- * tries to handle this with respect document identification (hashcode).
- *
- * This class is known to work with:
- *
- * - {@link StreamSource} - both {@link java.io.InputStream} based and {@link java.io.Reader} based
- * - {@link javax.xml.transform.dom.DOMSource}
- * - {@link jakarta.xml.bind.util.JAXBSource}
- * - {@link TreeInfo}
- *
- *
- * Other {@link Source Sources} may work as well, please try and let us know.
- *
- * @author Andreas Penski
- */
-@Getter
-@Slf4j
-public class SourceInput extends AbstractInput {
-
- private final Source source;
-
- private final String name;
-
- private final String digestAlgorithm;
-
- public SourceInput(final StreamSource source, final String name, final String digestAlgorithm) {
- this(source, name, digestAlgorithm, null);
- }
-
- public SourceInput(final Source source, final String name, final String digestAlgorithm, final byte[] hashCode) {
- this.source = source;
- this.name = name;
- this.digestAlgorithm = digestAlgorithm;
- setHashCode(hashCode);
- validate();
- }
-
- @Override
- public String getName() {
- return defaultIfBlank(this.name, this.source.getClass().getSimpleName());
- }
-
- private void validate() {
- if (!isHashcodeComputed() && !isHashcodeComputationSupported()) {
- throw new IllegalStateException("Unsupported source. Only StreamSource supported yet");
- }
- if (!isHashcodeComputed() && ((StreamSource) this.source).getInputStream() == null) {
- log.warn("No hashcode supplied, will wrap the reader using system default charset");
- }
- if (!(isTreeInfo() || isDomSource() || isStreamSource() || isJaxbSource())) {
- log.warn("No known to be working Source implementation provided.");
- }
- }
-
- @Override
- public Source getSource() throws IOException {
- if (isConsumed()) {
- throw new IllegalStateException("A SourceInput can only read once");
- }
- return isHashcodeComputed() ? this.source : wrappedSource();
- }
-
- private boolean isHashcodeComputationSupported() {
- return isStreamSource();
- }
-
- private boolean isConsumed() {
- if (isStreamSource()) {
-
- final StreamSource ss = (StreamSource) this.source;
- try {
- return (ss.getInputStream() != null && ss.getInputStream().available() == 0)
- || (ss.getReader() != null && !ss.getReader().ready());
- } catch (final IOException e) {
- log.error("Error checking consumed state", e);
- return true;
- }
- }
- return false;
- }
-
- private boolean isStreamSource() {
- return this.source instanceof StreamSource;
- }
-
- private boolean isDomSource() {
- return this.source instanceof DOMSource;
- }
-
- public boolean isTreeInfo() {
- return this.source instanceof TreeInfo;
- }
-
- private boolean isJaxbSource() {
- return this.source instanceof JAXBSource;
- }
-
- private Source wrappedSource() {
- Source result = this.source;
- if (isStreamSource()) {
- final StreamSource ss = (StreamSource) this.source;
- if (ss.getInputStream() != null) {
- result = new StreamSource(wrap(ss.getInputStream()), this.source.getSystemId());
- } else if (ss.getReader() != null) {
- try {
- result = new StreamSource(
- wrap(ReaderInputStream.builder().setReader(ss.getReader()).setCharset(Charset.defaultCharset()).get()),
- this.source.getSystemId());
- } catch (final IOException ex) {
- throw new UncheckedIOException(ex);
- }
- }
- }
- return result;
- }
-
- @Override
- public boolean supportsMultipleReads() {
- return isDomSource() || isTreeInfo();
- }
-
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java b/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java
deleted file mode 100644
index cefd0e3..0000000
--- a/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl.input;
-
-import java.io.BufferedInputStream;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.security.DigestInputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import javax.xml.transform.stream.StreamSource;
-
-import org.apache.commons.io.input.BoundedInputStream;
-
-import de.kosit.validationtool.api.Input;
-
-/**
- * Helper for stream handling.
- *
- * @author Andreas Penski
- */
-public class StreamHelper {
-
- /**
- * Helper class, which generates the hashcode while reading the stream e.g. for parsing the document. This allows
- * generating the hashcode without an additional reading step.
- */
- @SuppressWarnings("squid:S4929") // efficient read is done by internally used stream
- private static class DigestingInputStream extends FilterInputStream {
-
- private final MessageDigest digest;
-
- private final LazyReadInput reference;
-
- DigestingInputStream(final LazyReadInput input, final InputStream in, final MessageDigest digest) {
- super(new DigestInputStream(in, digest));
- this.digest = digest;
- this.reference = input;
- }
-
- @Override
- public void close() throws IOException {
- super.close();
- this.reference.setHashCode(this.digest.digest());
- }
-
- }
-
- private static class PeekableInputStream extends BufferedInputStream {
-
- public PeekableInputStream(final InputStream in) {
- super(in);
- }
-
- @Override
- public synchronized int available() throws IOException {
- int count = super.available();
- if (count == 0) {
- count = peek();
- }
- return count;
- }
-
- @SuppressWarnings("ResultOfMethodCallIgnored")
- private int peek() throws IOException {
- try {
- mark(2);
- read();
- read();
- reset();
- } catch (final IOException e) {
- return 0;
- }
- return super.available();
- }
- }
-
- @SuppressWarnings("squid:S4929") // efficient read is done by internally used stream
- private static class CountInputStream extends FilterInputStream {
-
- private final LazyReadInput reference;
-
- public CountInputStream(final LazyReadInput input, final InputStream stream) throws IOException {
- super(BoundedInputStream.builder().setInputStream(stream).get());
- this.reference = input;
- }
-
- @Override
- public void close() throws IOException {
- super.close();
- this.reference.setLength(((BoundedInputStream) this.in).getCount());
- }
- }
-
- private static final int EOF = -1;
-
- private static final int DEFAULT_BUFFER_SIZE = 4096;
-
- private StreamHelper() {
- // hide
- }
-
- public static MessageDigest createDigest(final String algorithm) {
- try {
- final MessageDigest digest;
- digest = MessageDigest.getInstance(algorithm);
- return digest;
- } catch (final NoSuchAlgorithmException e) {
- // should not happen
- throw new IllegalArgumentException(String.format("Specified method %s is not available", algorithm), e);
- }
- }
-
- /**
- * Wraps the {@link InputStream} with a counting length implementation.
- *
- * @param input the lazy read input
- * @param stream the stream
- * @return a wrapped stream
- */
- public static InputStream wrapCount(final LazyReadInput input, final InputStream stream) {
- try {
- return new CountInputStream(input, stream);
- } catch (final IOException ex) {
- throw new UncheckedIOException(ex);
- }
- }
-
- /**
- * Wraps the {@link InputStream} with an implementation the generates a hash sum over the stream data.
- *
- * @param input the lazy read input
- * @param stream the stream
- * @param digestAlgorithm the message digest algorithm to use
- * @return a wrapped stream
- */
- public static InputStream wrapDigesting(final LazyReadInput input, final InputStream stream, final String digestAlgorithm) {
- return new DigestingInputStream(input, stream, createDigest(digestAlgorithm));
- }
-
- public static BufferedInputStream wrapPeekable(final InputStream stream) {
- return new PeekableInputStream(stream);
- }
-
- /**
- * Drains the {@link Input} without further processing. This is useful to computing hashcode etc.
- *
- * @param input the input
- * @return the input drained once
- * @throws IOException on I/O errors
- */
- public static Input drain(final Input input) throws IOException {
- final StreamSource s = (StreamSource) input.getSource();
- try ( final InputStream stream = s.getInputStream() ) {
- drain(stream);
- }
- return input;
-
- }
-
- /**
- * Drains the {@link InputStream} without further processing. This is useful to computing hashcode etc.
- *
- * @param input the input
- * @throws IOException on I/O errors
- */
- @SuppressWarnings({ "squid:S1854", "unused" })
- public static void drain(final InputStream input) throws IOException {
- final byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
-
- // noinspection unused
- int n;
-
- // noinspection StatementWithEmptyBody,UnusedAssignment
- while (EOF != (n = input.read(buffer))) {
- // nothing
- }
-
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/input/XdmNodeInput.java b/src/main/java/de/kosit/validationtool/impl/input/XdmNodeInput.java
deleted file mode 100644
index e3b9471..0000000
--- a/src/main/java/de/kosit/validationtool/impl/input/XdmNodeInput.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kosit.validationtool.impl.input;
-
-import javax.xml.transform.Source;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-import de.kosit.validationtool.api.Input;
-
-import net.sf.saxon.s9api.XdmNode;
-
-/**
- * An {@link Input} implementation holding saxon's {@link XdmNode} object.
- *
- * @author Andreas Penski
- */
-@RequiredArgsConstructor
-@Getter
-public class XdmNodeInput implements Input {
-
- private final XdmNode node;
-
- private final String name;
-
- private final String digestAlgorithm;
-
- private final byte[] hashCode;
-
- @Override
- public Source getSource() {
- // usually not neccessary to be called.
- return this.node.getUnderlyingNode();
- }
-}
diff --git a/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java b/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java
index 8e3c07c..b6a670b 100644
--- a/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java
+++ b/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java
@@ -1,19 +1,3 @@
-/*
- * Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package de.kosit.validationtool.impl.model;
import java.io.Serializable;
@@ -59,7 +43,7 @@ public abstract class BaseOutput {
* @return true wenn mindestens ein {@link FailedAssert} vorhanden ist
*/
public boolean hasFailedAsserts() {
- return !getFailedAsserts().isEmpty();
+ return getFailedAsserts().size() > 0;
}
/**
@@ -85,8 +69,4 @@ public abstract class BaseOutput {
return getFailedAsserts().stream().filter(e -> e.getId().equals(name)).findAny();
}
- public List getMessages() {
- return getFailedAsserts().stream().map(FailedAssert::getText).flatMap(e -> e.getContent().stream()).map(Object::toString)
- .collect(Collectors.toList());
- }
}
diff --git a/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java b/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java
new file mode 100644
index 0000000..b983c61
--- /dev/null
+++ b/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
+ * one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. KoSIT licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package de.kosit.validationtool.impl.model;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.xml.validation.Schema;
+
+import org.apache.commons.lang3.NotImplementedException;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import de.kosit.validationtool.impl.ContentRepository;
+import de.kosit.validationtool.impl.ScenarioRepository;
+import de.kosit.validationtool.model.scenarios.CreateReportType;
+import de.kosit.validationtool.model.scenarios.NamespaceType;
+import de.kosit.validationtool.model.scenarios.ResourceType;
+import de.kosit.validationtool.model.scenarios.ValidateWithSchematron;
+import de.kosit.validationtool.model.scenarios.ValidateWithXmlSchema;
+
+import net.sf.saxon.s9api.XPathExecutable;
+import net.sf.saxon.s9api.XPathSelector;
+import net.sf.saxon.s9api.XsltExecutable;
+
+/**
+ * Eine Basis-Klasse für Szenarien. Wiederverwendbare Objekte mit Bezug zum Szenario werden hier gecached. Die Klasse
+ * stellt im eigentlichen Sinne eine Erweiterung der durch JAXB generierten Strukturen dar.
+ *
+ * @author Andreas Penski
+ */
+public abstract class BaseScenario {
+
+ /**
+ * Laufzeitinformationen über eine Transformation.
+ */
+ @Getter
+ @Setter
+ @AllArgsConstructor
+ public static class Transformation {
+
+ private XsltExecutable executable;
+
+ private ResourceType resourceType;
+ }
+
+ private XPathExecutable matchExecutable;
+
+ private XPathExecutable acceptExecutable;
+
+ private Schema schema;
+
+ private List schematronValidations;
+
+ private ContentRepository repository;
+
+ private Transformation reportTransformation;
+
+ /**
+ * Gibt eine Transformation zurück.
+ *
+ * @return initialisierte Transformation
+ */
+ public Transformation getReportTransformation() {
+ if (this.reportTransformation == null) {
+ final ResourceType resource = getCreateReport().getResource();
+ final XsltExecutable executable = this.repository.loadXsltScript(URI.create(resource.getLocation()));
+ this.reportTransformation = new Transformation(executable, resource);
+ }
+ return this.reportTransformation;
+ }
+
+ /**
+ * Lieferrt das Schema zu diesem Szenario.
+ *
+ * @return das passende Schema
+ */
+ public Schema getSchema() {
+ if (this.schema == null && getValidateWithXmlSchema() != null) {
+ final List | | | |