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.iso.packager; 020 021import org.jpos.iso.*; 022import org.jpos.util.LogEvent; 023import org.jpos.util.Logger; 024 025import java.io.ByteArrayOutputStream; 026import java.io.IOException; 027import java.util.BitSet; 028import java.util.Map; 029 030/** 031 * ISO 8583 v1987 BINARY Packager 032 * customized for VISA Base1 subfields 033 * 034 * 035 * @author <a href="mailto:eoin.flood@orbiscom.com">Eoin Flood</a> 036 * @version $Id$ 037 * @see ISOPackager 038 * @see ISOBasePackager 039 * @see ISOComponent 040 */ 041 042@SuppressWarnings("unchecked") 043public class Base1SubFieldPackager extends ISOBasePackager 044{ 045 // These methods are identical to ISOBasePackager 046 // except that fld[1] has been replaced with fld[0] 047 // and a secondard bitmap is not allowed 048 049 protected boolean emitBitMap() 050 { 051 return fld[0] instanceof ISOBitMapPackager; 052 } 053 054 protected int getFirstField() 055 { 056 return fld[0] instanceof ISOBitMapPackager ? 1 : 0; 057 } 058 059 protected ISOFieldPackager getBitMapfieldPackager() 060 { 061 return fld[0]; 062 } 063 064 /** 065 * Unpack a packed subfield into 066 * its corresponding ISOComponent 067 */ 068 069 public int unpack (ISOComponent m, byte[] b) throws ISOException 070 { 071 LogEvent evt = new LogEvent (this, "unpack"); 072 try 073 { 074 if (m.getComposite() != m) 075 throw new ISOException ("Can't call packager on non Composite"); 076 if (logger != null) // save a few CPU cycle if no logger available 077 evt.addMessage (ISOUtil.hexString (b)); 078 079 int consumed=0; 080 ISOBitMap bitmap = new ISOBitMap (-1); 081 082 BitSet bmap = null; 083 int maxField = fld.length; 084 if (emitBitMap()) 085 { 086 consumed += getBitMapfieldPackager().unpack(bitmap,b,consumed); 087 bmap = (BitSet) bitmap.getValue(); 088 m.set (bitmap); 089 maxField = bmap.size(); 090 } 091 for (int i=getFirstField(); i<maxField && consumed < b.length; i++) 092 { 093 if (bmap == null || bmap.get(i)) 094 { 095 ISOComponent c = fld[i].createComponent(i); 096 consumed += fld[i].unpack (c, b, consumed); 097 m.set(c); 098 } 099 } 100 if (b.length != consumed) 101 { 102 evt.addMessage ( 103 "WARNING: unpack len=" +b.length +" consumed=" +consumed); 104 } 105 return consumed; 106 } 107 catch (ISOException e) 108 { 109 evt.addMessage (e); 110 throw e; 111 } 112 finally 113 { 114 Logger.log (evt); 115 } 116 } 117 118 /** 119 * Pack the subfield into a byte array 120 */ 121 @Override 122 public byte[] pack (ISOComponent m) throws ISOException { 123 LogEvent evt = new LogEvent (this, "pack"); 124 try (ByteArrayOutputStream bout = new ByteArrayOutputStream(100)) 125 { 126 ISOComponent c; 127 Map fields = m.getChildren(); 128 129 if (emitBitMap()) 130 { 131 // BITMAP (-1 in HashTable) 132 c = (ISOComponent) fields.get (-1); 133 byte[] b = getBitMapfieldPackager().pack(c); 134 bout.write(b); 135 } 136 137 for (int i=getFirstField(); i<=m.getMaxField(); i++) 138 { 139 if ((c = (ISOComponent) fields.get (i)) != null) 140 { 141 try 142 { 143 byte[] b = fld[i].pack(c); 144 bout.write(b); 145 } 146 catch (Exception e) 147 { 148 evt.addMessage ("error packing field "+i); 149 evt.addMessage (c); 150 evt.addMessage (e); 151 throw new ISOException (e); 152 } 153 } 154 } 155 156 byte[] d = bout.toByteArray(); 157 if (logger != null) // save a few CPU cycle if no logger available 158 evt.addMessage (ISOUtil.hexString (d)); 159 return d; 160 } catch (ISOException ex) { 161 evt.addMessage(ex); 162 throw ex; 163 } catch (IOException ex) { 164 evt.addMessage(ex); 165 throw new ISOException(ex); 166 } finally { 167 Logger.log(evt); 168 } 169 } 170} 171 172