diff --git a/api/src/main/java/org/jmisb/api/common/KlvParseException.java b/api/src/main/java/org/jmisb/api/common/KlvParseException.java
index b27b9da2c..3b05de492 100644
--- a/api/src/main/java/org/jmisb/api/common/KlvParseException.java
+++ b/api/src/main/java/org/jmisb/api/common/KlvParseException.java
@@ -1,7 +1,11 @@
package org.jmisb.api.common;
+import java.util.Arrays;
+
/** Indicates an error occurred during metadata parsing. */
public class KlvParseException extends Exception {
+ private final byte[] buffer;
+
/**
* Constructor.
*
@@ -10,5 +14,22 @@ public class KlvParseException extends Exception {
*/
public KlvParseException(String message) {
super(message);
+ this.buffer = null;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param exception the inner exception object
+ * @param buffer the buffer corresponding to the inner exception
+ */
+ public KlvParseException(KlvParseException exception, byte[] buffer) {
+ super(exception);
+ this.buffer = Arrays.copyOf(buffer, buffer.length);
+ }
+
+ /** @return a copy of the {@code byte[]} corresponding to the wrapped exception. */
+ public byte[] getBuffer() {
+ return Arrays.copyOf(buffer, buffer.length);
}
}
diff --git a/api/src/main/java/org/jmisb/api/klv/BerDecoder.java b/api/src/main/java/org/jmisb/api/klv/BerDecoder.java
index a6922dd81..de38a72d5 100644
--- a/api/src/main/java/org/jmisb/api/klv/BerDecoder.java
+++ b/api/src/main/java/org/jmisb/api/klv/BerDecoder.java
@@ -1,7 +1,11 @@
package org.jmisb.api.klv;
+import java.io.IOException;
+import java.io.InputStream;
+
/** Decode data using Basic Encoding Rules (BER). */
public class BerDecoder {
+
private BerDecoder() {}
/**
@@ -10,7 +14,7 @@ private BerDecoder() {}
* @param data Array holding the BER-encoded data
* @param offset Index of the first byte of the array to decode
* @param isOid true if the data is encoded using BER-OID
- * @return decoded The decoded field
+ * @return the decoded field
* @throws IllegalArgumentException if the encoded data is invalid
*/
public static BerField decode(byte[] data, int offset, boolean isOid)
@@ -42,7 +46,7 @@ public static BerField decode(byte[] data, int offset, boolean isOid)
if (berLength > 4) {
throw new IllegalArgumentException(
- "BER long form: BER length is >5 bytes; data is probably corrupt");
+ "BER long form: BER length is >4 bytes; data is probably corrupt");
}
int val = 0;
for (int i = 0; i < berLength; ++i) {
@@ -77,4 +81,62 @@ public static BerField decode(byte[] data, int offset, boolean isOid)
return new BerField(length, value);
}
+
+ /**
+ * Decode a field (length and value) from an InputStream.
+ *
+ * @param is InputStream with BER-encoded data at the tip
+ * @param isOid true if the data is encoded using BER-OID
+ * @return the decoded field
+ * @throws IllegalArgumentException if the encoded data is invalid
+ */
+ public static BerField decode(InputStream is, boolean isOid) throws IOException {
+ if (!isOid) {
+ return decodeBer(is);
+ }
+
+ return decodeBerOid(is);
+ }
+
+ private static BerField decodeBer(InputStream is) throws IOException {
+ int length = is.read();
+
+ if ((length & 0x80) == 0) {
+ // BER Short Form. If the first bit of the BER is 0 then the BER is 1-byte.
+ return new BerField(1, length);
+ }
+
+ // BER Long Form (variable length)
+ int berLength = length & 0x7f;
+ if (berLength > 4) {
+ throw new IllegalArgumentException(
+ "BER long form: BER length is >4 bytes; data is probably corrupt");
+ }
+ int fullBerSize = berLength + 1;
+ byte[] data = new byte[berLength];
+ int read = is.read(data, 0, data.length);
+ if (read != data.length) {
+ throw new IllegalArgumentException("BER parsing ran out of bytes");
+ }
+ int len = 0;
+ for (int i = 0; i < berLength; ++i) {
+ int b = 0x00FF & data[i];
+ len = (len << 8) | b;
+ }
+ return new BerField(fullBerSize, len);
+ }
+
+ private static BerField decodeBerOid(InputStream is) throws IOException {
+ int read;
+ int value = 0;
+ int length = 0;
+ do {
+ read = is.read();
+ int highbits = (value << 7);
+ int lowbits = (read & 0x7F);
+ value = highbits + lowbits;
+ length++;
+ } while ((read & 0x80) == 0x80);
+ return new BerField(length, value);
+ }
}
diff --git a/api/src/main/java/org/jmisb/api/klv/KlvParser.java b/api/src/main/java/org/jmisb/api/klv/KlvParser.java
index a90a11d2a..3b7598d23 100644
--- a/api/src/main/java/org/jmisb/api/klv/KlvParser.java
+++ b/api/src/main/java/org/jmisb/api/klv/KlvParser.java
@@ -1,8 +1,12 @@
package org.jmisb.api.klv;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.function.Consumer;
import org.jmisb.api.common.KlvParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -13,6 +17,84 @@ public class KlvParser {
private KlvParser() {}
+ /**
+ * Parse an InputStream containing one or more {@link IMisbMessage}s.
+ *
+ *
This differs from {@link #parseBytes(byte[]) parseBytes(byte[])} by parsing the
+ * UniversalLabel, BER-length, and value, and sending the {@link IMisbMessage} object in
+ * realtime to {@code handler}.
+ *
+ *
This is an additional interface for parsing KLV metadata. It assumes that {@code is}
+ * contains one or more top-level messages, i.e., byte sequences starting with a Universal Label
+ * (UL). If a particular UL is unsupported it will be send to {@code handler} as a {@link
+ * RawMisbMessage}.
+ *
+ *
If parsing errors occur with a valid length message, with an invalid value, the
+ * corresponding {@code byte[]} and {@link KlvParseException} will be sent to {@code
+ * exceptionHandler}.
+ *
+ *
The supported UL are determined by the {@link MisbMessageFactory} singleton.
+ *
+ * @param is The input stream
+ * @param handler The resultant {@link IMisbMessage} objects streamed
+ * @param exceptionHandler The {@link KlvParseException} errors detected in the stream.
+ * @throws KlvParseException if an unrecoverable parsing exception occurs when splitting
+ * messages
+ */
+ public static void parseStream(
+ InputStream is,
+ Consumer handler,
+ Consumer exceptionHandler)
+ throws KlvParseException {
+
+ // reusable key array to minimize garbage
+ byte[] key = new byte[UniversalLabel.LENGTH];
+
+ try {
+ while (true) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ // Read the UniversalLabel
+ int read = is.read(key, 0, key.length);
+ if (read < 0) {
+ break;
+ }
+ if (read != key.length) {
+ throw new KlvParseException(
+ "Read " + read + " bytes when expected " + key.length);
+ }
+ out.write(key);
+
+ // Read the payload length
+ BerField length = BerDecoder.decode(is, false);
+ out.write(BerEncoder.encode(length.getValue()));
+
+ // Read the payload
+ byte[] payload = new byte[length.getValue()];
+ read = is.read(payload, 0, payload.length);
+ if (read == 0) {
+ break;
+ }
+ if (read != payload.length) {
+ throw new KlvParseException(
+ "Read " + read + " bytes when expected " + payload.length);
+ }
+ out.write(payload);
+
+ // hand off the IMisbMessage
+ byte[] buf = out.toByteArray();
+ try {
+ IMisbMessage msg = MisbMessageFactory.getInstance().handleMessage(buf);
+ handler.accept(msg);
+ } catch (KlvParseException e) {
+ exceptionHandler.accept(new KlvParseException(e, buf));
+ }
+ }
+ } catch (IOException e) {
+ throw new KlvParseException("IOException during stream parsing");
+ }
+ }
+
/**
* Parse a byte array containing one or more {@link IMisbMessage}s.
*
diff --git a/api/src/test/java/org/jmisb/api/klv/BerDecoderTest.java b/api/src/test/java/org/jmisb/api/klv/BerDecoderTest.java
index 02fd85789..95a20ea68 100644
--- a/api/src/test/java/org/jmisb/api/klv/BerDecoderTest.java
+++ b/api/src/test/java/org/jmisb/api/klv/BerDecoderTest.java
@@ -1,5 +1,8 @@
package org.jmisb.api.klv;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -21,6 +24,24 @@ public void testShortFormLengthField() {
Assert.assertEquals(l3.getLength(), 1);
}
+ @Test
+ public void testShortFormLengthFieldInputStream() throws IOException {
+ // BER Short Form is always encoded in a single byte, and has its high order bit set to 0
+ byte[] data = {0x00, 0x05, 0x7f}; // 1, 5, 127
+ ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ BerField l1 = BerDecoder.decode(bais, false);
+ BerField l2 = BerDecoder.decode(bais, false);
+ BerField l3 = BerDecoder.decode(bais, false);
+
+ Assert.assertEquals(l1.getValue(), 0);
+ Assert.assertEquals(l2.getValue(), 5);
+ Assert.assertEquals(l3.getValue(), 127);
+
+ Assert.assertEquals(l1.getLength(), 1);
+ Assert.assertEquals(l2.getLength(), 1);
+ Assert.assertEquals(l3.getLength(), 1);
+ }
+
@Test
public void testLongFormLengthField() {
byte[] data = {
@@ -40,13 +61,54 @@ public void testLongFormLengthField() {
Assert.assertEquals(l3.getLength(), 5);
}
+ @Test
+ public void testLongFormLengthFieldInputStream() throws IOException {
+ byte[] data = {
+ (byte) 0x81, 0x05, (byte) 0x82, 0x01, (byte) 0x80, (byte) 0x84, 0x01, 0x01, 0x01, 0x01
+ };
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ BerField l1 = BerDecoder.decode(bais, false);
+ BerField l2 = BerDecoder.decode(bais, false);
+ BerField l3 = BerDecoder.decode(bais, false);
+
+ Assert.assertEquals(l1.getValue(), 5);
+ Assert.assertEquals(l2.getValue(), 384);
+ Assert.assertEquals(l3.getValue(), 16_843_009);
+
+ Assert.assertEquals(l1.getLength(), 2);
+ Assert.assertEquals(l2.getLength(), 3);
+ Assert.assertEquals(l3.getLength(), 5);
+ }
+
+ @Test(
+ expectedExceptions = IllegalArgumentException.class,
+ expectedExceptionsMessageRegExp = "BER parsing ran out of bytes")
+ public void testLongFormLengthFieldInputStreamOverrun() throws IOException {
+ byte[] data = {(byte) 0x84, 0x01, 0x02, 0x03};
+ InputStream is = new ByteArrayInputStream(data);
+ BerDecoder.decode(is, false);
+ }
+
+ @Test(
+ expectedExceptions = IllegalArgumentException.class,
+ expectedExceptionsMessageRegExp =
+ "BER long form: BER length is >4 bytes; data is probably corrupt")
+ public void testLongFormLengthFieldInputStreamTooLong() throws IOException {
+ byte[] data = {(byte) 0x85, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00};
+ InputStream is = new ByteArrayInputStream(data);
+ BerDecoder.decode(is, false);
+ }
+
@Test(expectedExceptions = IllegalArgumentException.class)
public void testParseBufferOverrun() {
byte[] data = {0x00, 0x05, 0x7f};
BerField l1 = BerDecoder.decode(data, 3, false);
}
- @Test(expectedExceptions = IllegalArgumentException.class)
+ @Test(
+ expectedExceptions = IllegalArgumentException.class,
+ expectedExceptionsMessageRegExp = "Cannot read BER from beyond array limit")
public void testParseBufferOverrunGreater() {
byte[] data = {0x00, 0x05, 0x7f};
BerField l1 = BerDecoder.decode(data, 4, false);
@@ -64,7 +126,10 @@ public void testParseBufferOverrunLongform() {
BerField l1 = BerDecoder.decode(data, 2, false);
}
- @Test(expectedExceptions = IllegalArgumentException.class)
+ @Test(
+ expectedExceptions = IllegalArgumentException.class,
+ expectedExceptionsMessageRegExp =
+ "BER long form: BER length is >4 bytes; data is probably corrupt")
public void testParseBufferOverrunLongform5() {
byte[] data = {(byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
BerField l1 = BerDecoder.decode(data, 0, false);
@@ -75,4 +140,119 @@ public void testParseIndexOverrunOid() {
byte[] data = {(byte) 0x80};
BerField l1 = BerDecoder.decode(data, 0, true);
}
+
+ @Test
+ public void testBerOidDecode1() {
+ BerField berField = BerDecoder.decode(new byte[] {(byte) 0x01}, 0, true);
+ Assert.assertEquals(berField.getLength(), 1);
+ Assert.assertEquals(berField.getValue(), 1);
+ }
+
+ @Test
+ public void testBerOidDecode127() {
+ BerField berField = BerDecoder.decode(new byte[] {(byte) 0x7f}, 0, true);
+ Assert.assertEquals(berField.getLength(), 1);
+ Assert.assertEquals(berField.getValue(), 127);
+ }
+
+ @Test
+ public void testBerOidDecode128() {
+ BerField berField = BerDecoder.decode(new byte[] {(byte) 0x81, (byte) 0x00}, 0, true);
+ Assert.assertEquals(berField.getLength(), 2);
+ Assert.assertEquals(berField.getValue(), 128);
+ }
+
+ @Test
+ public void testBerOidDecode129() {
+ BerField berField = BerDecoder.decode(new byte[] {(byte) 0x81, (byte) 0x01}, 0, true);
+ Assert.assertEquals(berField.getLength(), 2);
+ Assert.assertEquals(berField.getValue(), 129);
+ }
+
+ @Test
+ public void testBerOidDecode255() {
+ BerField berField = BerDecoder.decode(new byte[] {(byte) 0x81, (byte) 0x7f}, 0, true);
+ Assert.assertEquals(berField.getLength(), 2);
+ Assert.assertEquals(berField.getValue(), 255);
+ }
+
+ @Test
+ public void testBerOidDecode256() {
+ BerField berField = BerDecoder.decode(new byte[] {(byte) 0x82, (byte) 0x00}, 0, true);
+ Assert.assertEquals(berField.getLength(), 2);
+ Assert.assertEquals(berField.getValue(), 256);
+ }
+
+ @Test
+ public void testBerOidDecode65535() {
+ BerField berField =
+ BerDecoder.decode(new byte[] {(byte) 0x83, (byte) 0xff, (byte) 0x7f}, 0, true);
+ Assert.assertEquals(berField.getLength(), 3);
+ Assert.assertEquals(berField.getValue(), 65535);
+ }
+
+ @Test
+ public void testBerOidDecode256Offset() {
+ BerField berField =
+ BerDecoder.decode(new byte[] {(byte) 0x80, (byte) 0x82, (byte) 0x00}, 1, true);
+ Assert.assertEquals(berField.getLength(), 2);
+ Assert.assertEquals(berField.getValue(), 256);
+ }
+
+ @Test
+ public void testBerOidDecode1InputStream() throws IOException {
+ InputStream is = new ByteArrayInputStream(new byte[] {(byte) 0x01});
+ BerField berField = BerDecoder.decode(is, true);
+ Assert.assertEquals(berField.getLength(), 1);
+ Assert.assertEquals(berField.getValue(), 1);
+ }
+
+ @Test
+ public void testBerOidDecode127InputStream() throws IOException {
+ InputStream is = new ByteArrayInputStream(new byte[] {(byte) 0x7f});
+ BerField berField = BerDecoder.decode(is, true);
+ Assert.assertEquals(berField.getLength(), 1);
+ Assert.assertEquals(berField.getValue(), 127);
+ }
+
+ @Test
+ public void testBerOidDecode128InputStream() throws IOException {
+ InputStream is = new ByteArrayInputStream(new byte[] {(byte) 0x81, (byte) 0x00});
+ BerField berField = BerDecoder.decode(is, true);
+ Assert.assertEquals(berField.getLength(), 2);
+ Assert.assertEquals(berField.getValue(), 128);
+ }
+
+ @Test
+ public void testBerOidDecode129InputStream() throws IOException {
+ InputStream is = new ByteArrayInputStream(new byte[] {(byte) 0x81, (byte) 0x01});
+ BerField berField = BerDecoder.decode(is, true);
+ Assert.assertEquals(berField.getLength(), 2);
+ Assert.assertEquals(berField.getValue(), 129);
+ }
+
+ @Test
+ public void testBerOidDecode255InputStream() throws IOException {
+ InputStream is = new ByteArrayInputStream(new byte[] {(byte) 0x81, (byte) 0x7f});
+ BerField berField = BerDecoder.decode(is, true);
+ Assert.assertEquals(berField.getLength(), 2);
+ Assert.assertEquals(berField.getValue(), 255);
+ }
+
+ @Test
+ public void testBerOidDecode256InputStream() throws IOException {
+ InputStream is = new ByteArrayInputStream(new byte[] {(byte) 0x82, (byte) 0x00});
+ BerField berField = BerDecoder.decode(is, true);
+ Assert.assertEquals(berField.getLength(), 2);
+ Assert.assertEquals(berField.getValue(), 256);
+ }
+
+ @Test
+ public void testBerOidDecode65535InputStream() throws IOException {
+ InputStream is =
+ new ByteArrayInputStream(new byte[] {(byte) 0x83, (byte) 0xff, (byte) 0x7f});
+ BerField berField = BerDecoder.decode(is, true);
+ Assert.assertEquals(berField.getLength(), 3);
+ Assert.assertEquals(berField.getValue(), 65535);
+ }
}
diff --git a/api/src/test/java/org/jmisb/api/klv/KlvParserTest.java b/api/src/test/java/org/jmisb/api/klv/KlvParserTest.java
index 2da691420..6e37a3b3d 100644
--- a/api/src/test/java/org/jmisb/api/klv/KlvParserTest.java
+++ b/api/src/test/java/org/jmisb/api/klv/KlvParserTest.java
@@ -4,6 +4,9 @@
import com.github.valfirst.slf4jtest.TestLogger;
import com.github.valfirst.slf4jtest.TestLoggerFactory;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
import java.util.List;
import org.jmisb.api.common.KlvParseException;
import org.testng.annotations.AfterMethod;
@@ -62,6 +65,109 @@ private void doParse() throws KlvParseException {
assertTrue(rawMessage.getIdentifiers().isEmpty());
}
+ @Test
+ public void checkParseStream() throws KlvParseException {
+ byte[] bytes =
+ new byte[] {
+ 0x06, 0x0E, 0x2B, 0x34, 0x02, 0x0B, 0x01, 0x01, 0x0E, 0x01, 0x03, 0x01, 0x02,
+ 0x00, 0x00, 0x00, 0x09, 0x04, 0x02, 0x00, 0x4f, 0x01, 0x03, 0x1e, 0x2f, 0x3a,
+ 0x06, 0x0E, 0x2B, 0x34, 0x02, 0x0B, 0x01, 0x01, 0x0E, 0x01, 0x03, 0x01, 0x02,
+ 0x00, 0x00, 0x00, 0x09, 0x04, 0x02, 0x00, 0x4f, 0x01, 0x03, 0x1e, 0x2f, 0x3b
+ };
+ ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ List messages = new ArrayList<>();
+ List errors = new ArrayList<>();
+ KlvParser.parseStream(bais, messages::add, errors::add);
+ assertEquals(0, errors.size());
+ if (!errors.isEmpty()) {
+ throw errors.get(0);
+ }
+
+ assertNotNull(messages);
+ assertEquals(messages.size(), 2);
+ for (int i = 0; i < messages.size(); i++) {
+ IMisbMessage message = messages.get(i);
+ assertNotNull(message);
+ assertEquals(
+ message.getUniversalLabel(),
+ new UniversalLabel(
+ new byte[] {
+ 0x06, 0x0E, 0x2B, 0x34, 0x02, 0x0B, 0x01, 0x01, 0x0E, 0x01, 0x03,
+ 0x01, 0x02, 0x00, 0x00, 0x00
+ }));
+ assertEquals(message.displayHeader(), "Unknown");
+ assertTrue(message instanceof RawMisbMessage);
+ RawMisbMessage rawMessage = (RawMisbMessage) message;
+ assertEquals(
+ rawMessage.getBytes(),
+ new byte[] {
+ 0x06, 0x0E, 0x2B, 0x34, 0x02, 0x0B, 0x01, 0x01, 0x0E, 0x01, 0x03, 0x01,
+ 0x02, 0x00, 0x00, 0x00, 0x09, 0x04, 0x02, 0x00, 0x4f, 0x01, 0x03, 0x1e,
+ 0x2f, (byte) (0x3a + i)
+ });
+ assertTrue(rawMessage.getIdentifiers().isEmpty());
+ }
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void checkParseStreamWithError() throws KlvParseException {
+ byte[] bytes =
+ new byte[] {
+ 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x03, 0x01, 0x01, 0x00, 0x06, 0x0E, 0x2B, 0x34, 0x02, 0x0B,
+ 0x01, 0x01, 0x0E, 0x01, 0x03, 0x01, 0x02, 0x00, 0x00, 0x00, 0x09, 0x04, 0x02,
+ 0x00, 0x4f, 0x01, 0x03, 0x1e, 0x2f, 0x3a
+ };
+ MisbMessageFactory.getInstance()
+ .registerHandler(
+ MisbMessageFactoryThatThrowsOnCreate.UNIVERSAL_LABEL,
+ new MisbMessageFactoryThatThrowsOnCreate());
+ InputStream is = new ByteArrayInputStream(bytes);
+ List messages = new ArrayList<>();
+ List errors = new ArrayList<>();
+ KlvParser.parseStream(is, messages::add, errors::add);
+ assertNotNull(errors);
+ assertEquals(errors.size(), 1);
+ assertEquals(
+ errors.get(0).getMessage(),
+ "org.jmisb.api.common.KlvParseException: MisbMessageFactoryThatThrowsOnCreate::create()");
+ assertNotNull(messages);
+ assertEquals(messages.size(), 1);
+ IMisbMessage message = messages.get(0);
+ assertNotNull(message);
+ assertEquals(
+ message.getUniversalLabel(),
+ new UniversalLabel(
+ new byte[] {
+ 0x06, 0x0E, 0x2B, 0x34, 0x02, 0x0B, 0x01, 0x01, 0x0E, 0x01, 0x03, 0x01,
+ 0x02, 0x00, 0x00, 0x00
+ }));
+ assertEquals(message.displayHeader(), "Unknown");
+ assertTrue(message instanceof RawMisbMessage);
+ RawMisbMessage rawMessage = (RawMisbMessage) message;
+ assertEquals(
+ rawMessage.getBytes(),
+ new byte[] {
+ 0x06, 0x0E, 0x2B, 0x34, 0x02, 0x0B, 0x01, 0x01, 0x0E, 0x01, 0x03, 0x01,
+ 0x02, 0x00, 0x00, 0x00, 0x09, 0x04, 0x02, 0x00, 0x4f, 0x01, 0x03, 0x1e,
+ 0x2f, 0x3a
+ });
+ }
+
+ @Test(
+ expectedExceptions = KlvParseException.class,
+ expectedExceptionsMessageRegExp = "Read 1 bytes when expected 2")
+ public void checkParseStreamBadLength() throws KlvParseException {
+ InputStream is =
+ new ByteArrayInputStream(
+ new byte[] {
+ 0x06, 0x0E, 0x2B, 0x34, 0x02, 0x0B, 0x01, 0x01, 0x0E, 0x01, 0x03, 0x01,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00
+ });
+ KlvParser.parseStream(is, null, null);
+ }
+
@Test(expectedExceptions = KlvParseException.class)
public void checkBadLength() throws KlvParseException {
KlvParser.parseBytes(
diff --git a/api/src/test/java/org/jmisb/api/klv/MisbMessageFactoryThatThrowsOnCreate.java b/api/src/test/java/org/jmisb/api/klv/MisbMessageFactoryThatThrowsOnCreate.java
new file mode 100644
index 000000000..90722845e
--- /dev/null
+++ b/api/src/test/java/org/jmisb/api/klv/MisbMessageFactoryThatThrowsOnCreate.java
@@ -0,0 +1,25 @@
+package org.jmisb.api.klv;
+
+import org.jmisb.api.common.KlvParseException;
+
+/** A test factory to check error handling */
+public class MisbMessageFactoryThatThrowsOnCreate implements IMisbMessageFactory {
+
+ // This isn't real - only used for unit testing.
+ public static final UniversalLabel UNIVERSAL_LABEL =
+ new UniversalLabel(
+ new byte[] {
+ 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03
+ });
+
+ @Override
+ public UniversalLabel getUniversalLabel() {
+ return UNIVERSAL_LABEL;
+ }
+
+ @Override
+ public IMisbMessage create(byte[] bytes) throws KlvParseException {
+ throw new KlvParseException("MisbMessageFactoryThatThrowsOnCreate::create()");
+ }
+}
diff --git a/api/src/test/java/org/jmisb/api/klv/NothingFactory1.java b/api/src/test/java/org/jmisb/api/klv/NothingFactory1.java
index 0acd06ebe..47b280ac9 100644
--- a/api/src/test/java/org/jmisb/api/klv/NothingFactory1.java
+++ b/api/src/test/java/org/jmisb/api/klv/NothingFactory1.java
@@ -1,7 +1,5 @@
package org.jmisb.api.klv;
-import static org.jmisb.api.klv.NothingMessage1.UNIVERSAL_LABEL;
-
import org.jmisb.api.common.KlvParseException;
/** A test factory. */
@@ -9,7 +7,7 @@ public class NothingFactory1 implements IMisbMessageFactory {
@Override
public UniversalLabel getUniversalLabel() {
- return UNIVERSAL_LABEL;
+ return NothingMessage1.UNIVERSAL_LABEL;
}
@Override