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.header; 020 021import org.jpos.iso.ISOUtil; 022 023/** 024 * BASE1 header implementation. 025 * <pre> 026 * 0 hlen; Fld 1: Header Length 1B (Byte 0) 027 * 1 hformat; Fld 2: Header Format 8N,bit (Byte 1) 028 * 2 format; Fld 3: Text Format 1B (Byte 2) 029 * 3 len[2]; Fld 4: Total Message Length 2B (Byte 3- 4) 030 * 5 dstId[3]; Fld 5: Destination Id 6N,BCD (Byte 5- 7) 031 * 8 srcId[3]; Fld 6: Source Id 6N,BCD (Byte 8-10) 032 * 11 rtCtl; Fld 7: Round-Trip Ctrl Info 8N,bit (Byte 11) 033 * 12 flags[2]; Fld 8: BASE I Flags 16N,bit (Byte 12-13) 034 * 14 status[3]; Fld 9: Message Status Flags 24bits (Byte 14-16) 035 * 17 batchNbr; Fld 10: Batch Number 1B (Byte 17) 036 * 18 reserved[3]; Fld 11: Reserved 3B (Byte 18-20) 037 * 21 userInfo; Fld 12: User Info 1B (Byte 21) 038 * The following fields are only presend in a reject message 039 * 22 bitmap; Fld 13: Bitmap 2B (Byte 22-23) 040 * 24 rejectdata; Fld 14: Reject Data Group 2B (Byte 24-25) 041 * </pre> 042 * 043 */ 044public class BASE1Header extends BaseHeader { 045 046 private static final long serialVersionUID = 6466427524726021374L; 047 /** Fixed length of a BASE-1 header in bytes. */ 048 public static final int LENGTH = 22; 049 050 /** Creates a BASE1Header with source and destination both set to {@code "000000"}. */ 051 public BASE1Header() { 052 this("000000", "000000"); 053 } 054 /** Creates a BASE1Header with the given source and destination and default format (2). 055 * @param source 6-digit source ID 056 * @param destination 6-digit destination ID 057 */ 058 public BASE1Header(String source, String destination) { 059 super(); 060 header = new byte[LENGTH]; 061 header[0] = LENGTH; // hlen 062 setHFormat(1); 063 setFormat(2); 064 setSource(source); 065 setDestination(destination); 066 } 067 /** Creates a BASE1Header with explicit format. 068 * @param source 6-digit source ID 069 * @param destination 6-digit destination ID 070 * @param format header format code 071 */ 072 public BASE1Header(String source, String destination, int format) { 073 super(); 074 header = new byte[LENGTH]; 075 header[0] = LENGTH; // hlen 076 setHFormat(1); 077 setFormat(format); 078 setSource(source); 079 setDestination(destination); 080 } 081 /** Creates a BASE1Header from a raw byte array. 082 * @param header raw header bytes 083 */ 084 public BASE1Header(byte[] header) { 085 super(header); 086 } 087 088 /** 089 * Returns the header length field value. 090 * @return header length 091 */ 092 public int getHLen() { 093 return header[0] & 0xFF; 094 } 095 /** 096 * Sets the header format byte. 097 * @param hformat header format value 098 */ 099 public void setHFormat(int hformat) { 100 header[1] = (byte) hformat; 101 } 102 /** 103 * Returns the message format code. 104 * @return message format code 105 */ 106 public int getFormat() { 107 return header[2] & 0xFF; 108 } 109 /** 110 * Sets the routing control byte. 111 * @param i routing control value 112 */ 113 public void setRtCtl(int i) { 114 header[11] = (byte) i; 115 } 116 /** 117 * Sets the flags field. 118 * @param i flags value 119 */ 120 public void setFlags(int i) { 121 header[12] = (byte) (i >> 8 & 0xFF); 122 header[13] = (byte) (i & 0xFF); 123 } 124 /** 125 * Sets the status field. 126 * @param i status value 127 */ 128 public void setStatus(int i) { 129 header[14] = (byte) (i >> 16 & 0xFF); 130 header[15] = (byte) (i >> 8 & 0xFF); 131 header[16] = (byte) (i & 0xFF); 132 } 133 /** 134 * Sets the batch number. 135 * @param i batch number 136 */ 137 public void setBatchNumber(int i) { 138 header[17] = (byte) (i & 0xFF); 139 } 140 /** 141 * Sets the message format code. 142 * @param format the message format code 143 */ 144 public void setFormat(int format) { 145 header[2] = (byte) format; 146 } 147 /** 148 * Sets the message length field in the header. 149 * @param len the payload length (header length will be added automatically) 150 */ 151 public void setLen(int len) { 152 len += header.length; 153 header[3] = (byte) (len >> 8 & 0xff); 154 header[4] = (byte) (len & 0xff); 155 } 156 public void setDestination(String dest) { 157 byte[] d = ISOUtil.str2bcd(dest, true); 158 System.arraycopy(d, 0, header, 5, 3); 159 } 160 public void setSource(String src) { 161 byte[] d = ISOUtil.str2bcd(src, true); 162 System.arraycopy(d, 0, header, 8, 3); 163 } 164 public String getSource() { 165 return ISOUtil.bcd2str (this.header, 8, 6, false); 166 } 167 public String getDestination() { 168 return ISOUtil.bcd2str (this.header, 5, 6, false); 169 } 170 public void swapDirection() { 171 if (header != null && header.length >= LENGTH) { 172 byte[] source = new byte[3]; 173 System.arraycopy(header, 8, source, 0, 3); 174 System.arraycopy(header, 5, header, 8, 3); 175 System.arraycopy(source, 0, header, 5, 3); 176 } 177 } 178 /** 179 * Returns true if this message is a BASE-1 reject. 180 * @return true if the message is rejected 181 */ 182 public boolean isRejected() { 183 // Header length must be 26 or gerater 184 // And header field 13 bit 1 must be 1 (field 13 starts at byte 22) 185 return getLength() >= 26 && (header[22] & 0x80) == 0x80; 186 } 187 188 /** 189 * Gets the BASE 1 Reject Code. 190 * 191 * @return If the message is a reject return the Reject Code Otherwise return "" 192 */ 193 public String getRejectCode() { 194 return isRejected() ? ISOUtil.bcd2str (this.header, 24, 4, false) : ""; 195 } 196 197 /* 198 * parse header contributed by santhoshvee@yahoo.co.uk in jpos-dev mailing list 199 */ 200 /** 201 * Formats the header fields as a human-readable diagnostic string. 202 * @return formatted header dump 203 */ 204 public String formatHeader() { 205 String h = ISOUtil.hexString(this.header); 206 String lf = System.getProperty("line.separator"); 207 StringBuffer d = new StringBuffer(); 208 d.append(lf); 209 d.append("[H 01] Header length "); d.append(h.substring(0, 2)); d.append(lf); 210 d.append("[H 02] Header format "); d.append(h.substring(2, 4)); d.append(lf); 211 d.append("[H 03] Text format "); d.append(h.substring(4, 6)); d.append(lf); 212 d.append("[H 04] Total length "); d.append(h.substring(6, 10)); d.append(lf); 213 d.append("[H 05] Destination ID "); d.append(h.substring(10, 16)); d.append(lf); 214 d.append("[H 06] Source ID "); d.append(h.substring(16, 22)); d.append(lf); 215 d.append("[H 07] Round-trip ctrl info "); d.append(h.substring(22, 24)); d.append(lf); 216 d.append("[H 08] BASE I flags "); d.append(h.substring(24, 28)); d.append(lf); 217 d.append("[H 09] Message status flags "); d.append(h.substring(28, 34)); d.append(lf); 218 d.append("[H 10] Batch number "); d.append(h.substring(34, 36)); d.append(lf); 219 d.append("[H 11] Reserved "); d.append(h.substring(36, 42)); d.append(lf); 220 d.append("[H 12] User info "); d.append(h.substring(42, 44)); d.append(lf); 221 if (isRejected()) { 222 d.append("[H 13] Bitmap "); d.append(h.substring(44, 48)); d.append(lf); 223 d.append("[H 14] Reject data group "); d.append(h.substring(48, 52)); d.append(lf); 224 d.append("Original header "); d.append(h.substring(52)); d.append(lf); 225 } 226 return d.toString(); 227 } 228}