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; 024import org.jpos.util.SimpleLogSource; 025 026import java.io.ByteArrayOutputStream; 027import java.io.IOException; 028import java.io.InputStream; 029 030/** 031 * @author apr@cs.com.uy 032 * @version $Id$ 033 * @see ISOPackager 034 * @see ISOBasePackager 035 * @see ISOComponent 036 */ 037@SuppressWarnings("unchecked") 038public class VISA1Packager 039 extends SimpleLogSource implements ISOPackager, VISA1ResponseFilter 040{ 041 public static final byte[] FS = { (byte)'\034' }; 042 int[] sequence; 043 int respField; 044 String badResultCode; 045 String okPattern; 046 VISA1ResponseFilter filter; 047 048 /** 049 * @param sequence array of fields that go to VISA1 request 050 * @param respField where to put response 051 * @param badResultCode (i.e. "05") 052 * @param okPattern (i.e. "AUT. ") 053 */ 054 public VISA1Packager 055 (int[] sequence, int respField, String badResultCode, String okPattern) 056 { 057 super(); 058 this.sequence = sequence; 059 this.respField = respField; 060 this.badResultCode = badResultCode; 061 this.okPattern = okPattern; 062 setVISA1ResponseFilter (this); 063 } 064 public void setVISA1ResponseFilter (VISA1ResponseFilter filter) { 065 this.filter = filter; 066 } 067 068 protected int handleSpecialField35 (ISOMsg m, ByteArrayOutputStream bout) 069 throws ISOException, IOException 070 { 071 int len = 0; 072 byte[] entryMode = new byte[1]; 073 if (m.hasField (35)) { 074 entryMode[0] = (byte) '\001'; 075 byte[] value = m.getString(35).getBytes(); 076 bout.write(entryMode); 077 bout.write(value); 078 bout.write(FS); 079 len += value.length+2; 080 } else if (m.hasField (2) && m.hasField (14)) { 081 entryMode[0] = (byte) '\000'; 082 String simulatedTrack2 = m.getString(2) + "=" + m.getString(14); 083 bout.write(entryMode); 084 bout.write(simulatedTrack2.getBytes()); 085 bout.write(FS); 086 len += simulatedTrack2.length()+2; 087 } 088 return len; 089 } 090 091 @Override 092 public byte[] pack (ISOComponent c) throws ISOException 093 { 094 LogEvent evt = new LogEvent (this, "pack"); 095 try (ByteArrayOutputStream bout = new ByteArrayOutputStream(100)) 096 { 097 if (!(c instanceof ISOMsg)) 098 throw new ISOException 099 ("Can't call VISA1 packager on non ISOMsg"); 100 101 ISOMsg m = (ISOMsg) c; 102 103 for (int i=0; i<sequence.length; i++) { 104 int fld = sequence[i]; 105 if (fld == 35) 106 handleSpecialField35(m, bout); 107 else if (m.hasField(fld)) { 108 byte[] value; 109 if (fld == 4) { 110 long amt = Long.valueOf(m.getString(4)); 111 value = ISOUtil.formatAmount (amt,12).trim().getBytes(); 112 } 113 else 114 value = m.getString(fld).getBytes(); 115 bout.write(value); 116 if (i < sequence.length-1) { 117 bout.write(FS); 118 } 119 } 120 } 121 122 byte[] d = bout.toByteArray(); 123 if (logger != null) // save a few CPU cycle if no logger available 124 evt.addMessage (ISOUtil.dumpString (d)); 125 return d; 126 } catch (ISOException ex) { 127 evt.addMessage(ex); 128 throw ex; 129 } catch (IOException ex) { 130 evt.addMessage(ex); 131 throw new ISOException(ex); 132 } finally { 133 Logger.log(evt); 134 } 135 } 136 137 public String guessAutNumber (String s) { 138 StringBuilder buf = new StringBuilder(); 139 for (int i=0; i<s.length(); i++) 140 if (Character.isDigit(s.charAt(i))) 141 buf.append (s.charAt(i)); 142 if (buf.length() == 0) 143 return null; 144 145 while (buf.length() > 6) 146 buf.deleteCharAt(0); 147 while (buf.length() < 6) 148 buf.insert(0, "0"); 149 150 return buf.toString(); 151 } 152 153 @Override 154 public int unpack (ISOComponent m, byte[] b) throws ISOException 155 { 156 String response = new String (b); 157 m.set (new ISOField (respField, response)); 158 m.set (new ISOField (39, badResultCode)); 159 if (response.startsWith (okPattern)) { 160 String autNumber = filter.guessAutNumber (response); 161 if (autNumber != null) { 162 m.set (new ISOField (39, "00")); 163 m.set (new ISOField (38, autNumber)); 164 } 165 } 166 return b.length; 167 } 168 public void unpack (ISOComponent m, InputStream in) throws ISOException { 169 throw new ISOException ("not implemented"); 170 } 171 public String getFieldDescription(ISOComponent m, int fldNumber) 172 { 173 return "VISA 1 fld "+fldNumber; 174 } 175 public String getDescription () { 176 return getClass().getName(); 177 } 178 public ISOMsg createISOMsg() { 179 return new ISOMsg(); 180 } 181}