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 * @author Vishnu Pillai 034 */ 035public class IF_FSTCHAR extends ISOFieldPackager implements TaggedFieldPackager { 036 037 private char terminator = '\\'; 038 039 /** Default constructor. */ 040 public IF_FSTCHAR() { 041 super(); 042 } 043 044 @Override 045 public void setToken(String token) { 046 if (token == null || token.length() != 1) { 047 throw new IllegalArgumentException("IF_FSTCHAR needs a token of 1 character."); 048 } 049 terminator = token.charAt(0); 050 } 051 052 @Override 053 public String getToken() { 054 return String.valueOf(terminator); 055 } 056 057 /** 058 * Constructs a packager with the given length and description. 059 * @param len - field len 060 * @param description symbolic descrption 061 */ 062 public IF_FSTCHAR(int len, String description) { 063 super(len, description); 064 } 065 066 /** 067 * @param c - a component 068 * @return packed component 069 * @throws org.jpos.iso.ISOException on pack/unpack error 070 */ 071 public byte[] pack(ISOComponent c) throws ISOException { 072 int len; 073 String s = (String) c.getValue(); 074 075 if ((len = s.length()) > getLength()) { 076 throw new ISOException( 077 "Invalid length " + len + " packing IF_FSTCHAR field " 078 + c.getKey() + " max length=" + getLength() 079 ); 080 } 081 082 s = s + terminator; 083 return s.getBytes(); 084 } 085 086 /** 087 * @param c - the Component to unpack 088 * @param b - binary image 089 * @param offset - starting offset within the binary image 090 * @return consumed bytes 091 * @throws org.jpos.iso.ISOException on pack/unpack error 092 */ 093 public int unpack(ISOComponent c, byte[] b, int offset) 094 throws ISOException { 095 if (!(c instanceof ISOField)) 096 throw new ISOException 097 (c.getClass().getName() + " is not an ISOField"); 098 int length = -1; 099 for (int i = 0; i < getMaxPackedLength(); i++) { 100 byte dataByte = b[offset + i]; 101 if ((char) dataByte == terminator) { 102 length = i; 103 break; 104 } 105 } 106 if (length >= 0) { 107 String value = new String(b, offset, length); 108 c.setValue(value); 109 return length + 1; 110 } else { 111 throw new ISOException("Terminating Backslash does not exist"); 112 } 113 } 114 115 public void unpack(ISOComponent c, InputStream in) 116 throws IOException, ISOException { 117 118 if (!(c instanceof ISOField)) 119 throw new ISOException 120 (c.getClass().getName() + " is not an ISOField"); 121 122 boolean endFound = false; 123 if (in.markSupported()) { 124 in.mark(getMaxPackedLength()); 125 } 126 ByteBuffer buf = ByteBuffer.allocate(getMaxPackedLength()); 127 128 for (int i = 0; i < getMaxPackedLength() && in.available() > 0; i++) { 129 byte dataByte = (byte) in.read(); 130 if ((char) dataByte == terminator) { 131 endFound = true; 132 break; 133 } else { 134 buf.put(dataByte); 135 } 136 } 137 if (endFound) { 138 byte[] data = byteBufferToBytes(buf); 139 String value = new String(data); 140 c.setValue(value); 141 } else { 142 if (in.markSupported()) { 143 in.reset(); 144 } 145 throw new ISOException("Terminating Backslash does not exist"); 146 } 147 } 148 149 private byte[] byteBufferToBytes(ByteBuffer buffer) { 150 int dataLength = buffer.position(); 151 byte[] bytes = new byte[dataLength]; 152 buffer.position(0); 153 buffer.get(bytes); 154 buffer.position(dataLength); 155 return bytes; 156 } 157 158 public int getMaxPackedLength() { 159 return getLength() + 1; 160 } 161} 162