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.channel; 020/** 021 * sends back requests, posibly applying filters 022 * @author <a href="mailto:apr@cs.com.uy">Alejandro P. Revilla</a> 023 * @version $Revision$ $Date$ 024 * @since 1.2.2 025 */ 026 027import org.jpos.iso.FilteredBase; 028import org.jpos.iso.ISOException; 029import org.jpos.iso.ISOMsg; 030import org.jpos.iso.ISOPackager; 031import org.jpos.util.*; 032 033import java.io.IOException; 034 035/** 036 * In-memory ISO channel that loops messages back through a {@link BlockingQueue}, 037 * useful for testing without external network resources. 038 */ 039public class LoopbackChannel extends FilteredBase implements LogSource { 040 boolean usable = true; 041 private int[] cnt; 042 String name; 043 BlockingQueue queue; 044 Logger logger; 045 String realm; 046 047 /** Default constructor. */ 048 public LoopbackChannel () { 049 super(); 050 cnt = new int[SIZEOF_CNT]; 051 queue = new BlockingQueue(); 052 } 053 054 /** 055 * setPackager is optional on LoopbackChannel, it is 056 * used for debugging/formating purposes only 057 */ 058 public void setPackager(ISOPackager packager) { 059 // N/A 060 } 061 062 public void connect () { 063 cnt[CONNECT]++; 064 usable = true; 065 setChanged(); 066 notifyObservers(); 067 } 068 069 /** 070 * disconnects ISOChannel 071 */ 072 public void disconnect () { 073 usable = false; 074 setChanged(); 075 notifyObservers(); 076 } 077 078 public void reconnect() { 079 usable = true; 080 setChanged(); 081 notifyObservers(); 082 } 083 084 public boolean isConnected() { 085 return usable; 086 } 087 088 public void send (ISOMsg m) 089 throws IOException,ISOException { 090 if (!isConnected()) 091 throw new ISOException ("unconnected ISOChannel"); 092 LogEvent evt = new LogEvent (this, "loopback-send", m); 093 m = applyOutgoingFilters (m, evt); 094 queue.enqueue (m); 095 cnt[TX]++; 096 notifyObservers(); 097 Logger.log (evt); 098 } 099 100 public void send (byte[] b) 101 throws IOException,ISOException { 102 if (!isConnected()) 103 throw new ISOException ("unconnected ISOChannel"); 104 LogEvent evt = new LogEvent (this, "loopback-send", b); 105 queue.enqueue (b); 106 cnt[TX]++; 107 notifyObservers(); 108 Logger.log (evt); 109} 110 111 public ISOMsg receive() throws IOException, ISOException 112 { 113 if (!isConnected()) 114 throw new ISOException ("unconnected ISOChannel"); 115 try { 116 ISOMsg m = (ISOMsg) ((ISOMsg) queue.dequeue()).clone(); 117 LogEvent evt = new LogEvent (this, "loopback-receive", m); 118 m = applyIncomingFilters (m, evt); 119 cnt[RX]++; 120 notifyObservers(); 121 Logger.log (evt); 122 return m; 123 } catch (InterruptedException e) { 124 throw new IOException (e.toString()); 125 } catch (BlockingQueue.Closed e) { 126 throw new IOException (e.toString()); 127 } 128 } 129 130 public void setUsable(boolean usable) { 131 this.usable = usable; 132 setChanged(); 133 notifyObservers(); 134 } 135 136 /** 137 * Returns the live counter array (transmitted/received tallies). 138 * 139 * @return counter array as managed by this channel 140 */ 141 public int[] getCounters() { 142 return cnt; 143 } 144 145 public void setName (String name) { 146 this.name = name; 147 NameRegistrar.register ("channel."+name, this); 148 } 149 150 public String getName() { 151 return name; 152 } 153 154 /** 155 * Returns the packager configured on this channel. 156 * 157 * @return {@code null}; the loopback channel has no packager because messages are queued as objects 158 */ 159 public ISOPackager getPackager() { 160 return null; 161 } 162 163 /** Resets the connect/transmit/receive counters to zero. */ 164 public void resetCounters() { 165 for (int i=0; i<SIZEOF_CNT; i++) 166 cnt[i] = 0; 167 } 168 public void setLogger (Logger logger, String realm) { 169 this.logger = logger; 170 this.realm = realm; 171 } 172 public String getRealm () { 173 return realm; 174 } 175 public Logger getLogger() { 176 return logger; 177 } 178}