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.gui; 020 021/** 022 * allows for easy visualization of channel utilization. 023 * It shows messages coming through in an 024 * 'Oscilloscope' style clickeable window. 025 * @see ISOMeter 026 * @see ISOMsgPanel 027 * @serial 028 */ 029 030import org.jpos.iso.*; 031 032import javax.swing.*; 033import java.awt.*; 034import java.util.Observable; 035import java.util.Observer; 036 037/** Swing panel that displays ISO channel activity and recent log entries. */ 038public class ISOChannelPanel extends JPanel implements Observer { 039 private static final long serialVersionUID = -8069489863639386589L; 040 /** 041 * Meter widget used to visualize channel activity. 042 * 043 * @serial embedded child component state 044 */ 045 ISOMeter meter; 046 /** 047 * Rolling log model displayed when the meter is opened. 048 * 049 * @serial serialized log contents 050 */ 051 DefaultListModel log; 052 /** 053 * Human-readable channel name shown in the UI. 054 * 055 * @serial display name persisted with the panel 056 */ 057 String symbolicName; 058 059 /** Fields that must be protected before logging. */ 060 private int[] protectFields = null; 061 /** Fields that must be wiped before logging. */ 062 private int[] wipeFields = null; 063 064 /** Maximum number of log entries to retain. */ 065 public static final int LOG_CAPACITY = 250; 066 067 /** 068 * Constructs a panel for the given channel. 069 * @param channel the ISO channel 070 * @param symbolicName the display name 071 */ 072 public ISOChannelPanel (ISOChannel channel, String symbolicName) 073 { 074 super(); 075 this.symbolicName = symbolicName; 076 setLayout(new FlowLayout()); 077 setBorder(BorderFactory.createRaisedBevelBorder()); 078 log = new DefaultListModel(); 079 add(createCountersPanel()); 080 meter.setConnected(channel.isConnected()); 081 if (channel instanceof Observable) 082 ((Observable)channel).addObserver(this); 083 } 084 /** 085 * Unconnected constructor allows for instantiation of 086 * ISOChannelPanel without associated ISOChannel 087 * (that can be attached later) 088 * @param symbolicName the display name 089 */ 090 public ISOChannelPanel (String symbolicName) { 091 super(); 092 this.symbolicName = symbolicName; 093 setLayout(new FlowLayout()); 094 setBorder(BorderFactory.createRaisedBevelBorder()); 095 log = new DefaultListModel(); 096 add(createCountersPanel()); 097 meter.setConnected(false); 098 } 099 100 /** Returns the symbolic name. 101 * @return symbolic name 102 */ 103 public final String getSymbolicName() { 104 return symbolicName; 105 } 106 /** Returns the log model. 107 * @return the log model 108 */ 109 public final ListModel getLog() { 110 return log; 111 } 112 113 public void update(Observable o, Object arg) { 114 if (arg != null && arg instanceof ISOMsg) { 115 ISOMsg m = (ISOMsg) arg; 116 try { 117 String mti = (String) m.getValue(0); 118 int imti = Integer.parseInt(mti); 119 if (m.isIncoming()) 120 meter.setValue(-imti, mti); 121 else 122 meter.setValue(imti, mti); 123 124 // log.insertElementAt(m,0); 125 log.addElement(getProtectedClone (m)); 126 if (log.getSize() > LOG_CAPACITY) 127 log.remove(0); 128 129 } catch (ISOException e) { 130 meter.setValue(ISOMeter.mass, "ERROR"); 131 } 132 meter.setValue(ISOMeter.mass); 133 } 134 if (o instanceof BaseChannel) { 135 BaseChannel c = (BaseChannel) o; 136 meter.setConnected(c.isConnected()); 137 int cnt[] = c.getCounters(); 138 try { 139 meter.setPositiveCounter( 140 ISOUtil.zeropad(Integer.toString(cnt[ISOChannel.TX % 1000000000]), 9) 141 ); 142 meter.setNegativeCounter( 143 ISOUtil.zeropad(Integer.toString(cnt[ISOChannel.RX] % 1000000000), 9) 144 ); 145 } catch (ISOException e) { } 146 } else if (o instanceof ISOServer) { 147 final ISOServer server = (ISOServer) o; 148 final Runnable updateIt = new Runnable() { 149 public void run() { 150 ISOUtil.sleep (250L); 151 int active = server.getActiveConnections(); 152 meter.setConnected(active > 0); 153 try { 154 meter.setPositiveCounter( 155 ISOUtil.zeropad(Integer.toString(active), 6) 156 ); 157 } catch (ISOException e) { } 158 meter.repaint(); 159 } 160 }; 161 SwingUtilities.invokeLater (updateIt); 162 } else 163 meter.setConnected(true); 164 } 165 /** Returns the ISO meter component. 166 * @return the ISOMeter 167 */ 168 public ISOMeter getISOMeter() { 169 return meter; 170 } 171 /** Sets the fields to protect in output. 172 * @param fields field numbers to protect 173 */ 174 public void setProtectFields (int[] fields) { 175 protectFields = fields; 176 } 177 /** Sets the fields to wipe in output. 178 * @param fields field numbers to wipe 179 */ 180 public void setWipeFields (int[] fields) { 181 wipeFields = fields; 182 } 183 private JPanel createCountersPanel() { 184 JPanel A = new JPanel() { 185 186 private static final long serialVersionUID = 1175437215105556679L; 187 188 public Insets getInsets() { 189 return new Insets(10,10,10,10); 190 } 191 }; 192 193 A.setLayout(new BorderLayout()); 194 195 meter = new ISOMeter(this); 196 197 JLabel l = new JLabel(symbolicName); 198 A.add(l, BorderLayout.NORTH); 199 A.add(meter, BorderLayout.CENTER); 200 // meter.start(); -- ISOMeter has auto-start now 201 return A; 202 } 203 private ISOMsg getProtectedClone (ISOMsg m) throws ISOException { 204 ISOMsg pm = (ISOMsg) m.clone (); 205 if (protectFields != null) 206 checkProtected(pm); 207 if (wipeFields != null) 208 checkHidden (pm); 209 return pm; 210 } 211 private void checkProtected (ISOMsg m) throws ISOException { 212 for (int f : protectFields) { 213 if (m.hasField(f)) 214 m.set(f, ISOUtil.protect(m.getString(f))); 215 } 216 } 217 private void checkHidden (ISOMsg m) throws ISOException { 218 for (int f : wipeFields) { 219 if (m.hasField(f)) 220 m.set(f, "[WIPED]"); 221 } 222 } 223}