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