
org.jpos.tlv.TLVList Maven / Gradle / Ivy
Go to download
jPOS is an ISO-8583 based financial transaction
library/framework that can be customized and
extended in order to implement financial interchanges.
/*
* jPOS Project [http://jpos.org]
* Copyright (C) 2000-2017 jPOS Software SRL
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package org.jpos.tlv;
import org.jpos.iso.ISOException;
import org.jpos.iso.ISOUtil;
import org.jpos.util.Loggeable;
import java.io.PrintStream;
import java.io.Serializable;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
/**
* @author bharavi
*/
public class TLVList implements Serializable, Loggeable {
private static final long serialVersionUID = 6962311407331957465L;
private List tags = new ArrayList();
private int tagToFind = 0;
private int indexLastOccurrence = -1;
public TLVList() {
super();
}
/**
* unpack a message
* @param buf - raw message
*/
public void unpack(byte[] buf) throws ISOException {
unpack(buf, 0);
}
/**
* @return a list of tags.
*/
public List getTags() {
return tags;
}
/**
* @return an enumeration of the List of tags.
*/
public Enumeration elements() {
return Collections.enumeration(tags);
}
/**
* unpack a message with a starting offset
* @param buf - raw message
* @param offset theoffset
* @throws org.jpos.iso.ISOException
*/
public void unpack(byte[] buf, int offset) throws ISOException {
ByteBuffer buffer=ByteBuffer.wrap(buf,offset,buf.length-offset);
TLVMsg currentNode;
while (hasNext(buffer)) {
currentNode = getTLVMsg(buffer); // null is returned if no tag found (trailing padding)
if (currentNode != null)
append(currentNode);
}
}
/**
* Append TLVMsg to the TLVList
*/
public void append(TLVMsg tlvToAppend) {
tags.add(tlvToAppend);
}
/**
* Append TLVMsg to the TLVList
* @param tag tag id
* @param value tag value
*/
public void append(int tag, byte[] value) {
append(new TLVMsg(tag, value));
}
/**
* Append TLVMsg to the TLVList
* @param tag id
* @param value in hexadecimal character representation
*/
public void append(int tag, String value) {
append(new TLVMsg(tag, ISOUtil.hex2byte(value)));
}
/**
* delete the specified TLV from the list using a Zero based index
* @param index number
*/
public void deleteByIndex(int index) {
tags.remove(index);
}
/**
* Delete the specified TLV from the list by tag value
* @param tag id
*/
public void deleteByTag(int tag) {
List t = new ArrayList();
for (TLVMsg tlv2 :tags ) {
if (tlv2.getTag() == tag)
t.add(tlv2);
}
tags.removeAll(t);
}
/**
* searches the list for a specified tag and returns a TLV object
* @param tag id
* @return TLVMsg
*/
public TLVMsg find(int tag) {
tagToFind = tag;
for (TLVMsg tlv :tags ) {
if (tlv.getTag() == tag) {
indexLastOccurrence = tags.indexOf(tlv);
return tlv;
}
}
indexLastOccurrence = -1;
return null;
}
/**
* searches the list for a specified tag and returns a zero based index for
* that tag
* @return index for a given {2code tag}
*/
public int findIndex(int tag) {
tagToFind = tag;
for (TLVMsg tlv :tags ) {
if (tlv.getTag() == tag) {
indexLastOccurrence = tags.indexOf(tlv);
return indexLastOccurrence;
}
}
indexLastOccurrence = -1;
return -1;
}
/**
* Return the next TLVMsg of same TAG value
* @return TLVMsg (return null if not found)
*/
public TLVMsg findNextTLV() {
for ( int i=indexLastOccurrence + 1 ; i < tags.size(); i++) {
if (tags.get(i).getTag() == tagToFind) {
indexLastOccurrence = i;
return tags.get(i);
}
}
return null;
}
/**
* Returns a TLV object which represents the TLVMsg stored within the TLVList
* at the given index
* @param index number
* @return TLVMsg
*/
public TLVMsg index(int index) {
return tags.get(index);
}
/**
* pack the TLV message (BER-TLV Encoding)
* @return the packed message
*/
public byte[] pack() {
ByteBuffer buffer=ByteBuffer.allocate(516);
for ( TLVMsg tlv : tags)
buffer.put(tlv.getTLV());
byte[] b=new byte[buffer.position()];
buffer.flip();
buffer.get(b);
return b;
}
/**
* Read next TLV Message from stream and return it
* @param buffer the buffer
* @return TLVMsg
*/
private TLVMsg getTLVMsg(ByteBuffer buffer) throws ISOException {
int tag = getTAG(buffer); // tag = 0 if tag not found
if (tag ==0)
return null;
// Get Length if buffer remains!
if (!buffer.hasRemaining())
throw new ISOException(String.format("BAD TLV FORMAT - tag (%x)"
+ " without length or value",tag));
int length = getValueLength(buffer);
if(length >buffer.remaining())
throw new ISOException(String.format("BAD TLV FORMAT - tag (%x)"
+ " length (%d) exceeds available data.", tag, length));
byte[] arrValue= new byte[length];
buffer.get(arrValue);
return getTLVMsg(tag, arrValue);
}
protected TLVMsg getTLVMsg(int tag, byte[] arrValue) {
return new TLVMsg(tag,arrValue);
}
/**
* Check Existance of next TLV Field
* @param buffer ByteBuffer containing TLV data
*/
private boolean hasNext(ByteBuffer buffer) {
return buffer.hasRemaining();
}
/**
* Return the next TAG
* @return tag
*/
private int getTAG(ByteBuffer buffer) {
int b;
int tag;
b = buffer.get() & 0xff;
// Skip padding chars
if (b == 0xFF || b == 0x00) {
do {
if (hasNext(buffer)) {
b = buffer.get() & 0xff;
} else {
break;
}
} while (b == 0xFF || b == 0x00);
}
// Get first byte of Tag Identifier
tag = b;
// Get rest of Tag identifier if required
if ((b & 0x1F) == 0x1F) {
do {
tag <<= 8;
b = buffer.get();
tag |= b & 0xFF;
} while ((b & 0x80) == 0x80);
}
return tag;
}
/**
* Read length bytes and return the int value
* @param buffer buffer
* @return value length
*/
protected int getValueLength(ByteBuffer buffer) {
byte b = buffer.get();
int count = b & 0x7f;
// check first byte for more bytes to follow
if ((b & 0x80) == 0 || count == 0)
return count;
//fetch rest of bytes
byte[] bb = new byte[count];
buffer.get(bb);
//adjust buffer if first bit is turn on
//important for BigInteger reprsentation
if ( (bb[0] & 0x80) > 0 )
bb = ISOUtil.concat(new byte[1], bb);
return new BigInteger(bb).intValue();
}
/**
* searches the list for a specified tag and returns a hex String
* @param tag id
* @return hexString
*/
public String getString(int tag) {
TLVMsg msg = find(tag);
if (msg != null) {
return msg.getStringValue();
}
else {
return null;
}
}
/**
* searches the list for a specified tag and returns it raw
* @param tag id
* @return byte[]
*/
public byte[] getValue(int tag) {
TLVMsg msg = find(tag);
if (msg != null) {
return msg.getValue();
}
else {
return null;
}
}
/**
* searches the list for a specified tag and returns a boolean indicating presence
* @return boolean
*/
public boolean hasTag(int tag) {
return findIndex(tag) > -1;
}
@Override
public void dump(PrintStream p, String indent) {
String inner = indent + " ";
p.println (indent + "");
for (TLVMsg msg : getTags())
msg.dump (p, inner);
p.println (indent + " ");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy