Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
175c3c1dfe | ||
|
|
41507d8b5c | ||
|
|
d3e34d760a | ||
|
|
92af1156cc | ||
|
|
4022ab3ad8 | ||
|
|
0d2e5409b4 | ||
|
|
4d02af0a76 | ||
|
|
92c6b6d4f9 | ||
|
|
913d74a133 | ||
|
|
d570eb4885 | ||
|
|
a3a7b53fa0 | ||
|
|
6abbeb93bb | ||
|
|
32fe3f20f4 | ||
|
|
2e5911f261 | ||
|
|
778501b2d6 | ||
|
|
d549b00563 | ||
|
|
8c1abc6b88 |
+4
-4
@@ -1,7 +1,7 @@
|
||||
apply plugin:'java'
|
||||
apply plugin: 'maven'
|
||||
defaultTasks 'build'
|
||||
version='1.5.7'
|
||||
version='1.6.0'
|
||||
description='Java implementation of the ISO 8583 protocol, focused on making the creation, edition and reading of ISO8583 messages as simple and flexible as possible.'
|
||||
sourceCompatibility=6
|
||||
targetCompatibility=6
|
||||
@@ -17,9 +17,9 @@ configurations {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'org.slf4j:slf4j-api:1.7.1'
|
||||
testCompile 'junit:junit:4.10'
|
||||
testRuntime 'org.slf4j:slf4j-simple:1.7.1'
|
||||
compile 'org.slf4j:slf4j-api:1.7.2'
|
||||
testCompile 'junit:junit:4.11'
|
||||
testRuntime 'org.slf4j:slf4j-simple:1.7.2'
|
||||
}
|
||||
|
||||
tasks.javadoc.options.use=true
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="slf4j" level="application" />
|
||||
<orderEntry type="library" scope="TEST" name="jUnit" level="application" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="slf4j-runtime" level="application" />
|
||||
<orderEntry type="library" scope="TEST" name="slf4j-runtime" level="application" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.sf.j8583</groupId>
|
||||
<artifactId>j8583</artifactId>
|
||||
<version>1.5.6</version>
|
||||
<version>1.5.8-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>j8583</name>
|
||||
<description>Java implementation of the ISO 8583 protocol, focused on making the creation, edition and reading of ISO8583 messages as simple and flexible as possible.</description>
|
||||
|
||||
@@ -270,22 +270,16 @@ public class IsoMessage {
|
||||
if (etx > -1) {
|
||||
l++;
|
||||
}
|
||||
byte[] bbuf = new byte[lengthBytes];
|
||||
int pos = 0;
|
||||
if (lengthBytes == 4) {
|
||||
bbuf[0] = (byte)((l & 0xff000000) >> 24);
|
||||
pos++;
|
||||
buf.put((byte)((l & 0xff000000) >> 24));
|
||||
}
|
||||
if (lengthBytes > 2) {
|
||||
bbuf[pos] = (byte)((l & 0xff0000) >> 16);
|
||||
pos++;
|
||||
buf.put((byte)((l & 0xff0000) >> 16));
|
||||
}
|
||||
if (lengthBytes > 1) {
|
||||
bbuf[pos] = (byte)((l & 0xff00) >> 8);
|
||||
pos++;
|
||||
buf.put((byte)((l & 0xff00) >> 8));
|
||||
}
|
||||
bbuf[pos] = (byte)(l & 0xff);
|
||||
buf.put(bbuf);
|
||||
buf.put((byte)(l & 0xff));
|
||||
}
|
||||
buf.put(data);
|
||||
//ETX
|
||||
|
||||
@@ -190,15 +190,17 @@ public class IsoValue<T> implements Cloneable {
|
||||
return type.format((Date)value);
|
||||
} else if (type == IsoType.BINARY) {
|
||||
if (value instanceof byte[]) {
|
||||
return type.format(encoder == null ? HexCodec.hexEncode((byte[])value) : encoder.encodeField(value), length * 2);
|
||||
final byte[] _v = (byte[])value;
|
||||
return type.format(encoder == null ? HexCodec.hexEncode(_v, 0, _v.length) : encoder.encodeField(value), length * 2);
|
||||
} else {
|
||||
return type.format(encoder == null ? value.toString() : encoder.encodeField(value), length * 2);
|
||||
}
|
||||
} else if (type == IsoType.LLBIN || type == IsoType.LLLBIN) {
|
||||
if (value instanceof byte[]) {
|
||||
return encoder == null ? HexCodec.hexEncode((byte[])value) : encoder.encodeField(value);
|
||||
final byte[] _v = (byte[])value;
|
||||
return encoder == null ? HexCodec.hexEncode(_v, 0, _v.length) : encoder.encodeField(value);
|
||||
} else {
|
||||
String _s = encoder == null ? value.toString() : encoder.encodeField(value);
|
||||
final String _s = encoder == null ? value.toString() : encoder.encodeField(value);
|
||||
return (_s.length() % 2 == 1) ? String.format("0%s", _s) : _s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,13 +253,13 @@ public class MessageFactory<T extends IsoMessage> {
|
||||
* and the rest of the message must come. */
|
||||
public T parseMessage(byte[] buf, int isoHeaderLength)
|
||||
throws ParseException, UnsupportedEncodingException {
|
||||
final int minlength = isoHeaderLength+(useBinary||binBitmap ? 10 : 20);
|
||||
final int minlength = isoHeaderLength+(useBinary?2:4)+(binBitmap||useBinary ? 8:16);
|
||||
if (buf.length < minlength) {
|
||||
throw new ParseException("Insufficient buffer length, needs to be at least " + minlength, 0);
|
||||
}
|
||||
final T m = createIsoMessage(isoHeaderLength > 0 ? new String(buf, 0, isoHeaderLength) : null);
|
||||
m.setCharacterEncoding(encoding);
|
||||
int type = 0;
|
||||
final int type;
|
||||
if (useBinary) {
|
||||
type = ((buf[isoHeaderLength] & 0xff) << 8) | (buf[isoHeaderLength + 1] & 0xff);
|
||||
} else {
|
||||
@@ -273,7 +273,8 @@ public class MessageFactory<T extends IsoMessage> {
|
||||
final BitSet bs = new BitSet(64);
|
||||
int pos = 0;
|
||||
if (useBinary || binBitmap) {
|
||||
for (int i = isoHeaderLength + 2; i < isoHeaderLength + 10; i++) {
|
||||
final int bitmapStart = isoHeaderLength + (useBinary ? 2 : 4);
|
||||
for (int i = bitmapStart; i < 8+bitmapStart; i++) {
|
||||
int bit = 128;
|
||||
for (int b = 0; b < 8; b++) {
|
||||
bs.set(pos++, (buf[i] & bit) != 0);
|
||||
@@ -285,7 +286,7 @@ public class MessageFactory<T extends IsoMessage> {
|
||||
if (buf.length < minlength + 8) {
|
||||
throw new ParseException("Insufficient length for secondary bitmap", minlength);
|
||||
}
|
||||
for (int i = isoHeaderLength + 10; i < isoHeaderLength + 18; i++) {
|
||||
for (int i = 8+bitmapStart; i < 16+bitmapStart; i++) {
|
||||
int bit = 128;
|
||||
for (int b = 0; b < 8; b++) {
|
||||
bs.set(pos++, (buf[i] & bit) != 0);
|
||||
@@ -378,7 +379,7 @@ public class MessageFactory<T extends IsoMessage> {
|
||||
log.warn("Field {} is not really in the message even though it's in the bitmap", i);
|
||||
bs.clear(i - 1);
|
||||
} else {
|
||||
IsoValue<?> val = fpi.parseBinary(buf, pos, getCustomField(i));
|
||||
IsoValue<?> val = fpi.parseBinary(i, buf, pos, getCustomField(i));
|
||||
m.setField(i, val);
|
||||
if (val != null) {
|
||||
if (val.getType() == IsoType.NUMERIC || val.getType() == IsoType.DATE10
|
||||
@@ -405,7 +406,7 @@ public class MessageFactory<T extends IsoMessage> {
|
||||
log.warn("Field {} is not really in the message even though it's in the bitmap", i);
|
||||
bs.clear(i - 1);
|
||||
} else {
|
||||
IsoValue<?> val = fpi.parse(buf, pos, getCustomField(i));
|
||||
IsoValue<?> val = fpi.parse(i, buf, pos, getCustomField(i));
|
||||
m.setField(i, val);
|
||||
//To get the correct next position, we need to get the number of bytes, not chars
|
||||
pos += val.toString().getBytes(fpi.getCharacterEncoding()).length;
|
||||
@@ -419,6 +420,7 @@ public class MessageFactory<T extends IsoMessage> {
|
||||
}
|
||||
}
|
||||
m.setBinary(useBinary);
|
||||
m.setBinaryBitmap(binBitmap);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,27 +35,36 @@ 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);
|
||||
}
|
||||
String _v = new String(buf, pos, length, getCharacterEncoding());
|
||||
if (_v.length() != length) {
|
||||
_v = new String(buf, pos, buf.length-pos, getCharacterEncoding()).substring(0, length);
|
||||
}
|
||||
if (custom == null) {
|
||||
return new IsoValue<String>(type, _v, length, null);
|
||||
} else {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
IsoValue<?> v = new IsoValue(type, custom.decodeField(_v), length, custom);
|
||||
if (v.getValue() == null) {
|
||||
return new IsoValue<String>(type, _v, length, null);
|
||||
}
|
||||
return v;
|
||||
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());
|
||||
if (_v.length() != length) {
|
||||
_v = new String(buf, pos, buf.length-pos, getCharacterEncoding()).substring(0, length);
|
||||
}
|
||||
if (custom == null) {
|
||||
return new IsoValue<String>(type, _v, length, null);
|
||||
} else {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
IsoValue<?> v = new IsoValue(type, custom.decodeField(_v), length, custom);
|
||||
if (v.getValue() == null) {
|
||||
return new IsoValue<String>(type, _v, length, null);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
} catch (StringIndexOutOfBoundsException ex) {
|
||||
throw new ParseException(String.format(
|
||||
"Insufficient data for %s field %d of length %d, pos %d",
|
||||
type, field, length, pos), pos);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,24 +35,33 @@ 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);
|
||||
}
|
||||
if (custom == null) {
|
||||
return new IsoValue<String>(type, new String(buf, pos, length, getCharacterEncoding()), length, null);
|
||||
} else {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
IsoValue<?> v = new IsoValue(type, custom.decodeField(new String(buf, pos, length, getCharacterEncoding())), length, custom);
|
||||
if (v.getValue() == null) {
|
||||
return new IsoValue<String>(type, new String(buf, pos, length, getCharacterEncoding()), length, null);
|
||||
}
|
||||
return v;
|
||||
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) {
|
||||
return new IsoValue<String>(type, new String(buf, pos, length, getCharacterEncoding()), length, null);
|
||||
} else {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
IsoValue<?> v = new IsoValue(type, custom.decodeField(new String(buf, pos, length, getCharacterEncoding())), length, custom);
|
||||
if (v.getValue() == null) {
|
||||
return new IsoValue<String>(type, new String(buf, pos, length, getCharacterEncoding()), length, null);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
throw new ParseException(String.format(
|
||||
"Insufficient data for bin %s field %d of length %d, pos %d",
|
||||
type, field, length, pos), pos);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,23 +37,32 @@ public class AmountParseInfo extends FieldParseInfo {
|
||||
super(IsoType.AMOUNT, 12);
|
||||
}
|
||||
|
||||
public IsoValue<BigDecimal> parse(byte[] buf, int pos, CustomField<?> custom)
|
||||
public IsoValue<BigDecimal> 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<BigDecimal>(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 %d, pos %d", field, pos), pos);
|
||||
}
|
||||
}
|
||||
|
||||
public IsoValue<BigDecimal> parseBinary(byte[] buf, int pos, CustomField<?> custom) throws ParseException {
|
||||
public IsoValue<BigDecimal> 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;
|
||||
@@ -67,7 +76,11 @@ public class AmountParseInfo extends FieldParseInfo {
|
||||
try {
|
||||
return new IsoValue<BigDecimal>(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 %d, pos %d", field, pos), pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<byte[]>(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<byte[]>(type, _v, length, null);
|
||||
}
|
||||
|
||||
@@ -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 <T extends IsoMessage> MessageFactory<T> 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<T>();
|
||||
} 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 <T extends IsoMessage> MessageFactory<T> createFromClasspathConfig(String path) throws IOException {
|
||||
InputStream ins = MessageFactory.class.getClassLoader().getResourceAsStream(path);
|
||||
MessageFactory mfact = new MessageFactory();
|
||||
MessageFactory<T> mfact = new MessageFactory<T>();
|
||||
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 <T extends IsoMessage> MessageFactory<T> createFromUrl(URL url) throws IOException {
|
||||
MessageFactory<T> mfact = new MessageFactory<T>();
|
||||
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 <T extends IsoMessage> void parse(
|
||||
MessageFactory<T> mfact, InputStream stream) throws IOException {
|
||||
final DocumentBuilderFactory docfact = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docb = null;
|
||||
Document doc = null;
|
||||
@@ -167,7 +168,7 @@ public class ConfigParser {
|
||||
CustomField<Object> _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 <T extends IsoMessage> void configureFromDefault(
|
||||
MessageFactory<T> 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 <T extends IsoMessage> void configureFromUrl(
|
||||
MessageFactory<T> 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 <T extends IsoMessage> void configureFromClasspathConfig(
|
||||
MessageFactory<T> mfact, String path) throws IOException {
|
||||
InputStream ins = MessageFactory.class.getClassLoader().getResourceAsStream(path);
|
||||
if (ins != null) {
|
||||
log.debug("ISO8583 Parsing config from classpath file {}", path);
|
||||
|
||||
@@ -42,13 +42,16 @@ public class Date10ParseInfo extends FieldParseInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsoValue<Date> parse(byte[] buf, int pos, CustomField<?> custom)
|
||||
public IsoValue<Date> 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<Date> parseBinary(byte[] buf, int pos, CustomField<?> custom) throws ParseException {
|
||||
public IsoValue<Date> 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++) {
|
||||
|
||||
@@ -37,12 +37,15 @@ public class Date4ParseInfo extends FieldParseInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsoValue<Date> parse(byte[] buf, int pos, CustomField<?> custom) throws ParseException {
|
||||
public IsoValue<Date> 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<Date> parseBinary(byte[] buf, int pos, CustomField<?> custom) throws ParseException {
|
||||
public IsoValue<Date> 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);
|
||||
}
|
||||
|
||||
@@ -37,12 +37,16 @@ public class DateExpParseInfo extends FieldParseInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsoValue<Date> parse(byte[] buf, int pos, CustomField<?> custom) throws ParseException {
|
||||
public IsoValue<Date> 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<Date> parseBinary(byte[] buf, int pos, CustomField<?> custom) throws ParseException {
|
||||
public IsoValue<Date> 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++) {
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -37,46 +37,64 @@ 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) {
|
||||
return new IsoValue<byte[]>(type, binval, binval.length, null);
|
||||
} else {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
IsoValue<?> v = new IsoValue(type, custom.decodeField(
|
||||
new String(buf, pos + 2, length)), binval.length, custom);
|
||||
if (v.getValue() == null) {
|
||||
return new IsoValue<byte[]>(type, binval, binval.length, null);
|
||||
}
|
||||
return v;
|
||||
try {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
IsoValue<?> v = new IsoValue(type, custom.decodeField(
|
||||
new String(buf, pos + 2, length)), binval.length, custom);
|
||||
if (v.getValue() == null) {
|
||||
return new IsoValue<byte[]>(type, binval, binval.length, null);
|
||||
}
|
||||
return v;
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
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);
|
||||
@@ -84,7 +102,7 @@ public class LlbinParseInfo extends FieldParseInfo {
|
||||
return new IsoValue<byte[]>(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<byte[]>(type, _v, null);
|
||||
}
|
||||
|
||||
@@ -37,49 +37,67 @@ 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) {
|
||||
return new IsoValue<byte[]>(type, binval, binval.length, null);
|
||||
} else {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
IsoValue<?> v = new IsoValue(type, custom.decodeField(
|
||||
length == 0 ? "" : new String(buf, pos + 3, length)), length, custom);
|
||||
if (v.getValue() == null) {
|
||||
//problems decoding? return the string
|
||||
return new IsoValue<byte[]>(type, binval, binval.length, null);
|
||||
}
|
||||
return v;
|
||||
try {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
IsoValue<?> v = new IsoValue(type, custom.decodeField(
|
||||
length == 0 ? "" : new String(buf, pos + 3, length)), length, custom);
|
||||
if (v.getValue() == null) {
|
||||
//problems decoding? return the string
|
||||
return new IsoValue<byte[]>(type, binval, binval.length, null);
|
||||
}
|
||||
return v;
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
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);
|
||||
@@ -87,7 +105,7 @@ public class LllbinParseInfo extends FieldParseInfo {
|
||||
return new IsoValue<byte[]>(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<byte[]>(type, _v, null);
|
||||
}
|
||||
|
||||
@@ -36,24 +36,35 @@ 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 = length == 0 ? "" : new String(buf, pos + 3, length, getCharacterEncoding());
|
||||
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, 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,
|
||||
//and then cut it to the specified length.
|
||||
@@ -69,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<String>(type, new String(buf, pos + 2, length, getCharacterEncoding()), null);
|
||||
|
||||
@@ -35,20 +35,29 @@ 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 = length == 0 ? "" : new String(buf, pos + 2, length, getCharacterEncoding());
|
||||
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, 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,
|
||||
//and then cut it to the specified length.
|
||||
@@ -67,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<String>(type, new String(buf, pos + 1, length, getCharacterEncoding()), null);
|
||||
|
||||
@@ -35,12 +35,16 @@ public class NumericParseInfo extends AlphaNumericFieldParseInfo {
|
||||
super(IsoType.NUMERIC, len);
|
||||
}
|
||||
|
||||
public IsoValue<Number> parseBinary(byte[] buf, int pos, CustomField<?> custom) throws ParseException {
|
||||
public IsoValue<Number> 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) {
|
||||
@@ -57,10 +61,16 @@ public class NumericParseInfo extends AlphaNumericFieldParseInfo {
|
||||
//Use a BigInteger
|
||||
char[] digits = new char[length];
|
||||
int start = 0;
|
||||
for (int i = pos; i < pos + (length / 2) + (length % 2); i++) {
|
||||
digits[start++] = (char)(((buf[i] & 0xf0) >> 4) + 48);
|
||||
digits[start++] = (char)((buf[i] & 0x0f) + 48);
|
||||
}
|
||||
try {
|
||||
for (int i = pos; i < pos + (length / 2) + (length % 2); i++) {
|
||||
digits[start++] = (char)(((buf[i] & 0xf0) >> 4) + 48);
|
||||
digits[start++] = (char)((buf[i] & 0x0f) + 48);
|
||||
}
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
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<Number>(IsoType.NUMERIC, new BigInteger(new String(digits)), length, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,15 @@ public class TimeParseInfo extends FieldParseInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsoValue<Date> parse(byte[] buf, int pos, CustomField<?> custom) throws ParseException {
|
||||
public IsoValue<Date> 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<Date> parseBinary(byte[] buf, int pos, CustomField<?> custom) throws ParseException {
|
||||
public IsoValue<Date> 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;
|
||||
|
||||
@@ -5,17 +5,18 @@ public class HexCodec {
|
||||
|
||||
static final char[] HEX = new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
public static String hexEncode(byte[] buffer) {
|
||||
public static String hexEncode(byte[] buffer, int start, int length) {
|
||||
if (buffer.length == 0) {
|
||||
return "";
|
||||
}
|
||||
int holder = 0;
|
||||
char[] chars = new char[buffer.length * 2];
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
char[] chars = new char[length * 2];
|
||||
int pos = -1;
|
||||
for (int i = start; i < start+length; i++) {
|
||||
holder = (buffer[i] & 0xf0) >> 4;
|
||||
chars[i * 2] = HEX[holder];
|
||||
chars[++pos * 2] = HEX[holder];
|
||||
holder = buffer[i] & 0x0f;
|
||||
chars[(i * 2) + 1] = HEX[holder];
|
||||
chars[(pos * 2) + 1] = HEX[holder];
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
<item name="Download" href="http://sourceforge.net/projects/j8583/files/j8583/"/>
|
||||
</links>
|
||||
|
||||
<menu name="j8583 1.5.6">
|
||||
<menu name="j8583 1.5.7">
|
||||
<item name="Introduction" href="index.html"/>
|
||||
<item name="API docs" href="javadoc/index.html" />
|
||||
<item name="Beginner's Guide" href="guide.html"/>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<item name="Descargar" href="http://sourceforge.net/projects/j8583/files/j8583/"/>
|
||||
</links>
|
||||
|
||||
<menu name="j8583 1.5.6">
|
||||
<menu name="j8583 1.5.7">
|
||||
<item name="Introducción" href="index.html"/>
|
||||
<item name="Documentación API" href="../javadoc/index.html" />
|
||||
<item name="Guía de inicio" href="guide.html"/>
|
||||
|
||||
@@ -4,10 +4,8 @@ import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.ParseException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -40,27 +38,25 @@ public class TestBinaries {
|
||||
byte[] buf = (byte[])m.getObjectValue(41);
|
||||
byte[] exp = new byte[]{ (byte)0xab, (byte)0xcd, (byte)0xef, 0, 0, 0, 0, 0};
|
||||
Assert.assertEquals("Field 41 wrong length", 8, buf.length);
|
||||
Assert.assertTrue("Field 41 wrong value", Arrays.equals(exp, buf));
|
||||
Assert.assertArrayEquals("Field 41 wrong value", exp, buf);
|
||||
buf = (byte[])m.getObjectValue(42);
|
||||
exp = new byte[]{ (byte)0x0a, (byte)0xbc, (byte)0xde, 0 };
|
||||
Assert.assertEquals("field 42 wrong length", 4, buf.length);
|
||||
Assert.assertTrue("Field 42 wrong value", Arrays.equals(exp, buf));
|
||||
Assert.assertArrayEquals("Field 42 wrong value", exp, buf);
|
||||
Assert.assertTrue(((String)m.getObjectValue(43)).startsWith("Field of length 40"));
|
||||
buf = (byte[])m.getObjectValue(62);
|
||||
exp = new byte[]{ 1, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef,
|
||||
1, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef };
|
||||
Assert.assertEquals(16, buf.length);
|
||||
Assert.assertTrue(Arrays.equals(exp, buf));
|
||||
0x62, 1, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xab, (byte)0xcd };
|
||||
Assert.assertArrayEquals(exp, buf);
|
||||
buf = (byte[])m.getObjectValue(64);
|
||||
Assert.assertEquals(16, buf.length);
|
||||
Assert.assertTrue(Arrays.equals(exp, buf));
|
||||
exp[8] = 0x64;
|
||||
Assert.assertArrayEquals(exp, buf);
|
||||
buf = (byte[])m.getObjectValue(63);
|
||||
exp = new byte[]{ 0, (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78, (byte)0x9a };
|
||||
Assert.assertEquals(6, buf.length);
|
||||
Assert.assertTrue(Arrays.equals(exp, buf));
|
||||
exp = new byte[]{ 0, (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78, (byte)0x63 };
|
||||
Assert.assertArrayEquals(exp, buf);
|
||||
buf = (byte[])m.getObjectValue(65);
|
||||
Assert.assertEquals(6, buf.length);
|
||||
Assert.assertTrue(Arrays.equals(exp, buf));
|
||||
exp[5] = 0x65;
|
||||
Assert.assertArrayEquals(exp, buf);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -68,12 +64,16 @@ public class TestBinaries {
|
||||
//Create a message with both factories
|
||||
IsoMessage ascii = mfactAscii.newMessage(0x600);
|
||||
IsoMessage bin = mfactBin.newMessage(0x600);
|
||||
Assert.assertFalse(ascii.isBinary() || ascii.isBinaryBitmap());
|
||||
Assert.assertTrue(bin.isBinary());
|
||||
//HEXencode the binary message, headers should be similar to the ASCII version
|
||||
String hexBin = HexCodec.hexEncode(bin.writeData());
|
||||
final byte[] _v = bin.writeData();
|
||||
String hexBin = HexCodec.hexEncode(_v, 0, _v.length);
|
||||
String hexAscii = new String(ascii.writeData()).toUpperCase();
|
||||
Assert.assertEquals("0600", hexBin.substring(0, 4));
|
||||
//Should be the same up to the field 42 (first 80 chars)
|
||||
Assert.assertEquals(hexAscii.substring(0, 88), hexBin.substring(0, 88));
|
||||
Assert.assertEquals(ascii.getObjectValue(43), new String(_v, 44, 40).trim());
|
||||
//Parse both messages
|
||||
byte[] asciiBuf = ascii.writeData();
|
||||
IsoMessage ascii2 = mfactAscii.parseMessage(asciiBuf, 0);
|
||||
@@ -98,7 +98,7 @@ public class TestBinaries {
|
||||
byte[] sub1 = new byte[8];
|
||||
System.arraycopy(data1, 16, sub1, 0, 8);
|
||||
String sub2 = new String(data2, 16, 16, iso2.getCharacterEncoding());
|
||||
Assert.assertEquals(sub2, HexCodec.hexEncode(sub1));
|
||||
Assert.assertEquals(sub2, HexCodec.hexEncode(sub1, 0, sub1.length));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import com.solab.iso8583.IsoMessage;
|
||||
import org.junit.*;
|
||||
|
||||
import com.solab.iso8583.IsoType;
|
||||
@@ -20,11 +21,11 @@ import com.solab.iso8583.parse.Date4ParseInfo;
|
||||
*/
|
||||
public class TestDates {
|
||||
|
||||
private MessageFactory mf;
|
||||
private MessageFactory<IsoMessage> mf;
|
||||
|
||||
@Before
|
||||
public void init() throws IOException {
|
||||
mf = new MessageFactory();
|
||||
mf = new MessageFactory<IsoMessage>();
|
||||
mf.setCharacterEncoding("UTF-8");
|
||||
mf.setCustomField(48, new CustomField48());
|
||||
mf.setConfigPath("config.xml");
|
||||
@@ -39,12 +40,12 @@ public class TestDates {
|
||||
today.set(GregorianCalendar.SECOND,0);
|
||||
today.set(GregorianCalendar.MILLISECOND,0);
|
||||
byte[] buf = IsoType.DATE4.format(soon).getBytes();
|
||||
IsoValue<Date> comp = new Date4ParseInfo().parse(buf, 0, null);
|
||||
IsoValue<Date> comp = new Date4ParseInfo().parse(0, buf, 0, null);
|
||||
Assert.assertEquals(comp.getValue(), today.getTime());
|
||||
//Now with the binary
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
comp.write(bout, true);
|
||||
IsoValue<Date> bin = new Date4ParseInfo().parseBinary(bout.toByteArray(), 0, null);
|
||||
IsoValue<Date> bin = new Date4ParseInfo().parseBinary(0, bout.toByteArray(), 0, null);
|
||||
Assert.assertEquals(comp.getValue().getTime(), bin.getValue().getTime());
|
||||
}
|
||||
|
||||
@@ -52,12 +53,12 @@ public class TestDates {
|
||||
public void testDate10FutureTolerance() throws ParseException, IOException {
|
||||
Date soon = new Date(System.currentTimeMillis() + 50000);
|
||||
byte[] buf = IsoType.DATE10.format(soon).getBytes();
|
||||
IsoValue<Date> comp = new Date10ParseInfo().parse(buf, 0, null);
|
||||
IsoValue<Date> comp = new Date10ParseInfo().parse(0, buf, 0, null);
|
||||
assert comp.getValue().after(new Date());
|
||||
//Now with the binary
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
comp.write(bout, true);
|
||||
IsoValue<Date> bin = new Date10ParseInfo().parseBinary(bout.toByteArray(), 0, null);
|
||||
IsoValue<Date> bin = new Date10ParseInfo().parseBinary(0, bout.toByteArray(), 0, null);
|
||||
Assert.assertEquals(comp.getValue().getTime(), bin.getValue().getTime());
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ public class TestHexCodec {
|
||||
public void encodeDecode(String hex) {
|
||||
byte[] buf = HexCodec.hexDecode(hex);
|
||||
Assert.assertEquals((hex.length() / 2) + (hex.length() % 2), buf.length);
|
||||
String reenc = HexCodec.hexEncode(buf);
|
||||
String reenc = HexCodec.hexEncode(buf, 0, buf.length);
|
||||
if (reenc.startsWith("0") && !hex.startsWith("0")) {
|
||||
Assert.assertEquals(reenc.substring(1), hex);
|
||||
} else {
|
||||
@@ -41,4 +41,10 @@ public class TestHexCodec {
|
||||
encodeDecode("ABC");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartial() {
|
||||
Assert.assertEquals("FF01", HexCodec.hexEncode(new byte[]{0, (byte)0xff, 1, 2, 3, 4},
|
||||
1, 2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ import com.solab.iso8583.MessageFactory;
|
||||
*/
|
||||
public class TestIsoMessage {
|
||||
|
||||
private MessageFactory mf;
|
||||
private MessageFactory<IsoMessage> mf;
|
||||
|
||||
@Before
|
||||
public void init() throws IOException {
|
||||
mf = new MessageFactory();
|
||||
mf = new MessageFactory<IsoMessage>();
|
||||
mf.setCharacterEncoding("UTF-8");
|
||||
mf.setCustomField(48, new CustomField48());
|
||||
mf.setConfigPath("config.xml");
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package j8583;
|
||||
|
||||
import com.solab.iso8583.IsoMessage;
|
||||
import com.solab.iso8583.MessageFactory;
|
||||
import com.solab.iso8583.parse.ConfigParser;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* Tests for chochos/j8583#4.
|
||||
*
|
||||
* @author Enrique Zamudio
|
||||
* Date: 18/01/13 10:13
|
||||
*/
|
||||
public class TestIssue4 {
|
||||
|
||||
@Test
|
||||
public void testTextBitmap() throws IOException, ParseException {
|
||||
MessageFactory<IsoMessage> tmf = new MessageFactory<IsoMessage>();
|
||||
ConfigParser.configureFromClasspathConfig(tmf, "issue4.xml");
|
||||
IsoMessage tm = tmf.newMessage(0x800);
|
||||
final ByteBuffer bb = tm.writeToBuffer(2);
|
||||
Assert.assertEquals("Wrong message length for new TXT",
|
||||
70, bb.array().length);
|
||||
Assert.assertEquals(68, bb.getShort());
|
||||
|
||||
MessageFactory<IsoMessage> tmfp = new MessageFactory<IsoMessage>();
|
||||
ConfigParser.configureFromClasspathConfig(tmfp, "issue4.xml");
|
||||
byte[] buf2 = new byte[bb.remaining()];
|
||||
bb.get(buf2);
|
||||
tm = tmfp.parseMessage(buf2, 0);
|
||||
final ByteBuffer bbp = tm.writeToBuffer(2);
|
||||
Assert.assertArrayEquals("Parsed-reencoded TXT differs from original",
|
||||
bb.array(), bbp.array());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBinaryBitmap() throws IOException, ParseException {
|
||||
MessageFactory<IsoMessage> mf = new MessageFactory<IsoMessage>();
|
||||
ConfigParser.configureFromClasspathConfig(mf, "issue4.xml");
|
||||
IsoMessage bm = mf.getMessageTemplate(0x800);
|
||||
bm.setBinaryBitmap(true);
|
||||
final ByteBuffer bb = bm.writeToBuffer(2);
|
||||
Assert.assertEquals("Wrong message length for new BIN", 62, bb.array().length);
|
||||
Assert.assertEquals(60, bb.getShort());
|
||||
|
||||
MessageFactory<IsoMessage> mfp = new MessageFactory<IsoMessage>();
|
||||
mfp.setUseBinaryBitmap(true);
|
||||
ConfigParser.configureFromClasspathConfig(mfp, "issue4.xml");
|
||||
byte[] buf2 = new byte[bb.remaining()];
|
||||
bb.get(buf2);
|
||||
bm = mfp.parseMessage(buf2, 0);
|
||||
Assert.assertTrue("Parsed message should have binary bitmap flag set",
|
||||
bm.isBinaryBitmap());
|
||||
Assert.assertFalse(bm.isBinary());
|
||||
final ByteBuffer bbp = bm.writeToBuffer(2);
|
||||
Assert.assertArrayEquals("Parsed-reencoded BIN differs from original",
|
||||
bb.array(), bbp.array());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import com.solab.iso8583.IsoMessage;
|
||||
import com.solab.iso8583.IsoValue;
|
||||
import com.solab.iso8583.parse.NumericParseInfo;
|
||||
import junit.framework.Assert;
|
||||
@@ -18,11 +19,11 @@ import com.solab.iso8583.MessageFactory;
|
||||
*/
|
||||
public class TestParsing {
|
||||
|
||||
private MessageFactory mf;
|
||||
private MessageFactory<IsoMessage> mf;
|
||||
|
||||
@Before
|
||||
public void init() throws IOException {
|
||||
mf = new MessageFactory();
|
||||
mf = new MessageFactory<IsoMessage>();
|
||||
mf.setCharacterEncoding("UTF-8");
|
||||
mf.setCustomField(48, new CustomField48());
|
||||
mf.setConfigPath("config.xml");
|
||||
@@ -102,7 +103,7 @@ public class TestParsing {
|
||||
@Test
|
||||
public void testBinaryNumberParsing() throws ParseException {
|
||||
NumericParseInfo npi = new NumericParseInfo(6);
|
||||
IsoValue<Number> val = npi.parseBinary(new byte[]{0x12, 0x34, 0x56}, 0, null);
|
||||
IsoValue<Number> val = npi.parseBinary(0, new byte[]{0x12, 0x34, 0x56}, 0, null);
|
||||
Assert.assertEquals(123456, val.getValue().intValue());
|
||||
}
|
||||
|
||||
|
||||
@@ -43,10 +43,10 @@
|
||||
<field num="41" type="BINARY" length="8">abcdef</field>
|
||||
<field num="42" type="BINARY" length="4">abcde</field>
|
||||
<field num="43" type="ALPHA" length="40">Field of length 40</field>
|
||||
<field num="62" type="LLBIN">0123456789abcdef0123456789abcdef</field>
|
||||
<field num="63" type="LLBIN">0123456789a</field>
|
||||
<field num="64" type="LLLBIN">0123456789abcdef0123456789abcdef</field>
|
||||
<field num="65" type="LLLBIN">0123456789a</field>
|
||||
<field num="62" type="LLBIN">0123456789abcdef620123456789abcd</field>
|
||||
<field num="63" type="LLBIN">01234567863</field>
|
||||
<field num="64" type="LLLBIN">0123456789abcdef640123456789abcd</field>
|
||||
<field num="65" type="LLLBIN">01234567865</field>
|
||||
<field num="102" type="LLLVAR">Field of type LLLVAR</field>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE j8583-config PUBLIC "-//J8583//DTD CONFIG 1.0//EN"
|
||||
"http://j8583.sourceforge.net/j8583.dtd">
|
||||
<j8583-config>
|
||||
<template type="0800">
|
||||
<field num="3" type="NUMERIC" length="6">990000</field>
|
||||
<field num="7" type="DATE10">1227120330</field>
|
||||
<field num="11" type="NUMERIC" length="6">2</field>
|
||||
<field num="24" type="NUMERIC" length="3">831</field>
|
||||
<field num="41" type="ALPHA" length="8">42001</field>
|
||||
<field num="42" type="ALPHA" length="15">420000000000001</field>
|
||||
</template>
|
||||
<parse type="0800">
|
||||
<field num="3" type="NUMERIC" length="6" />
|
||||
<field num="7" type="DATE10" />
|
||||
<field num="11" type="NUMERIC" length="6" />
|
||||
<field num="24" type="NUMERIC" length="3" />
|
||||
<field num="41" type="ALPHA" length="8" />
|
||||
<field num="42" type="ALPHA" length="15" />
|
||||
</parse>
|
||||
</j8583-config>
|
||||
@@ -0,0 +1,4 @@
|
||||
log4j.rootLogger=TRACE, A1
|
||||
log4j.appender.A1=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %C{1} - %m%n
|
||||
Reference in New Issue
Block a user