/** * A private Class for ourself on the bus * * @author Yannick Jestin * @author http://www.tls.cena.fr/products/ivy/ * @since 1.2.4 * * CHANGELOG: * 1.2.4: * - adds a the threaded option for callbacks * - Matthieu's bugreport on unBindMsg() */ package fr.dgac.ivy ; import java.util.*; import gnu.regexp.*; class SelfIvyClient extends IvyClient { private Ivy bus; private static int serial=0; /* an unique ID for each regexp */ private Hashtable callbacks=new Hashtable(); private Hashtable threadedFlag=new Hashtable(); private boolean massThreaded=false; public void sendDirectMsg(int id,String message) { bus.directMessage(this,id,message); } public void sendDie(String message) { bus.dieReceived(this,0,message); } protected SelfIvyClient(Ivy bus,String appName) { this.bus=bus; this.protocol=Ivy.PROTOCOLVERSION; this.appName=appName; } synchronized protected int bindMsg(String sregexp, IvyMessageListener callback, boolean threaded ) throws IvyException { // creates a new binding (regexp,callback) try { RE re=new RE(sregexp); Integer key = new Integer(serial++); regexps.put(key,re); regexpsText.put(key,sregexp); callbacks.put(key,callback); threadedFlag.put(key,new Boolean(threaded)); return key.intValue(); } catch (REException ree) { throw new IvyException("Invalid regexp " + sregexp); } } synchronized protected void unBindMsg(int id) throws IvyException { Integer key = new Integer(id); if ( ( regexps.remove(key) == null ) || (regexpsText.remove(key) == null ) || (callbacks.remove(key) == null ) || (threadedFlag.remove(key) == null ) ) throw new IvyException("client wants to remove an unexistant regexp "+id); } synchronized protected boolean unBindMsg(String re) { for (Enumeration e=regexpsText.keys();e.hasMoreElements();) { Integer k = (Integer)e.nextElement(); if ( ((String)regexps.get(k)).compareTo(re) == 0) { try { bus.unBindMsg(k.intValue()); } catch (IvyException ie) { return false; } return true; } } return false; } protected int sendSelfMsg(String message) { int count = 0; for (Enumeration e = regexps.keys();e.hasMoreElements();) { Integer key = (Integer)e.nextElement(); RE regexp = (RE)regexps.get(key); String sre = (String)regexpsText.get(key); int nb = regexp.getNumSubs(); REMatch result = regexp.getMatch(message); if (result==null) continue; count++; callCallback(this,key,toArgs(nb,result)); } return count; } protected void callCallback(IvyClient client, Integer key, String[] tab) { IvyMessageListener callback=(IvyMessageListener)callbacks.get(key); boolean threaded=((Boolean)threadedFlag.get(key)).booleanValue(); if (callback==null) { System.out.println("(callCallback) Not regexp matching id "+key.intValue()); System.exit(0); } if (!threaded) { // runs the callback in the same thread callback.receive(client, tab); } else { // starts a new Thread for each callback ... new Runner(callback,client,tab); } } private String[] toArgs(int nb,REMatch result) { String[] args = new String[nb]; for(int sub=1;sub<=nb;sub++) { args[sub-1]=result.toString(sub); if (bus.doProtectNewlines) args[sub-1]=decode(args[sub-1]); } return args; } public String toString() { return "IvyClient (ourself)"+bus.appName+":"+appName; } // a class to perform the threaded execution of each new message // this is an experimental feature introduced in 1.2.4 class Runner implements Runnable { IvyMessageListener cb; IvyClient c; String[] args; private Thread t; public Runner(IvyMessageListener cb,IvyClient c,String[] args) { this.cb=cb; this.args=args; this.c=c; t=new Thread(Runner.this); bus.registerThread(t); t.start(); bus.unRegisterThread(t); } public void run() { cb.receive(c,args); } } // class Runner private void traceDebug(String s){ if (debug) System.out.println("-->SelfIvyClient "+bus.appName+":"+appName+"<-- "+s); } } /* EOF */