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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user