From 8224690b6a76273b9f7d3ae71784a15d2739e507 Mon Sep 17 00:00:00 2001 From: "Andreas Penski (init)" Date: Mon, 6 Jan 2020 12:09:17 +0100 Subject: [PATCH] #40 Fix NPE in Result.getReportDocument for malformed xml input Compute correct Hashcode, when Input is malformed --- .../impl/input/AbstractInput.java | 14 ++++++- .../impl/input/SourceInput.java | 2 +- .../impl/input/StreamHelper.java | 40 +++++++++++++++++++ .../validationtool/api/InputFactoryTest.java | 16 +------- 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/main/java/de/kosit/validationtool/impl/input/AbstractInput.java b/src/main/java/de/kosit/validationtool/impl/input/AbstractInput.java index e4e4a8f..c5c30aa 100644 --- a/src/main/java/de/kosit/validationtool/impl/input/AbstractInput.java +++ b/src/main/java/de/kosit/validationtool/impl/input/AbstractInput.java @@ -1,5 +1,8 @@ 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; @@ -25,11 +28,20 @@ public abstract class AbstractInput implements Input, LazyReadInput { @Override public byte[] getHashCode() { if (this.hashCode == null) { - throw new IllegalStateException("Hashcode is not computed yet"); + 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()) { diff --git a/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java b/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java index ba27f90..8cc4a3d 100644 --- a/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java +++ b/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java @@ -57,7 +57,7 @@ public class SourceInput extends AbstractInput { return wrap(); } if (isConsumed()) { - throw new IllegalStateException("A StreamSource can only read once"); + throw new IllegalStateException("A SourceInput can only read once"); } return this.source; } diff --git a/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java b/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java index d364384..bd8de8a 100644 --- a/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java +++ b/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java @@ -7,8 +7,12 @@ import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import javax.xml.transform.stream.StreamSource; + import org.apache.commons.io.input.CountingInputStream; +import de.kosit.validationtool.api.Input; + /** * Helper for stream handling. * @@ -56,6 +60,10 @@ public class StreamHelper { } } + private static final int EOF = -1; + + private static final int DEFAULT_BUFFER_SIZE = 4096; + private StreamHelper() { // hide } @@ -92,4 +100,36 @@ public class StreamHelper { public static InputStream wrapDigesting(final LazyReadInput input, final InputStream stream, final String digestAlgorithm) { return new DigestingInputStream(input, stream, createDigest(digestAlgorithm)); } + + /** + * 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 + */ + public static void drain(final InputStream input) throws IOException { + final byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + + int n; + while (EOF != (n = input.read(buffer))) { + // nothing + } + + } } diff --git a/src/test/java/de/kosit/validationtool/api/InputFactoryTest.java b/src/test/java/de/kosit/validationtool/api/InputFactoryTest.java index 72d5990..3e5474f 100644 --- a/src/test/java/de/kosit/validationtool/api/InputFactoryTest.java +++ b/src/test/java/de/kosit/validationtool/api/InputFactoryTest.java @@ -19,6 +19,7 @@ package de.kosit.validationtool.api; +import static de.kosit.validationtool.impl.input.StreamHelper.drain; import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayInputStream; @@ -51,9 +52,7 @@ public class InputFactoryTest { private static URL NOT_EXISTING; - private static final int EOF = -1; - private static final int DEFAULT_BUFFER_SIZE = 4096; static { try { @@ -83,20 +82,7 @@ public class InputFactoryTest { assertThat(s1).isNotEqualTo(s3); } - private static Input drain(final Input input) throws IOException { - final byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; - final StreamSource s = (StreamSource) input.getSource(); - try ( final InputStream stream = s.getInputStream() ) { - int n; - while (EOF != (n = stream.read(buffer))) { - // nothing - } - - } - return input; - - } @Test public void testWrongAlgorithm() {