Added a new property, characterEncoding, to MessageFactory, IsoMessage, FieldParseInfo and IsoValue. This helps in parsing messages from byte buffers containing extended characters in encodings other than the default for the JVM. Tested with UTF8 on a Mac (which has default Mac OS Roman) and worked fine.
Several methods now have an additional encoding parameter (just a String, not directly a Charset), but the default is always the JVM's default encoding (taken from the property 'file.encoding'). git-svn-id: https://j8583.svn.sourceforge.net/svnroot/j8583/j8583@70 db60a039-f72e-0410-b1d2-baa000846441
This commit is contained in:
@@ -48,6 +48,7 @@ public class IsoMessage {
|
||||
private int etx = -1;
|
||||
/** Flag to enforce secondary bitmap even if empty. */
|
||||
private boolean forceb2;
|
||||
private String encoding = System.getProperty("file.encoding");
|
||||
|
||||
/** Creates a new empty message with no values set. */
|
||||
public IsoMessage() {
|
||||
@@ -66,6 +67,13 @@ public class IsoMessage {
|
||||
return forceb2;
|
||||
}
|
||||
|
||||
public void setCharacterEncoding(String value) {
|
||||
encoding = value;
|
||||
}
|
||||
public String getCharacterEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/** Sets the string to be sent as ISO header, that is, after the length header but before the message type.
|
||||
* This is useful in case an application needs some custom data in the ISO header of each message (very rare). */
|
||||
public void setIsoHeader(String value) {
|
||||
@@ -119,6 +127,7 @@ public class IsoMessage {
|
||||
if (index < 2 || index > 128) {
|
||||
throw new IndexOutOfBoundsException("Field index must be between 2 and 128");
|
||||
}
|
||||
field.setCharacterEncoding(encoding);
|
||||
fields[index] = field;
|
||||
}
|
||||
|
||||
@@ -153,6 +162,7 @@ public class IsoMessage {
|
||||
} else {
|
||||
v = new IsoValue(t, value, encoder);
|
||||
}
|
||||
v.setCharacterEncoding(encoding);
|
||||
fields[index] = v;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ public class IsoValue<T> implements Cloneable {
|
||||
private T value;
|
||||
private CustomField<T> encoder;
|
||||
private int length;
|
||||
private String encoding;
|
||||
|
||||
public IsoValue(IsoType t, T value) {
|
||||
this(t, value, null);
|
||||
@@ -156,6 +157,13 @@ public class IsoValue<T> implements Cloneable {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setCharacterEncoding(String value) {
|
||||
encoding = value;
|
||||
}
|
||||
public String getCharacterEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/** Returns the formatted value as a String. The formatting depends on the type of the
|
||||
* receiver. */
|
||||
public String toString() {
|
||||
@@ -302,8 +310,7 @@ public class IsoValue<T> implements Cloneable {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//Just write the value as text
|
||||
outs.write(toString().getBytes());
|
||||
outs.write(encoding == null ? toString().getBytes() : toString().getBytes(encoding));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
package com.solab.iso8583;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
@@ -72,6 +73,25 @@ public class MessageFactory {
|
||||
/** Flag to specify if missing fields should be ignored as long as they're at the end of the message. */
|
||||
private boolean ignoreLast;
|
||||
private boolean forceb2;
|
||||
private String encoding = System.getProperty("file.encoding");
|
||||
|
||||
/** Sets the character encoding used for parsing ALPHA, LLVAR and LLLVAR fields. */
|
||||
public void setCharacterEncoding(String value) {
|
||||
encoding = value;
|
||||
if (parseMap.size() > 0) {
|
||||
for (Map<Integer, FieldParseInfo> pt : parseMap.values()) {
|
||||
for (FieldParseInfo fpi : pt.values()) {
|
||||
fpi.setCharacterEncoding(encoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the encoding used to parse ALPHA, LLVAR and LLLVAR fields. The default is the file.encoding
|
||||
* system property. */
|
||||
public String getCharacterEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/** Sets or clears the flag to pass to new messages, to include a secondary bitmap even if it's not needed. */
|
||||
public void setForceSecondaryBitmap(boolean flag) {
|
||||
@@ -151,6 +171,7 @@ public class MessageFactory {
|
||||
m.setEtx(etx);
|
||||
m.setBinary(useBinary);
|
||||
m.setForceSecondaryBitmap(forceb2);
|
||||
m.setCharacterEncoding(encoding);
|
||||
|
||||
//Copy the values from the template
|
||||
IsoMessage templ = typeTemplates.get(type);
|
||||
@@ -176,6 +197,7 @@ public class MessageFactory {
|
||||
* @param request An ISO8583 message with a request type (ending in 00). */
|
||||
public IsoMessage createResponse(IsoMessage request) {
|
||||
IsoMessage resp = new IsoMessage(isoHeaders.get(request.getType() + 16));
|
||||
resp.setCharacterEncoding(request.getCharacterEncoding());
|
||||
resp.setBinary(request.isBinary());
|
||||
resp.setType(request.getType() + 16);
|
||||
resp.setEtx(etx);
|
||||
@@ -206,9 +228,10 @@ public class MessageFactory {
|
||||
* @param buf The byte buffer containing the message. Must not include the length header.
|
||||
* @param isoHeaderLength The expected length of the ISO header, after which the message type
|
||||
* and the rest of the message must come. */
|
||||
public IsoMessage parseMessage(byte[] buf, int isoHeaderLength) throws ParseException {
|
||||
public IsoMessage parseMessage(byte[] buf, int isoHeaderLength)
|
||||
throws ParseException, UnsupportedEncodingException {
|
||||
IsoMessage m = new IsoMessage(isoHeaderLength > 0 ? new String(buf, 0, isoHeaderLength) : null);
|
||||
//TODO Not really sure if binary support really works, unit tests pending...
|
||||
m.setCharacterEncoding(encoding);
|
||||
int type = 0;
|
||||
if (useBinary) {
|
||||
type = ((buf[isoHeaderLength] & 0xff) << 8) | (buf[isoHeaderLength + 1] & 0xff);
|
||||
@@ -351,11 +374,8 @@ public class MessageFactory {
|
||||
} else {
|
||||
IsoValue<?> val = fpi.parse(buf, pos, getCustomField(i));
|
||||
m.setField(i, val);
|
||||
pos += val.getLength();
|
||||
if (val.getType() == IsoType.LLBIN || val.getType() == IsoType.LLLBIN || val.getType() == IsoType.BINARY) {
|
||||
//Binary types in ASCII are twice as long as they say they are (because of the hex encoding)
|
||||
pos += val.getLength();
|
||||
}
|
||||
//To get the correct next position, we need to get the number of bytes, not chars
|
||||
pos += val.toString().getBytes(fpi.getCharacterEncoding()).length;
|
||||
if (val.getType() == IsoType.LLVAR || val.getType() == IsoType.LLBIN) {
|
||||
pos += 2;
|
||||
} else if (val.getType() == IsoType.LLLVAR || val.getType() == IsoType.LLLBIN) {
|
||||
|
||||
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
package com.solab.iso8583.parse;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import com.solab.iso8583.CustomField;
|
||||
@@ -34,7 +35,7 @@ public abstract class AlphaNumericFieldParseInfo extends FieldParseInfo {
|
||||
super(t, len);
|
||||
}
|
||||
|
||||
public <T extends Object> IsoValue<?> parse(byte[] buf, int pos, CustomField<T> custom) throws ParseException {
|
||||
public <T extends Object> IsoValue<?> parse(byte[] buf, int pos, CustomField<T> custom) throws ParseException, UnsupportedEncodingException {
|
||||
if (pos < 0) {
|
||||
throw new ParseException(String.format("Invalid position %d", pos), pos);
|
||||
}
|
||||
@@ -42,12 +43,16 @@ public abstract class AlphaNumericFieldParseInfo extends FieldParseInfo {
|
||||
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, new String(buf, pos, length), length, null);
|
||||
return new IsoValue<String>(type, _v, length, null);
|
||||
} else {
|
||||
IsoValue<T> v = new IsoValue<T>(type, custom.decodeField(new String(buf, pos, length)), length, custom);
|
||||
IsoValue<T> v = new IsoValue<T>(type, custom.decodeField(_v), length, custom);
|
||||
if (v.getValue() == null) {
|
||||
return new IsoValue<String>(type, new String(buf, pos, length), length, null);
|
||||
return new IsoValue<String>(type, _v, length, null);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
package com.solab.iso8583.parse;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import com.solab.iso8583.CustomField;
|
||||
@@ -34,13 +35,14 @@ public class AlphaParseInfo extends AlphaNumericFieldParseInfo {
|
||||
super(IsoType.ALPHA, len);
|
||||
}
|
||||
|
||||
public <T extends Object> IsoValue<?> parseBinary(byte[] buf, int pos, CustomField<T> custom) throws ParseException {
|
||||
public <T extends Object> IsoValue<?> parseBinary(byte[] buf, int pos, CustomField<T> custom)
|
||||
throws ParseException, UnsupportedEncodingException {
|
||||
if (custom == null) {
|
||||
return new IsoValue<String>(type, new String(buf, pos, length), length, null);
|
||||
return new IsoValue<String>(type, new String(buf, pos, length, getCharacterEncoding()), length, null);
|
||||
} else {
|
||||
IsoValue<T> v = new IsoValue<T>(type, custom.decodeField(new String(buf, pos, length)), length, custom);
|
||||
IsoValue<T> v = new IsoValue<T>(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), length, null);
|
||||
return new IsoValue<String>(type, new String(buf, pos, length, getCharacterEncoding()), length, null);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
package com.solab.iso8583.parse;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import com.solab.iso8583.CustomField;
|
||||
@@ -38,7 +39,7 @@ public class BinaryParseInfo extends FieldParseInfo {
|
||||
|
||||
@Override
|
||||
public <T> IsoValue<?> parse(byte[] buf, int pos, CustomField<T> custom)
|
||||
throws ParseException {
|
||||
throws ParseException, UnsupportedEncodingException {
|
||||
if (pos < 0) {
|
||||
throw new ParseException(String.format("Invalid position %d", pos), pos);
|
||||
}
|
||||
@@ -50,7 +51,7 @@ public class BinaryParseInfo extends FieldParseInfo {
|
||||
if (custom == null) {
|
||||
return new IsoValue<byte[]>(type, binval, binval.length, null);
|
||||
} else {
|
||||
IsoValue<T> v = new IsoValue<T>(type, custom.decodeField(new String(buf, pos, length*2)), length, custom);
|
||||
IsoValue<T> v = new IsoValue<T>(type, custom.decodeField(new String(buf, pos, length*2, getCharacterEncoding())), length, custom);
|
||||
if (v.getValue() == null) {
|
||||
return new IsoValue<byte[]>(type, binval, binval.length, null);
|
||||
}
|
||||
|
||||
@@ -139,6 +139,7 @@ public class ConfigParser {
|
||||
NodeList fields = elem.getElementsByTagName("field");
|
||||
IsoMessage m = new IsoMessage();
|
||||
m.setType(type);
|
||||
m.setCharacterEncoding(mfact.getCharacterEncoding());
|
||||
for (int j = 0; j < fields.getLength(); j++) {
|
||||
Element f = (Element)fields.item(j);
|
||||
int num = Integer.parseInt(f.getAttribute("num"));
|
||||
@@ -172,7 +173,7 @@ public class ConfigParser {
|
||||
if (f.getAttribute("length").length() > 0) {
|
||||
length = Integer.parseInt(f.getAttribute("length"));
|
||||
}
|
||||
parseMap.put(num, FieldParseInfo.getInstance(itype, length));
|
||||
parseMap.put(num, FieldParseInfo.getInstance(itype, length, mfact.getCharacterEncoding()));
|
||||
}
|
||||
mfact.setParseMap(type, parseMap);
|
||||
}
|
||||
@@ -189,6 +190,17 @@ 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 {
|
||||
InputStream stream = url.openStream();
|
||||
try {
|
||||
parse(mfact, stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
|
||||
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
package com.solab.iso8583.parse;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import com.solab.iso8583.CustomField;
|
||||
@@ -32,6 +33,7 @@ public abstract class FieldParseInfo {
|
||||
|
||||
protected IsoType type;
|
||||
protected int length;
|
||||
private String encoding = System.getProperty("file.encoding");
|
||||
|
||||
/** Creates a new instance that parses a value of the specified type, with the specified length.
|
||||
* The length is only useful for ALPHA and NUMERIC types.
|
||||
@@ -45,6 +47,13 @@ public abstract class FieldParseInfo {
|
||||
length = len;
|
||||
}
|
||||
|
||||
public void setCharacterEncoding(String value) {
|
||||
encoding = value;
|
||||
}
|
||||
public String getCharacterEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/** Returns the specified length for the data to be parsed. */
|
||||
public int getLength() {
|
||||
return length;
|
||||
@@ -57,40 +66,47 @@ public abstract class FieldParseInfo {
|
||||
|
||||
/** Parses the character data from the buffer and returns the
|
||||
* IsoValue with the correct data type in it. */
|
||||
public abstract <T extends Object> IsoValue<?> parse(byte[] buf, int pos, CustomField<T> custom) throws ParseException;
|
||||
public abstract <T extends Object> IsoValue<?> parse(byte[] buf, int pos, CustomField<T> custom)
|
||||
throws ParseException, UnsupportedEncodingException;
|
||||
|
||||
/** Parses binary data from the buffer, creating and returning an IsoValue of the configured
|
||||
* type and length. */
|
||||
public abstract <T extends Object> IsoValue<?> parseBinary(byte[] buf, int pos, CustomField<T> custom) throws ParseException;
|
||||
public abstract <T extends Object> IsoValue<?> parseBinary(byte[] buf, int pos, CustomField<T> custom)
|
||||
throws ParseException, UnsupportedEncodingException;
|
||||
|
||||
/** Returns a new FieldParseInfo instance that can parse the specified type. */
|
||||
public static FieldParseInfo getInstance(IsoType t, int len) {
|
||||
public static FieldParseInfo getInstance(IsoType t, int len, String encoding) {
|
||||
FieldParseInfo fpi = null;
|
||||
if (t == IsoType.ALPHA) {
|
||||
return new AlphaParseInfo(len);
|
||||
fpi = new AlphaParseInfo(len);
|
||||
} else if (t == IsoType.AMOUNT) {
|
||||
return new AmountParseInfo();
|
||||
fpi = new AmountParseInfo();
|
||||
} else if (t == IsoType.BINARY) {
|
||||
return new BinaryParseInfo(len);
|
||||
fpi = new BinaryParseInfo(len);
|
||||
} else if (t == IsoType.DATE10) {
|
||||
return new Date10ParseInfo();
|
||||
fpi = new Date10ParseInfo();
|
||||
} else if (t == IsoType.DATE4) {
|
||||
return new Date4ParseInfo();
|
||||
fpi = new Date4ParseInfo();
|
||||
} else if (t == IsoType.DATE_EXP) {
|
||||
return new DateExpParseInfo();
|
||||
fpi = new DateExpParseInfo();
|
||||
} else if (t == IsoType.LLBIN) {
|
||||
return new LlbinParseInfo();
|
||||
fpi = new LlbinParseInfo();
|
||||
} else if (t == IsoType.LLLBIN) {
|
||||
return new LllbinParseInfo();
|
||||
fpi = new LllbinParseInfo();
|
||||
} else if (t == IsoType.LLLVAR) {
|
||||
return new LllvarParseInfo();
|
||||
fpi = new LllvarParseInfo();
|
||||
} else if (t == IsoType.LLVAR) {
|
||||
return new LlvarParseInfo();
|
||||
fpi = new LlvarParseInfo();
|
||||
} else if (t == IsoType.NUMERIC) {
|
||||
return new NumericParseInfo(len);
|
||||
fpi = new NumericParseInfo(len);
|
||||
} else if (t == IsoType.TIME) {
|
||||
return new TimeParseInfo();
|
||||
fpi = new TimeParseInfo();
|
||||
}
|
||||
throw new IllegalArgumentException(String.format("Cannot parse type %s", t));
|
||||
if (fpi == null) {
|
||||
throw new IllegalArgumentException(String.format("Cannot parse type %s", t));
|
||||
}
|
||||
fpi.setCharacterEncoding(encoding);
|
||||
return fpi;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class LlbinParseInfo extends FieldParseInfo {
|
||||
throw new ParseException(String.format("Invalid LLBIN length %d pos %d", length, pos), pos);
|
||||
}
|
||||
if (pos+2 > buf.length || length+pos+2 > buf.length) {
|
||||
throw new ParseException(String.format("Insufficient data for LLBIN field, pos %d", pos), pos);
|
||||
throw new ParseException(String.format("Insufficient data for LLBIN field, pos %d (LEN states '%s')", 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) {
|
||||
|
||||
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
package com.solab.iso8583.parse;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import com.solab.iso8583.CustomField;
|
||||
@@ -35,7 +36,8 @@ public class LllvarParseInfo extends FieldParseInfo {
|
||||
super(IsoType.LLLVAR, 0);
|
||||
}
|
||||
|
||||
public <T extends Object> IsoValue<?> parse(byte[] buf, int pos, CustomField<T> custom) throws ParseException {
|
||||
public <T extends Object> IsoValue<?> parse(byte[] buf, int pos, CustomField<T> custom)
|
||||
throws ParseException, UnsupportedEncodingException {
|
||||
if (pos < 0) {
|
||||
throw new ParseException(String.format("Invalid position %d", pos), pos);
|
||||
}
|
||||
@@ -50,7 +52,13 @@ public class LllvarParseInfo extends FieldParseInfo {
|
||||
if (length+pos+3 > buf.length) {
|
||||
throw new ParseException(String.format("Insufficient data for LLLVAR field, pos %d", pos), pos);
|
||||
}
|
||||
String _v = length == 0 ? "" : new String(buf, pos + 3, length);
|
||||
String _v = length == 0 ? "" : new String(buf, pos + 3, length, getCharacterEncoding());
|
||||
//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.
|
||||
if (_v.length() != length) {
|
||||
_v = new String(buf, pos + 3, buf.length-pos-3, getCharacterEncoding()).substring(0, length);
|
||||
}
|
||||
if (custom == null) {
|
||||
return new IsoValue<String>(type, _v, length, null);
|
||||
} else {
|
||||
@@ -63,7 +71,8 @@ public class LllvarParseInfo extends FieldParseInfo {
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Object> IsoValue<?> parseBinary(byte[] buf, int pos, CustomField<T> custom) throws ParseException {
|
||||
public <T extends Object> IsoValue<?> parseBinary(byte[] buf, int pos, CustomField<T> custom)
|
||||
throws ParseException, UnsupportedEncodingException {
|
||||
length = ((buf[pos] & 0x0f) * 100) + (((buf[pos + 1] & 0xf0) >> 4) * 10) + (buf[pos + 1] & 0x0f);
|
||||
if (length < 0) {
|
||||
throw new ParseException(String.format("Invalid LLLVAR length %d pos %d", length, pos), pos);
|
||||
@@ -72,11 +81,11 @@ public class LllvarParseInfo extends FieldParseInfo {
|
||||
throw new ParseException(String.format("Insufficient data for LLLVAR field, pos %d", pos), pos);
|
||||
}
|
||||
if (custom == null) {
|
||||
return new IsoValue<String>(type, new String(buf, pos + 2, length), null);
|
||||
return new IsoValue<String>(type, new String(buf, pos + 2, length, getCharacterEncoding()), null);
|
||||
} else {
|
||||
IsoValue<T> v = new IsoValue<T>(type, custom.decodeField(new String(buf, pos + 2, length)), custom);
|
||||
IsoValue<T> v = new IsoValue<T>(type, custom.decodeField(new String(buf, pos + 2, length, getCharacterEncoding())), custom);
|
||||
if (v.getValue() == null) {
|
||||
return new IsoValue<String>(type, new String(buf, pos + 2, length), null);
|
||||
return new IsoValue<String>(type, new String(buf, pos + 2, length, getCharacterEncoding()), null);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
package com.solab.iso8583.parse;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import com.solab.iso8583.CustomField;
|
||||
@@ -34,7 +35,8 @@ public class LlvarParseInfo extends FieldParseInfo {
|
||||
super(IsoType.LLVAR, 0);
|
||||
}
|
||||
|
||||
public <T extends Object> IsoValue<?> parse(byte[] buf, int pos, CustomField<T> custom) throws ParseException {
|
||||
public <T extends Object> IsoValue<?> parse(byte[] buf, int pos, CustomField<T> custom)
|
||||
throws ParseException, UnsupportedEncodingException {
|
||||
if (pos < 0) {
|
||||
throw new ParseException(String.format("Invalid position %d", pos), pos);
|
||||
}
|
||||
@@ -45,7 +47,13 @@ public class LlvarParseInfo extends FieldParseInfo {
|
||||
if (pos+2 > buf.length || length+pos+2 > buf.length) {
|
||||
throw new ParseException(String.format("Insufficient data for LLVAR field, pos %d", pos), pos);
|
||||
}
|
||||
String _v = length == 0 ? "" : new String(buf, pos + 2, length);
|
||||
String _v = length == 0 ? "" : new String(buf, pos + 2, length, getCharacterEncoding());
|
||||
//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.
|
||||
if (_v.length() != length) {
|
||||
_v = new String(buf, pos + 2, buf.length-pos-2, getCharacterEncoding()).substring(0, length);
|
||||
}
|
||||
if (custom == null) {
|
||||
return new IsoValue<String>(type, _v, length, null);
|
||||
} else {
|
||||
@@ -57,7 +65,8 @@ public class LlvarParseInfo extends FieldParseInfo {
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Object> IsoValue<?> parseBinary(byte[] buf, int pos, CustomField<T> custom) throws ParseException {
|
||||
public <T extends Object> IsoValue<?> parseBinary(byte[] buf, int pos, CustomField<T> custom)
|
||||
throws ParseException, UnsupportedEncodingException {
|
||||
|
||||
length = (((buf[pos] & 0xf0) >> 4) * 10) + (buf[pos] & 0x0f);
|
||||
if (length < 0) {
|
||||
@@ -67,11 +76,11 @@ public class LlvarParseInfo extends FieldParseInfo {
|
||||
throw new ParseException(String.format("Insufficient data for LLVAR field, pos %d", pos), pos);
|
||||
}
|
||||
if (custom == null) {
|
||||
return new IsoValue<String>(type, new String(buf, pos + 1, length), null);
|
||||
return new IsoValue<String>(type, new String(buf, pos + 1, length, getCharacterEncoding()), null);
|
||||
} else {
|
||||
IsoValue<T> v = new IsoValue<T>(type, custom.decodeField(new String(buf, pos + 1, length)), custom);
|
||||
IsoValue<T> v = new IsoValue<T>(type, custom.decodeField(new String(buf, pos + 1, length, getCharacterEncoding())), custom);
|
||||
if (v.getValue() == null) {
|
||||
return new IsoValue<String>(type, new String(buf, pos + 1, length), null);
|
||||
return new IsoValue<String>(type, new String(buf, pos + 1, length, getCharacterEncoding()), null);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package j8583;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.ParseException;
|
||||
import java.util.Arrays;
|
||||
@@ -22,9 +23,11 @@ public class TestBinaries {
|
||||
|
||||
@Before
|
||||
public void setup() throws IOException {
|
||||
mfactAscii.setCharacterEncoding("UTF-8");
|
||||
mfactAscii.setConfigPath("config.xml");
|
||||
mfactBin.setConfigPath("config.xml");
|
||||
mfactAscii.setAssignDate(true);
|
||||
mfactBin.setCharacterEncoding("UTF-8");
|
||||
mfactBin.setConfigPath("config.xml");
|
||||
mfactBin.setAssignDate(true);
|
||||
mfactBin.setUseBinaryMessages(true);
|
||||
}
|
||||
@@ -61,19 +64,19 @@ public class TestBinaries {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessages() throws ParseException {
|
||||
public void testMessages() throws ParseException, UnsupportedEncodingException {
|
||||
//Create a message with both factories
|
||||
IsoMessage ascii = mfactAscii.newMessage(0x600);
|
||||
IsoMessage bin = mfactBin.newMessage(0x600);
|
||||
//HEXencode the binary message, headers should be similar to the ASCII version
|
||||
String hexBin = HexCodec.hexEncode(bin.writeData());
|
||||
String hexAscii = new String(ascii.writeData()).toUpperCase();
|
||||
System.out.printf("bin: %s%nascii: %s%n", hexBin, hexAscii);
|
||||
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));
|
||||
//Parse both messages
|
||||
IsoMessage ascii2 = mfactAscii.parseMessage(ascii.writeData(), 0);
|
||||
byte[] asciiBuf = ascii.writeData();
|
||||
IsoMessage ascii2 = mfactAscii.parseMessage(asciiBuf, 0);
|
||||
testParsed(ascii2);
|
||||
Assert.assertEquals(ascii.getObjectValue(7).toString(), ascii2.getObjectValue(7).toString());
|
||||
IsoMessage bin2 = mfactBin.parseMessage(bin.writeData(), 0);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package j8583;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.junit.Assert;
|
||||
@@ -23,6 +25,7 @@ public class TestIsoMessage {
|
||||
@Before
|
||||
public void init() throws IOException {
|
||||
mf = new MessageFactory();
|
||||
mf.setCharacterEncoding("UTF-8");
|
||||
mf.setCustomField(48, new CustomField48());
|
||||
mf.setConfigPath("config.xml");
|
||||
}
|
||||
@@ -60,7 +63,7 @@ public class TestIsoMessage {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncoding() throws ParseException {
|
||||
public void testEncoding() throws Exception {
|
||||
IsoMessage m1 = mf.newMessage(0x200);
|
||||
byte[] buf = m1.writeData();
|
||||
IsoMessage m2 = mf.parseMessage(buf, mf.getIsoHeader(0x200).length());
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<field num="48" type="LLLVAR">Life, the Universe, and Everything|42</field>
|
||||
<field num="49" type="ALPHA" length="3">484</field>
|
||||
<field num="60" type="LLLVAR">B456PRO1+000</field>
|
||||
<field num="61" type="LLLVAR"> 1234P vamos a meter mas de 90 caracteres en este campo para comprobar si hay algun error en el parseo del mismo. Esta definido como un LLLVAR aqui por lo tanto esto debe caber sin problemas; las guias de parseo de 200 y 210 tienen LLLVAR en campo 61 tambien.</field>
|
||||
<field num="61" type="LLLVAR"> 1234P vamos a meter más de 90 caracteres en este campo para comprobar si hay algun error en el parseo del mismo. Esta definido como un LLLVAR aqui por lo tanto esto debe caber sin problemas; las guias de parseo de 200 y 210 tienen LLLVAR en campo 61 tambien.</field>
|
||||
<field num="100" type="LLVAR">999</field>
|
||||
<field num="102" type="LLVAR">ABCD</field>
|
||||
</template>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
ISO0250000550210B23A80012EA080180000000014000004650000000000003000042813054746877112594604280428081103123173766123456123456=00123442579114472300614209027600TESTSOLAB TEST-3 DF MX484012B123PRO1+000013 0000P0312304ABCD040ABCD8123477547
|
||||
ISO0250000550210B23A80012EA080180000000014000004650000000000003000042813054746877112594604280428081103123173766123456123456=00123442579114472300614209027600TéSTSOLAB áéíóú üñÑ TEST-3 DF MX484012B123P®O1+000013 0000P0312304ABCD040ABCD8123477547
|
||||
|
||||
|
||||
Reference in New Issue
Block a user