From 913d74a133ed31976f1b313b6b012b68e7c0ea1a Mon Sep 17 00:00:00 2001 From: Enrique Zamudio Date: Fri, 18 Jan 2013 13:29:39 -0600 Subject: [PATCH] Fix #5 - Add field number to parse error messages --- .../parse/AlphaNumericFieldParseInfo.java | 15 ++++--- .../solab/iso8583/parse/AlphaParseInfo.java | 18 +++++---- .../solab/iso8583/parse/AmountParseInfo.java | 25 ++++++++---- .../solab/iso8583/parse/BinaryParseInfo.java | 25 +++++++++--- .../com/solab/iso8583/parse/ConfigParser.java | 26 +++++++----- .../solab/iso8583/parse/Date10ParseInfo.java | 21 ++++++++-- .../solab/iso8583/parse/Date4ParseInfo.java | 17 ++++++-- .../solab/iso8583/parse/DateExpParseInfo.java | 22 ++++++++-- .../solab/iso8583/parse/FieldParseInfo.java | 18 +++++++-- .../solab/iso8583/parse/LlbinParseInfo.java | 36 ++++++++++++----- .../solab/iso8583/parse/LllbinParseInfo.java | 40 +++++++++++++------ .../solab/iso8583/parse/LllvarParseInfo.java | 36 +++++++++++------ .../solab/iso8583/parse/LlvarParseInfo.java | 29 +++++++++----- .../solab/iso8583/parse/NumericParseInfo.java | 17 +++++--- .../solab/iso8583/parse/TimeParseInfo.java | 20 +++++++--- 15 files changed, 253 insertions(+), 112 deletions(-) diff --git a/src/main/java/com/solab/iso8583/parse/AlphaNumericFieldParseInfo.java b/src/main/java/com/solab/iso8583/parse/AlphaNumericFieldParseInfo.java index 40e239e..8d115c3 100644 --- a/src/main/java/com/solab/iso8583/parse/AlphaNumericFieldParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/AlphaNumericFieldParseInfo.java @@ -35,12 +35,15 @@ public abstract class AlphaNumericFieldParseInfo extends FieldParseInfo { super(t, len); } - public IsoValue parse(byte[] buf, int pos, CustomField custom) throws ParseException, UnsupportedEncodingException { + public IsoValue parse(final int field, final byte[] buf, final int pos, + final CustomField custom) + throws ParseException, UnsupportedEncodingException { if (pos < 0) { - throw new ParseException(String.format("Invalid ALPHA/NUM position %d", pos), pos); + throw new ParseException(String.format("Invalid ALPHA/NUM field %d position %d", + field, pos), pos); } else if (pos+length > buf.length) { - throw new ParseException(String.format("Insufficient data for %s field of length %d, pos %d", - type, length, pos), pos); + throw new ParseException(String.format("Insufficient data for %s field %d of length %d, pos %d", + type, field, length, pos), pos); } try { String _v = new String(buf, pos, length, getCharacterEncoding()); @@ -58,7 +61,9 @@ public abstract class AlphaNumericFieldParseInfo extends FieldParseInfo { return v; } } catch (StringIndexOutOfBoundsException ex) { - throw new ParseException(String.format("Insufficient data for %s field of length %d, pos %d", type, length, pos), pos); + throw new ParseException(String.format( + "Insufficient data for %s field %d of length %d, pos %d", + type, field, length, pos), pos); } } diff --git a/src/main/java/com/solab/iso8583/parse/AlphaParseInfo.java b/src/main/java/com/solab/iso8583/parse/AlphaParseInfo.java index 368cab3..12a5792 100644 --- a/src/main/java/com/solab/iso8583/parse/AlphaParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/AlphaParseInfo.java @@ -35,13 +35,16 @@ public class AlphaParseInfo extends AlphaNumericFieldParseInfo { super(IsoType.ALPHA, len); } - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) - throws ParseException, UnsupportedEncodingException { + public IsoValue parseBinary(final int field, final byte[] buf, final int pos, + final CustomField custom) + throws ParseException, UnsupportedEncodingException { if (pos < 0) { - throw new ParseException(String.format("Invalid bin ALPHA position %d", pos), pos); + throw new ParseException(String.format("Invalid bin ALPHA field %d position %d", + field, pos), pos); } else if (pos+length > buf.length) { - throw new ParseException(String.format("Insufficient data for bin %s field of length %d, pos %d", - type, length, pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin %s field %d of length %d, pos %d", + type, field, length, pos), pos); } try { if (custom == null) { @@ -55,8 +58,9 @@ public class AlphaParseInfo extends AlphaNumericFieldParseInfo { return v; } } catch (IndexOutOfBoundsException ex) { - throw new ParseException(String.format("Insufficient data for bin %s field of length %d, pos %d", - type, length, pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin %s field %d of length %d, pos %d", + type, field, length, pos), pos); } } diff --git a/src/main/java/com/solab/iso8583/parse/AmountParseInfo.java b/src/main/java/com/solab/iso8583/parse/AmountParseInfo.java index 4453703..4a45470 100644 --- a/src/main/java/com/solab/iso8583/parse/AmountParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/AmountParseInfo.java @@ -37,25 +37,32 @@ public class AmountParseInfo extends FieldParseInfo { super(IsoType.AMOUNT, 12); } - public IsoValue parse(byte[] buf, int pos, CustomField custom) + public IsoValue parse(final int field, final byte[] buf, + final int pos, final CustomField custom) throws ParseException, UnsupportedEncodingException { if (pos < 0) { - throw new ParseException(String.format("Invalid AMOUNT position %d", pos), pos); + throw new ParseException(String.format("Invalid AMOUNT field %d position %d", + field, pos), pos); } if (pos+12 > buf.length) { - throw new ParseException(String.format("Insufficient data for AMOUNT field, pos %d", pos), pos); + throw new ParseException(String.format("Insufficient data for AMOUNT field %d, pos %d", + field, pos), pos); } String c = new String(buf, pos, 12, getCharacterEncoding()); try { return new IsoValue(type, new BigDecimal(c).movePointLeft(2), null); } catch (NumberFormatException ex) { - throw new ParseException(String.format("Cannot read amount '%s' pos %d", c, pos), pos); + throw new ParseException(String.format("Cannot read amount '%s' field %d pos %d", + c, field, pos), pos); } catch (IndexOutOfBoundsException ex) { - throw new ParseException(String.format("Insufficient data for AMOUNT field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for AMOUNT field %d, pos %d", field, pos), pos); } } - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parseBinary(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { char[] digits = new char[13]; digits[10] = '.'; int start = 0; @@ -69,9 +76,11 @@ public class AmountParseInfo extends FieldParseInfo { try { return new IsoValue(IsoType.AMOUNT, new BigDecimal(new String(digits)), null); } catch (NumberFormatException ex) { - throw new ParseException(String.format("Cannot read amount '%s' pos %d", new String(digits), pos), pos); + throw new ParseException(String.format("Cannot read amount '%s' field %d pos %d", + new String(digits), field, pos), pos); } catch (IndexOutOfBoundsException ex) { - throw new ParseException(String.format("Insufficient data for AMOUNT field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for AMOUNT field %d, pos %d", field, pos), pos); } } diff --git a/src/main/java/com/solab/iso8583/parse/BinaryParseInfo.java b/src/main/java/com/solab/iso8583/parse/BinaryParseInfo.java index e5e3ed3..e02e15a 100644 --- a/src/main/java/com/solab/iso8583/parse/BinaryParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/BinaryParseInfo.java @@ -38,14 +38,17 @@ public class BinaryParseInfo extends FieldParseInfo { } @Override - public IsoValue parse(byte[] buf, int pos, CustomField custom) + public IsoValue parse(final int field, final byte[] buf, final int pos, + final CustomField custom) throws ParseException, UnsupportedEncodingException { if (pos < 0) { - throw new ParseException(String.format("Invalid BINARY position %d", pos), pos); + throw new ParseException(String.format("Invalid BINARY field %d position %d", + field, pos), pos); } if (pos+(length*2) > buf.length) { - throw new ParseException(String.format("Insufficient data for BINARY field of length %d, pos %d", - length, pos), pos); + throw new ParseException(String.format( + "Insufficient data for BINARY field %d of length %d, pos %d", + field, length, pos), pos); } byte[] binval = HexCodec.hexDecode(new String(buf, pos, length*2)); if (custom == null) { @@ -61,14 +64,24 @@ public class BinaryParseInfo extends FieldParseInfo { } @Override - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parseBinary(final int field, final byte[] buf, final int pos, + final CustomField custom) throws ParseException { + if (pos < 0) { + throw new ParseException(String.format("Invalid BINARY field %d position %d", + field, pos), pos); + } + if (pos+length > buf.length) { + throw new ParseException(String.format( + "Insufficient data for BINARY field %d of length %d, pos %d", + field, length, pos), pos); + } byte[] _v = new byte[length]; System.arraycopy(buf, pos, _v, 0, length); if (custom == null) { return new IsoValue(type, _v, length, null); } else { @SuppressWarnings({"unchecked", "rawtypes"}) - IsoValue v = new IsoValue(type, custom.decodeField(HexCodec.hexEncode(_v)), length, custom); + IsoValue v = new IsoValue(type, custom.decodeField(HexCodec.hexEncode(_v, 0, _v.length)), length, custom); if (v.getValue() == null) { return new IsoValue(type, _v, length, null); } diff --git a/src/main/java/com/solab/iso8583/parse/ConfigParser.java b/src/main/java/com/solab/iso8583/parse/ConfigParser.java index b8eff9b..03f6b9c 100644 --- a/src/main/java/com/solab/iso8583/parse/ConfigParser.java +++ b/src/main/java/com/solab/iso8583/parse/ConfigParser.java @@ -52,19 +52,19 @@ public class ConfigParser { /** Creates a message factory configured from the default file, which is j8583.xml * located in the root of the classpath. */ - public static MessageFactory createDefault() throws IOException { + public static MessageFactory createDefault() throws IOException { if (MessageFactory.class.getClassLoader().getResource("j8583.xml") == null) { log.warn("ISO8583 ConfigParser cannot find j8583.xml, returning empty message factory"); - return new MessageFactory(); + return new MessageFactory(); } else { return createFromClasspathConfig("j8583.xml"); } } /** Creates a message factory from the specified path inside the classpath. */ - public static MessageFactory createFromClasspathConfig(String path) throws IOException { + public static MessageFactory createFromClasspathConfig(String path) throws IOException { InputStream ins = MessageFactory.class.getClassLoader().getResourceAsStream(path); - MessageFactory mfact = new MessageFactory(); + MessageFactory mfact = new MessageFactory(); if (ins != null) { log.debug("ISO8583 Parsing config from classpath file {}", path); try { @@ -79,8 +79,8 @@ public class ConfigParser { } /** Creates a message factory from the file located at the specified URL. */ - public static MessageFactory createFromUrl(URL url) throws IOException { - MessageFactory mfact = new MessageFactory(); + public static MessageFactory createFromUrl(URL url) throws IOException { + MessageFactory mfact = new MessageFactory(); InputStream stream = url.openStream(); try { parse(mfact, stream); @@ -93,7 +93,8 @@ public class ConfigParser { /** Reads the XML from the stream and configures the message factory with its values. * @param mfact The message factory to be configured with the values read from the XML. * @param stream The InputStream containing the XML configuration. */ - protected static void parse(MessageFactory mfact, InputStream stream) throws IOException { + protected static void parse( + MessageFactory mfact, InputStream stream) throws IOException { final DocumentBuilderFactory docfact = DocumentBuilderFactory.newInstance(); DocumentBuilder docb = null; Document doc = null; @@ -167,7 +168,7 @@ public class ConfigParser { CustomField _cf = mfact.getCustomField(num); m.setValue(num, _cf == null ? v : _cf.decodeField(v), _cf, itype, length); } - mfact.addMessageTemplate(m); + mfact.addMessageTemplate((T)m); } //Read the parsing guides @@ -197,7 +198,8 @@ public class ConfigParser { /** Configures a MessageFactory using the default configuration file j8583.xml. This is useful * if you have a MessageFactory created using Spring for example. */ - public static void configureFromDefault(MessageFactory mfact) throws IOException { + public static void configureFromDefault( + MessageFactory mfact) throws IOException { if (MessageFactory.class.getClassLoader().getResource("j8583.xml") == null) { log.warn("ISO8583 config file j8583.xml not found!"); } else { @@ -207,7 +209,8 @@ public class ConfigParser { /** This method attempts to open a stream from the XML configuration in the specified URL and * configure the message factory from that config. */ - public static void configureFromUrl(MessageFactory mfact, URL url) throws IOException { + public static void configureFromUrl( + MessageFactory mfact, URL url) throws IOException { InputStream stream = url.openStream(); try { parse(mfact, stream); @@ -219,7 +222,8 @@ public class ConfigParser { /** Configures a MessageFactory using the configuration file at the path specified (will be searched * within the classpath using the MessageFactory's ClassLoader). This is useful for configuring * Spring-bound instances of MessageFactory for example. */ - public static void configureFromClasspathConfig(MessageFactory mfact, String path) throws IOException { + public static void configureFromClasspathConfig( + MessageFactory mfact, String path) throws IOException { InputStream ins = MessageFactory.class.getClassLoader().getResourceAsStream(path); if (ins != null) { log.debug("ISO8583 Parsing config from classpath file {}", path); diff --git a/src/main/java/com/solab/iso8583/parse/Date10ParseInfo.java b/src/main/java/com/solab/iso8583/parse/Date10ParseInfo.java index 4fc2818..71b4c09 100644 --- a/src/main/java/com/solab/iso8583/parse/Date10ParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/Date10ParseInfo.java @@ -42,13 +42,16 @@ public class Date10ParseInfo extends FieldParseInfo { } @Override - public IsoValue parse(byte[] buf, int pos, CustomField custom) + public IsoValue parse(final int field, final byte[] buf, + final int pos, final CustomField custom) throws ParseException { if (pos < 0) { - throw new ParseException(String.format("Invalid DATE10 position %d", pos), pos); + throw new ParseException(String.format("Invalid DATE10 field %d position %d", + field, pos), pos); } if (pos+10 > buf.length) { - throw new ParseException(String.format("Insufficient data for DATE10 field, pos %d", pos), pos); + throw new ParseException(String.format("Insufficient data for DATE10 field %d, pos %d", + field, pos), pos); } //A SimpleDateFormat in the case of dates won't help because of the missing data //we have to use the current date for reference and change what comes in the buffer @@ -65,7 +68,17 @@ public class Date10ParseInfo extends FieldParseInfo { } @Override - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parseBinary(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { + if (pos < 0) { + throw new ParseException(String.format("Invalid DATE10 field %d position %d", + field, pos), pos); + } + if (pos+5 > buf.length) { + throw new ParseException(String.format("Insufficient data for DATE10 field %d, pos %d", + field, pos), pos); + } int[] tens = new int[5]; int start = 0; for (int i = pos; i < pos + tens.length; i++) { diff --git a/src/main/java/com/solab/iso8583/parse/Date4ParseInfo.java b/src/main/java/com/solab/iso8583/parse/Date4ParseInfo.java index cad87e3..b3e640c 100644 --- a/src/main/java/com/solab/iso8583/parse/Date4ParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/Date4ParseInfo.java @@ -37,12 +37,15 @@ public class Date4ParseInfo extends FieldParseInfo { } @Override - public IsoValue parse(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parse(final int field, final byte[] buf, final int pos, + final CustomField custom) throws ParseException { if (pos < 0) { - throw new ParseException(String.format("Invalid DATE4 position %d", pos), pos); + throw new ParseException(String.format("Invalid DATE4 field %d position %d", + field, pos), pos); } if (pos+4 > buf.length) { - throw new ParseException(String.format("Insufficient data for DATE4 field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for DATE4 field %d, pos %d", field, pos), pos); } Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR, 0); @@ -57,9 +60,15 @@ public class Date4ParseInfo extends FieldParseInfo { } @Override - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parseBinary(final int field, final byte[] buf, final int pos, + final CustomField custom) throws ParseException { int[] tens = new int[2]; int start = 0; + if (buf.length-pos < 2) { + throw new ParseException(String.format( + "Insufficient data to parse binary DATE4 field %d pos %d", + field, pos), pos); + } for (int i = pos; i < pos + tens.length; i++) { tens[start++] = (((buf[i] & 0xf0) >> 4) * 10) + (buf[i] & 0x0f); } diff --git a/src/main/java/com/solab/iso8583/parse/DateExpParseInfo.java b/src/main/java/com/solab/iso8583/parse/DateExpParseInfo.java index a647959..8d2f39f 100644 --- a/src/main/java/com/solab/iso8583/parse/DateExpParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/DateExpParseInfo.java @@ -37,12 +37,16 @@ public class DateExpParseInfo extends FieldParseInfo { } @Override - public IsoValue parse(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parse(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { if (pos < 0) { - throw new ParseException(String.format("Invalid DATE_EXP position %d", pos), pos); + throw new ParseException(String.format("Invalid DATE_EXP field %d position %d", + field, pos), pos); } if (pos+4 > buf.length) { - throw new ParseException(String.format("Insufficient data for DATE_EXP field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for DATE_EXP field %d pos %d", field, pos), pos); } Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR, 0); @@ -57,7 +61,17 @@ public class DateExpParseInfo extends FieldParseInfo { } @Override - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parseBinary(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { + if (pos < 0) { + throw new ParseException(String.format("Invalid DATE_EXP field %d position %d", + field, pos), pos); + } + if (pos+2 > buf.length) { + throw new ParseException(String.format( + "Insufficient data for DATE_EXP field %d pos %d", field, pos), pos); + } int[] tens = new int[2]; int start = 0; for (int i = pos; i < pos + tens.length; i++) { diff --git a/src/main/java/com/solab/iso8583/parse/FieldParseInfo.java b/src/main/java/com/solab/iso8583/parse/FieldParseInfo.java index 8843b30..bc75d8d 100644 --- a/src/main/java/com/solab/iso8583/parse/FieldParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/FieldParseInfo.java @@ -65,13 +65,23 @@ public abstract class FieldParseInfo { } /** Parses the character data from the buffer and returns the - * IsoValue with the correct data type in it. */ - public abstract IsoValue parse(byte[] buf, int pos, CustomField custom) + * IsoValue with the correct data type in it. + * @param field The field index, useful for error reporting. + * @param buf The full ISO message buffer. + * @param pos The starting position for the field data. + * @param custom A CustomField to decode the field. */ + public abstract IsoValue parse(final int field, byte[] buf, int pos, + CustomField custom) throws ParseException, UnsupportedEncodingException; /** Parses binary data from the buffer, creating and returning an IsoValue of the configured - * type and length. */ - public abstract IsoValue parseBinary(byte[] buf, int pos, CustomField custom) + * type and length. + * @param field The field index, useful for error reporting. + * @param buf The full ISO message buffer. + * @param pos The starting position for the field data. + * @param custom A CustomField to decode the field. */ + public abstract IsoValue parseBinary(final int field, byte[] buf, int pos, + CustomField custom) throws ParseException, UnsupportedEncodingException; /** Returns a new FieldParseInfo instance that can parse the specified type. */ diff --git a/src/main/java/com/solab/iso8583/parse/LlbinParseInfo.java b/src/main/java/com/solab/iso8583/parse/LlbinParseInfo.java index b62c7aa..24c3a8c 100644 --- a/src/main/java/com/solab/iso8583/parse/LlbinParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/LlbinParseInfo.java @@ -37,18 +37,25 @@ public class LlbinParseInfo extends FieldParseInfo { } @Override - public IsoValue parse(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parse(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { if (pos < 0) { - throw new ParseException(String.format("Invalid LLBIN position %d", pos), pos); + throw new ParseException(String.format("Invalid LLBIN field %d position %d", + field, pos), pos); } else if (pos+2 > buf.length) { - throw new ParseException("Insufficient LLBIN header", pos); + throw new ParseException(String.format("Insufficient LLBIN header field %d", + field), pos); } length = ((buf[pos] - 48) * 10) + (buf[pos + 1] - 48); if (length < 0) { - throw new ParseException(String.format("Invalid LLBIN length %d pos %d", length, pos), pos); + throw new ParseException(String.format("Invalid LLBIN field %d length %d pos %d", + field, length, pos), pos); } if (length+pos+2 > buf.length) { - throw new ParseException(String.format("Insufficient data for LLBIN field, pos %d (LEN states '%s')", pos, new String(buf, pos, 2)), pos); + throw new ParseException(String.format( + "Insufficient data for LLBIN field %d, pos %d (LEN states '%s')", + field, pos, new String(buf, pos, 2)), pos); } byte[] binval = length == 0 ? new byte[0] : HexCodec.hexDecode(new String(buf, pos + 2, length)); if (custom == null) { @@ -63,24 +70,31 @@ public class LlbinParseInfo extends FieldParseInfo { } return v; } catch (IndexOutOfBoundsException ex) { - throw new ParseException(String.format("Insufficient data for LLBIN field, pos %d (LEN states '%s')", pos, new String(buf, pos, 2)), pos); + throw new ParseException(String.format( + "Insufficient data for LLBIN field %d, pos %d (LEN states '%s')", + field, pos, new String(buf, pos, 2)), pos); } } } @Override - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parseBinary(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { if (pos < 0) { - throw new ParseException(String.format("Invalid bin LLBIN position %d", pos), pos); + throw new ParseException(String.format("Invalid bin LLBIN field %d position %d", + field, pos), pos); } else if (pos+1 > buf.length) { - throw new ParseException("Insufficient bin LLBIN header", pos); + throw new ParseException(String.format("Insufficient bin LLBIN header field %d", + field), pos); } length = (((buf[pos] & 0xf0) >> 4) * 10) + (buf[pos] & 0x0f); if (length < 0) { throw new ParseException(String.format("Invalid bin LLBIN length %d pos %d", length, pos), pos); } if (length+pos+1 > buf.length) { - throw new ParseException(String.format("Insufficient data for bin LLBIN field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin LLBIN field %d, pos %d", field, pos), pos); } byte[] _v = new byte[length]; System.arraycopy(buf, pos+1, _v, 0, length); @@ -88,7 +102,7 @@ public class LlbinParseInfo extends FieldParseInfo { return new IsoValue(type, _v, null); } else { @SuppressWarnings({"unchecked", "rawtypes"}) - IsoValue v = new IsoValue(type, custom.decodeField(HexCodec.hexEncode(_v)), custom); + IsoValue v = new IsoValue(type, custom.decodeField(HexCodec.hexEncode(_v, 0, _v.length)), custom); if (v.getValue() == null) { return new IsoValue(type, _v, null); } diff --git a/src/main/java/com/solab/iso8583/parse/LllbinParseInfo.java b/src/main/java/com/solab/iso8583/parse/LllbinParseInfo.java index 32c4d7b..43816d6 100644 --- a/src/main/java/com/solab/iso8583/parse/LllbinParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/LllbinParseInfo.java @@ -37,20 +37,27 @@ public class LllbinParseInfo extends FieldParseInfo { } @Override - public IsoValue parse(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parse(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { if (pos < 0) { - throw new ParseException(String.format("Invalid LLLBIN position %d", pos), pos); + throw new ParseException(String.format("Invalid LLLBIN field %d pos %d", + field, pos), pos); } else if (pos+3 > buf.length) { - throw new ParseException("Insufficient LLLBIN header", pos); + throw new ParseException(String.format("Insufficient LLLBIN header field %d", + field), pos); } if (!(Character.isDigit(buf[pos]) && Character.isDigit(buf[pos+1]) && Character.isDigit(buf[pos+2]))) { - throw new ParseException(String.format("Invalid LLLBIN length '%s' pos %d", new String(buf, pos, 3), pos), pos); + throw new ParseException(String.format("Invalid LLLBIN length '%s' field %d pos %d", + new String(buf, pos, 3), field, pos), pos); } length = ((buf[pos] - 48) * 100) + ((buf[pos + 1] - 48) * 10) + (buf[pos + 2] - 48); if (length < 0) { - throw new ParseException(String.format("Invalid LLLBIN length %d pos %d", length, pos), pos); + throw new ParseException(String.format("Invalid LLLBIN length %d field %d pos %d", + length, field, pos), pos); } else if (length+pos+3 > buf.length) { - throw new ParseException(String.format("Insufficient data for LLLBIN field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for LLLBIN field %d, pos %d", field, pos), pos); } byte[] binval = length == 0 ? new byte[0] : HexCodec.hexDecode(new String(buf, pos + 3, length)); if (custom == null) { @@ -66,24 +73,31 @@ public class LllbinParseInfo extends FieldParseInfo { } return v; } catch (IndexOutOfBoundsException ex) { - throw new ParseException(String.format("Insufficient data for LLLBIN field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for LLLBIN field %d, pos %d", field, pos), pos); } } } @Override - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parseBinary(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { if (pos < 0) { - throw new ParseException(String.format("Invalid bin LLLBIN position %d", pos), pos); + throw new ParseException(String.format("Invalid bin LLLBIN field %d pos %d", + field, pos), pos); } else if (pos+3 > buf.length) { - throw new ParseException("Insufficient bin LLLBIN header", pos); + throw new ParseException(String.format("Insufficient LLLBIN header field %d", + field), pos); } length = ((buf[pos] & 0x0f) * 100) + (((buf[pos + 1] & 0xf0) >> 4) * 10) + (buf[pos + 1] & 0x0f); if (length < 0) { - throw new ParseException(String.format("Invalid bin LLLBIN length %d pos %d", length, pos), pos); + throw new ParseException(String.format("Invalid LLLBIN length %d field %d pos %d", + length, field, pos), pos); } if (length+pos+2 > buf.length) { - throw new ParseException(String.format("Insufficient data for bin LLLBIN field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin LLLBIN field %d, pos %d", field, pos), pos); } byte[] _v = new byte[length]; System.arraycopy(buf, pos+2, _v, 0, length); @@ -91,7 +105,7 @@ public class LllbinParseInfo extends FieldParseInfo { return new IsoValue(type, _v, null); } else { @SuppressWarnings({"unchecked", "rawtypes"}) - IsoValue v = new IsoValue(type, custom.decodeField(HexCodec.hexEncode(_v)), custom); + IsoValue v = new IsoValue(type, custom.decodeField(HexCodec.hexEncode(_v, 0, _v.length)), custom); if (v.getValue() == null) { return new IsoValue(type, _v, null); } diff --git a/src/main/java/com/solab/iso8583/parse/LllvarParseInfo.java b/src/main/java/com/solab/iso8583/parse/LllvarParseInfo.java index 90337d7..bb5f99c 100644 --- a/src/main/java/com/solab/iso8583/parse/LllvarParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/LllvarParseInfo.java @@ -36,28 +36,34 @@ public class LllvarParseInfo extends FieldParseInfo { super(IsoType.LLLVAR, 0); } - public IsoValue parse(byte[] buf, int pos, CustomField custom) + public IsoValue parse(final int field, final byte[] buf, + final int pos, final CustomField custom) throws ParseException, UnsupportedEncodingException { if (pos < 0) { - throw new ParseException(String.format("Invalid LLLVAR position %d", pos), pos); + throw new ParseException(String.format("Invalid LLLVAR field %d pos %d", + field, pos), pos); } else if (pos+3 > buf.length) { - throw new ParseException(String.format("Insufficient data for LLLVAR header, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for LLLVAR header field %d pos %d", field, pos), pos); } if (!(Character.isDigit(buf[pos]) && Character.isDigit(buf[pos+1]) && Character.isDigit(buf[pos+2]))) { - throw new ParseException(String.format("Invalid LLLVAR length '%s' pos %d", - new String(buf, pos, 3), pos), pos); + throw new ParseException(String.format("Invalid LLLVAR length '%s' field %d pos %d", + new String(buf, pos, 3), field, pos), pos); } length = ((buf[pos] - 48) * 100) + ((buf[pos + 1] - 48) * 10) + (buf[pos + 2] - 48); if (length < 0) { - throw new ParseException(String.format("Invalid LLLVAR length %d pos %d", length, pos), pos); + throw new ParseException(String.format("Invalid LLLVAR length %d field %d pos %d", + length, field, pos), pos); } else if (length+pos+3 > buf.length) { - throw new ParseException(String.format("Insufficient data for LLLVAR field, pos %d", pos), pos); + throw new ParseException(String.format("Insufficient data for LLLVAR field %d, pos %d", + field, pos), pos); } String _v; try { _v = length == 0 ? "" : new String(buf, pos + 3, length, getCharacterEncoding()); } catch (IndexOutOfBoundsException ex) { - throw new ParseException(String.format("Insufficient data for LLLVAR header, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for LLLVAR header, field %d pos %d", field, pos), pos); } //This is new: if the String's length is different from the specified length in the buffer, //there are probably some extended characters. So we create a String from the rest of the buffer, @@ -74,18 +80,22 @@ public class LllvarParseInfo extends FieldParseInfo { } } - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) + public IsoValue parseBinary(final int field, final byte[] buf, + final int pos, final CustomField custom) throws ParseException, UnsupportedEncodingException { if (pos < 0) { - throw new ParseException(String.format("Invalid bin LLLVAR position %d", pos), pos); + throw new ParseException(String.format("Invalid bin LLLVAR field %d pos %d", field, pos), pos); } else if (pos+3 > buf.length) { - throw new ParseException(String.format("Insufficient data for bin LLLVAR header, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin LLLVAR header, field %d pos %d", field, pos), pos); } length = ((buf[pos] & 0x0f) * 100) + (((buf[pos + 1] & 0xf0) >> 4) * 10) + (buf[pos + 1] & 0x0f); if (length < 0) { - throw new ParseException(String.format("Invalid bin LLLVAR length %d pos %d", length, pos), pos); + throw new ParseException(String.format( + "Invalid bin LLLVAR length %d, field %d pos %d", length, field, pos), pos); } else if (length+pos+2 > buf.length) { - throw new ParseException(String.format("Insufficient data for bin LLLVAR field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin LLLVAR field %d, pos %d", field, pos), pos); } if (custom == null) { return new IsoValue(type, new String(buf, pos + 2, length, getCharacterEncoding()), null); diff --git a/src/main/java/com/solab/iso8583/parse/LlvarParseInfo.java b/src/main/java/com/solab/iso8583/parse/LlvarParseInfo.java index 3c8d3e3..10b376b 100644 --- a/src/main/java/com/solab/iso8583/parse/LlvarParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/LlvarParseInfo.java @@ -35,24 +35,28 @@ public class LlvarParseInfo extends FieldParseInfo { super(IsoType.LLVAR, 0); } - public IsoValue parse(byte[] buf, int pos, CustomField custom) + public IsoValue parse(final int field, final byte[] buf, + final int pos, final CustomField custom) throws ParseException, UnsupportedEncodingException { if (pos < 0) { - throw new ParseException(String.format("Invalid LLVAR position %d", pos), pos); + throw new ParseException(String.format("Invalid LLVAR field %d %d", field, pos), pos); } else if (pos+2 > buf.length) { throw new ParseException(String.format("Insufficient data for LLVAR header, pos %d", pos), pos); } length = ((buf[pos] - 48) * 10) + (buf[pos + 1] - 48); if (length < 0) { - throw new ParseException(String.format("Invalid LLVAR length %d pos %d", length, pos), pos); + throw new ParseException(String.format( + "Invalid LLVAR length %d, field %d pos %d", length, field, pos), pos); } else if (length+pos+2 > buf.length) { - throw new ParseException(String.format("Insufficient data for LLVAR field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for LLVAR field %d, pos %d", field, pos), pos); } String _v; try { _v = length == 0 ? "" : new String(buf, pos + 2, length, getCharacterEncoding()); } catch (IndexOutOfBoundsException ex) { - throw new ParseException(String.format("Insufficient data for LLVAR header, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for LLVAR header, field %d pos %d", field, pos), pos); } //This is new: if the String's length is different from the specified length in the buffer, //there are probably some extended characters. So we create a String from the rest of the buffer, @@ -72,19 +76,24 @@ public class LlvarParseInfo extends FieldParseInfo { } } - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) + public IsoValue parseBinary(final int field, final byte[] buf, + final int pos, final CustomField custom) throws ParseException, UnsupportedEncodingException { if (pos < 0) { - throw new ParseException(String.format("Invalid bin LLVAR position %d", pos), pos); + throw new ParseException(String.format("Invalid bin LLVAR field %d pos %d", + field, pos), pos); } else if (pos+1 > buf.length) { - throw new ParseException(String.format("Insufficient data for bin LLVAR header, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin LLVAR header, field %d pos %d", field, pos), pos); } length = (((buf[pos] & 0xf0) >> 4) * 10) + (buf[pos] & 0x0f); if (length < 0) { - throw new ParseException(String.format("Invalid bin LLVAR length %d pos %d", length, pos), pos); + throw new ParseException(String.format( + "Invalid bin LLVAR length %d, field %d pos %d", length, field, pos), pos); } if (length+pos+1 > buf.length) { - throw new ParseException(String.format("Insufficient data for bin LLVAR field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin LLVAR field %d, pos %d", field, pos), pos); } if (custom == null) { return new IsoValue(type, new String(buf, pos + 1, length, getCharacterEncoding()), null); diff --git a/src/main/java/com/solab/iso8583/parse/NumericParseInfo.java b/src/main/java/com/solab/iso8583/parse/NumericParseInfo.java index 4c87624..c9e4eaf 100644 --- a/src/main/java/com/solab/iso8583/parse/NumericParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/NumericParseInfo.java @@ -35,12 +35,16 @@ public class NumericParseInfo extends AlphaNumericFieldParseInfo { super(IsoType.NUMERIC, len); } - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parseBinary(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { if (pos < 0) { - throw new ParseException(String.format("Invalid bin NUMERIC position %d", pos), pos); + throw new ParseException(String.format("Invalid bin NUMERIC field %d pos %d", + field, pos), pos); } else if (pos+(length/2) > buf.length) { - throw new ParseException(String.format("Insufficient data for bin %s field of length %d, pos %d", - type, length, pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin %s field %d of length %d, pos %d", + type, field, length, pos), pos); } //A long covers up to 18 digits if (length < 19) { @@ -63,8 +67,9 @@ public class NumericParseInfo extends AlphaNumericFieldParseInfo { digits[start++] = (char)((buf[i] & 0x0f) + 48); } } catch (IndexOutOfBoundsException ex) { - throw new ParseException(String.format("Insufficient data for bin %s field of length %d, pos %d", - type, length, pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin %s field %d of length %d, pos %d", + type, field, length, pos), pos); } return new IsoValue(IsoType.NUMERIC, new BigInteger(new String(digits)), length, null); } diff --git a/src/main/java/com/solab/iso8583/parse/TimeParseInfo.java b/src/main/java/com/solab/iso8583/parse/TimeParseInfo.java index d5ac5ad..edd583d 100644 --- a/src/main/java/com/solab/iso8583/parse/TimeParseInfo.java +++ b/src/main/java/com/solab/iso8583/parse/TimeParseInfo.java @@ -38,11 +38,15 @@ public class TimeParseInfo extends FieldParseInfo { } @Override - public IsoValue parse(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parse(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { if (pos < 0) { - throw new ParseException(String.format("Invalid TIME position %d", pos), pos); + throw new ParseException(String.format("Invalid TIME field %d pos %d", + field, pos), pos); } else if (pos+6 > buf.length) { - throw new ParseException(String.format("Insufficient data for TIME field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for TIME field %d, pos %d", field, pos), pos); } Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, ((buf[pos] - 48) * 10) + buf[pos + 1] - 48); @@ -52,11 +56,15 @@ public class TimeParseInfo extends FieldParseInfo { } @Override - public IsoValue parseBinary(byte[] buf, int pos, CustomField custom) throws ParseException { + public IsoValue parseBinary(final int field, final byte[] buf, + final int pos, final CustomField custom) + throws ParseException { if (pos < 0) { - throw new ParseException(String.format("Invalid bin TIME position %d", pos), pos); + throw new ParseException(String.format("Invalid bin TIME field %d pos %d", + field, pos), pos); } else if (pos+3 > buf.length) { - throw new ParseException(String.format("Insufficient data for bin TIME field, pos %d", pos), pos); + throw new ParseException(String.format( + "Insufficient data for bin TIME field %d, pos %d", field, pos), pos); } int[] tens = new int[3]; int start = 0;