/** * 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.16 * - now uses the synchronized wrappers of the Java API for all collections * 1.2.14 * - uses autoboxing for Boolean * - switch from gnu regexp (deprecated) to the built in java regexp * - add generic types to declarations * 1.2.7: * - fixes a bug on unbindMsg(String) ( closes Matthieu's burreport ) * 1.2.6: * - jakarta regexp are not threadsafe, adding extra synch blocks * 1.2.5: * - uses apache regexp instead of gnu regexp * 1.2.4: * - adds a the threaded option for callbacks * - Matthieu's bugreport on unBindMsg() */ package fr.dgac.ivy ; import java.util.Map; import java.util.HashMap; import java.util.Collections; import java.util.regex.*; public class SelfIvyClient extends IvyClient { private Ivy bus; private static int serial=0; /* an unique ID for each regexp */ private Map callbacks= Collections.synchronizedMap(new HashMap()); private Map threadedFlag= Collections.synchronizedMap(new HashMap()); 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; } protected int bindMsg(String sregexp, IvyMessageListener callback, BindType type ) throws IvyException { // creates a new binding (regexp,callback) try { Pattern re=Pattern.compile(sregexp,Pattern.DOTALL); Integer key = serial++; regexps.put(key,re); regexpsText.put(key,sregexp); synchronized (callbacks) { callbacks.put(key,callback); } synchronized (threadedFlag) { threadedFlag.put(key,type); // use autoboxing of boolean } return key.intValue(); } catch (PatternSyntaxException ree) { throw new IvyException("Invalid regexp " + sregexp); } } protected synchronized void unBindMsg(int id) throws IvyException { Integer key = id; synchronized (regexps) { synchronized (callbacks) { synchronized (threadedFlag) { 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); } } } } // unbinds to the first regexp protected synchronized boolean unBindMsg(String re) { synchronized (regexpsText) { if (regexpsText.get(re) == null) return false; for (Integer k : regexpsText.keySet()) { if ( (regexpsText.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; traceDebug("trying to send to self the message <"+message+">"); for (Integer key : regexps.keySet() ) { Pattern regexp = regexps.get(key); String sre = regexpsText.get(key); synchronized(regexp) { traceDebug("checking against: "+sre); Matcher m = regexp.matcher(message); if (!m.matches()) { traceDebug("checking against: "+sre+" failed"); continue; } traceDebug("checking against: "+sre+" succeeded"); count++; callCallback(this,key,toArgs(m)); } } return count; } protected void callCallback(IvyClient client, Integer key, String[] tab) { IvyMessageListener callback; synchronized (callbacks) { callback=callbacks.get(key); } if (callback==null) { traceDebug("Not regexp matching id "+key.intValue()+", it must have been unsubscribed concurrently"); return; // DONE check that nasty synchro issue, test suite: Request } BindType type = threadedFlag.get(key); switch (type) { case NORMAL: // runs the callback in the same thread callback.receive(client, tab); // can tab can be faulty ?! TODO break; case ASYNC: // starts a new Thread for each callback ... ( Async API ) new Runner(callback,client,tab); break; case SWING: // deferes the callback to the Event Dispatch Thread new SwingRunner(callback,client,tab); break; } } private String[] toArgs(Matcher m) { String[] args= (m.groupCount()>0) ? new String[m.groupCount()] : new String[0]; //System.out.println("DEBUG "+args.length+" arguments"); for(int sub=0;subSelfIvyClient "+bus.getAppName()+":"+appName+"<-- "+s); } } /* EOF */