001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.tlv.packager; 020 021import org.jpos.iso.ISOComponent; 022import org.jpos.iso.ISOException; 023import org.jpos.iso.ISOField; 024import org.jpos.iso.ISOFieldPackager; 025import org.jpos.iso.TaggedFieldPackager; 026 027import java.io.IOException; 028import java.io.InputStream; 029import java.nio.ByteBuffer; 030 031/** 032 * Field Separator Terminated packager 033 * 034 * @author Vishnu Pillai 035 */ 036public class IF_FSTBINARY extends ISOFieldPackager implements TaggedFieldPackager { 037 038 private byte terminator = (byte) 0xFF; 039 private String token; 040 041 /** Default constructor. */ 042 public IF_FSTBINARY() { 043 super(); 044 } 045 046 @Override 047 public void setToken(String token) { 048 if (token == null || token.length() != 2) { 049 throw new IllegalArgumentException("IF_FSTBINARY needs a HEX token of 2 characters."); 050 } 051 this.token = token; 052 this.terminator = (byte) Integer.parseInt(token, 16); 053 } 054 055 @Override 056 public String getToken() { 057 return token; 058 } 059 060 /** 061 * Constructs a packager with the given length and description. 062 * @param len - field len 063 * @param description symbolic descrption 064 */ 065 public IF_FSTBINARY(int len, String description) { 066 super(len, description); 067 } 068 069 /** 070 * @param c - a component 071 * @return packed component 072 * @throws org.jpos.iso.ISOException on pack/unpack error 073 */ 074 public byte[] pack(ISOComponent c) throws ISOException { 075 int len; 076 byte[] s = c.getBytes(); 077 078 if ((len = s.length) > getLength()) { 079 throw new ISOException( 080 "Invalid length " + len + " packing IF_FSTBINARY field " 081 + c.getKey() + " max length=" + getLength() 082 ); 083 } 084 byte[] b = new byte[s.length + 1]; 085 System.arraycopy(s, 0, b, 0, s.length); 086 b[b.length - 2] = terminator; 087 return b; 088 } 089 090 /** 091 * @param c - the Component to unpack 092 * @param b - binary image 093 * @param offset - starting offset within the binary image 094 * @return consumed bytes 095 * @throws org.jpos.iso.ISOException on pack/unpack error 096 */ 097 public int unpack(ISOComponent c, byte[] b, int offset) 098 throws ISOException { 099 if (!(c instanceof ISOField)) 100 throw new ISOException 101 (c.getClass().getName() + " is not an ISOField"); 102 int length = -1; 103 for (int i = 0; i < getMaxPackedLength(); i++) { 104 byte dataByte = b[offset + i]; 105 if (dataByte == terminator) { 106 length = i; 107 break; 108 } 109 } 110 if (length >= 0) { 111 byte[] value = new byte[length]; 112 System.arraycopy(b, offset, value, 0, length); 113 c.setValue(value); 114 return length + 1; 115 } else { 116 throw new ISOException("Terminating Backslash does not exist"); 117 } 118 } 119 120 public void unpack(ISOComponent c, InputStream in) 121 throws IOException, ISOException { 122 123 if (!(c instanceof ISOField)) 124 throw new ISOException 125 (c.getClass().getName() + " is not an ISOField"); 126 127 boolean endFound = false; 128 if (in.markSupported()) { 129 in.mark(getMaxPackedLength()); 130 } 131 ByteBuffer buf = ByteBuffer.allocate(getMaxPackedLength()); 132 133 for (int i = 0; i < getMaxPackedLength() && in.available() > 0; i++) { 134 byte dataByte = (byte) in.read(); 135 if (dataByte == terminator) { 136 endFound = true; 137 break; 138 } else { 139 buf.put(dataByte); 140 } 141 } 142 if (endFound) { 143 byte[] data = byteBufferToBytes(buf); 144 c.setValue(data); 145 } else { 146 if (in.markSupported()) { 147 in.reset(); 148 } 149 throw new ISOException("Terminating Backslash does not exist"); 150 } 151 } 152 153 private byte[] byteBufferToBytes(ByteBuffer buffer) { 154 int dataLength = buffer.position(); 155 byte[] bytes = new byte[dataLength]; 156 buffer.position(0); 157 buffer.get(bytes); 158 buffer.position(dataLength); 159 return bytes; 160 } 161 162 public int getMaxPackedLength() { 163 return getLength() + 1; 164 } 165} 166