?? isomessage.java
字號:
/*j8583 A Java implementation of the ISO8583 protocolCopyright (C) 2007 Enrique Zamudio LopezThis library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2.1 of the License, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA*/package com.solab.iso8583;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.OutputStream;import java.nio.ByteBuffer;import java.util.ArrayList;import java.util.BitSet;import java.util.Collections;import java.util.Hashtable;import java.util.Iterator;/** Represents an ISO8583 message. This is the core class of the framework. * Contains the bitmap which is modified as fields are added/removed. * This class makes no assumptions as to what types belong in each field, * nor what fields should each different message type have; that is left * for the developer, since the different ISO8583 implementations can vary * greatly. * * @author Enrique Zamudio */public class IsoMessage { static final byte[] HEX = new byte[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /** The message type. */ private int type; /** Indicates if the message is binary-coded. */ private boolean binary; /** This is where the values are stored. */ private Hashtable fields = new Hashtable(); /** Stores the optional ISO header. */ private String isoHeader; private int etx = -1; /** Creates a new empty message with no values set. */ public IsoMessage() { } /** Creates a new message with the specified ISO header. This will be prepended to the message. */ IsoMessage(String header) { isoHeader = header; } /** Returns the ISO header that this message was created with. */ public String getIsoHeader() { return isoHeader; } /** Sets the ISO message type. Common values are 0x200, 0x210, 0x400, 0x410, 0x800, 0x810. */ public void setType(int value) { type = value; } /** Returns the ISO message type. */ public int getType() { return type; } /** Indicates whether the message should be binary. Default is false. */ public void setBinary(boolean flag) { binary = flag; } /** Returns true if the message is binary coded; default is false. */ public boolean isBinary() { return binary; } /** Sets the ETX character, which is sent at the end of the message as a terminator. * Default is -1, which means no terminator is sent. */ public void setEtx(int value) { etx = value; } /** Returns the stored value in the field, without converting or formatting it. * @param field The field number. 1 is the secondary bitmap and is not returned as such; * real fields go from 2 to 128. */ public Object getObjectValue(int field) { IsoValue v = (IsoValue)fields.get(new Integer(field)); if (v == null) { return null; } return v.getValue(); } /** Returns the IsoValue for the specified field. First real field is 2. */ public IsoValue getField(int field) { return (IsoValue)fields.get(new Integer(field)); } /** Stored the field in the specified index. The first field is the secondary bitmap and has index 1, * so the first valid value for index must be 2. */ public void setField(int index, IsoValue field) { if (index < 2 || index > 128) { throw new IndexOutOfBoundsException("Field index must be between 2 and 128"); } if (field == null) { fields.remove(new Integer(index)); } else { fields.put(new Integer(index), field); } } /** Sets the specified value in the specified field, creating an IsoValue internally. * @param index The field number (2 to 128) * @param value The value to be stored. * @param t The ISO type. * @param length The length of the field, used for ALPHA and NUMERIC values only, ignored * with any other type. */ public void setValue(int index, Object value, IsoType t, int length) { if (index < 2 || index > 128) { throw new IndexOutOfBoundsException("Field index must be between 2 and 128"); } if (value == null) { fields.remove(new Integer(index)); } else { IsoValue v = null; if (t.needsLength()) { v = new IsoValue(t, value, length); } else { v = new IsoValue(t, value); } fields.put(new Integer(index), v); } } /** Returns true is the message has a value in the specified field. * @param idx The field number. */ public boolean hasField(int idx) { return fields.get(new Integer(idx)) != null; } /** Writes a message to a stream, after writing the specified number of bytes indicating * the message's length. The message will first be written to an internal memory stream * which will then be dumped into the specified stream. This method flushes the stream * after the write. There are at most three write operations to the stream: one for the * length header, one for the message, and the last one with for the ETX. * @param outs The stream to write the message to. * @param lengthBytes The size of the message length header. Valid ranges are 0 to 4. * @throws IllegalArgumentException if the specified length header is more than 4 bytes. * @throws IOException if there is a problem writing to the stream. */ public void write(OutputStream outs, int lengthBytes) throws IOException { if (lengthBytes > 4) { throw new IllegalArgumentException("The length header can have at most 4 bytes"); } byte[] data = writeInternal(); if (lengthBytes > 0) { int l = data.length; if (etx > -1) { l++; } byte[] buf = new byte[lengthBytes]; int pos = 0; if (lengthBytes == 4) { buf[0] = (byte)((l & 0xff000000) >> 24); pos++; } if (lengthBytes > 2) { buf[pos] = (byte)((l & 0xff0000) >> 16); pos++; } if (lengthBytes > 1) { buf[pos] = (byte)((l & 0xff00) >> 8); pos++; } buf[pos] = (byte)(l & 0xff); outs.write(buf); } outs.write(data); //ETX if (etx > -1) { outs.write(etx); } outs.flush(); } /** Creates and returns a ByteBuffer with the data of the message, including the length header. * The returned buffer is already flipped, so it is ready to be written to a Channel. */ public ByteBuffer writeToBuffer(int lengthBytes) { if (lengthBytes > 4) { throw new IllegalArgumentException("The length header can have at most 4 bytes"); } byte[] data = writeInternal(); ByteBuffer buf = ByteBuffer.allocate(lengthBytes + data.length + (etx > -1 ? 1 : 0)); if (lengthBytes > 0) { int l = data.length; if (etx > -1) { l++; } byte[] bbuf = new byte[lengthBytes]; int pos = 0; if (lengthBytes == 4) { bbuf[0] = (byte)((l & 0xff000000) >> 24); pos++; } if (lengthBytes > 2) { bbuf[pos] = (byte)((l & 0xff0000) >> 16); pos++; } if (lengthBytes > 1) { bbuf[pos] = (byte)((l & 0xff00) >> 8); pos++; } bbuf[pos] = (byte)(l & 0xff); buf.put(bbuf); } buf.put(data); //ETX if (etx > -1) { buf.put((byte)etx); } buf.flip(); return buf; } /** Writes the message to a memory buffer and returns it. The message does not include * the ETX character or the header length. */ protected byte[] writeInternal() { ByteArrayOutputStream bout = new ByteArrayOutputStream(); if (isoHeader != null) { try { bout.write(isoHeader.getBytes()); } catch (IOException ex) { //should never happen, writing to a ByteArrayOutputStream } } //Message Type if (binary) { bout.write((type & 0xff00) >> 8); bout.write(type & 0xff); } else { String x = Integer.toHexString(type); if (x.length() < 4) { bout.write(48); } try { bout.write(x.getBytes()); } catch (IOException ex) { //should never happen, writing to a ByteArrayOutputStream } } //Bitmap ArrayList keys = new ArrayList(); keys.addAll(fields.keySet()); Collections.sort(keys); BitSet bs = new BitSet(64); for (Iterator iter = keys.iterator(); iter.hasNext();) { bs.set(((Integer)iter.next()).intValue() - 1); } //Extend to 128 if needed if (bs.length() > 64) { BitSet b2 = new BitSet(128); b2.or(bs); bs = b2; bs.set(0); } //Write bitmap to stream if (binary) { int pos = 128; int b = 0; for (int i = 0; i < bs.size(); i++) { if (bs.get(i)) { b |= pos; } pos >>= 1; if (pos == 0) { bout.write(b); pos = 128; b = 0; } } } else { int pos = 0; int lim = bs.size() / 4; for (int i = 0; i < lim; i++) { int nibble = 0; if (bs.get(pos++)) nibble += 8; if (bs.get(pos++)) nibble += 4; if (bs.get(pos++)) nibble += 2; if (bs.get(pos++)) nibble++; bout.write(HEX[nibble]); } } //Fields for (Iterator iter = keys.iterator(); iter.hasNext();) { IsoValue v = (IsoValue)fields.get(iter.next()); try { v.write(bout, binary); } catch (IOException ex) { //should never happen, writing to a ByteArrayOutputStream } } return bout.toByteArray(); }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -