From a5ca9fd3f54783b7f9371d69574660f29fe0d10f Mon Sep 17 00:00:00 2001 From: jestin Date: Fri, 11 Aug 2000 09:15:47 +0000 Subject: Probe is the java implementation of ivyprobe(1). It supports the same syntax. --- src/Ivy.java | 362 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 236 insertions(+), 126 deletions(-) (limited to 'src/Ivy.java') diff --git a/src/Ivy.java b/src/Ivy.java index 8756c94..5b423eb 100755 --- a/src/Ivy.java +++ b/src/Ivy.java @@ -1,8 +1,11 @@ -// -// API de connexion au bus logiciel ivy -// -// - +/** + * a software bus package + * + * @author François-Régis Colin + * @author Yannick Jestin + * @author http://www.tls.cena.fr/products/ivy/ + * + */ package fr.dgac.ivy ; import java.net.*; @@ -11,179 +14,270 @@ import java.util.Vector; import java.util.Hashtable; import java.util.StringTokenizer; +/** + * A class connecting to the Ivy software bus. + * For example: + *
+ *Ivy bus = new Ivy("Dummy agent","ready",null);
+ *bus.bindMsg("(.*)",myMessageListener);
+ *bus.start(null);
+ *
+ */ public class Ivy implements Runnable, IvyApplicationListener { - static private boolean debug = (System.getProperty("IVY_DEBUG")!=null) ; - + /** + * the name of the application on the bus + */ + public String appName; + /** + * the protocol version number + */ + public static final int PROCOCOLVERSION = 3 ; + /** + * the port for the UDP rendez vous, if none is supplied + */ public static final int DEFAULT_PORT = 2010 ; + /** + * the domain for the UDP rendez vous + */ public static final String DEFAULT_DOMAIN = "127.255.255.255:"+DEFAULT_PORT; - public String appName; - private boolean ivyRunning = false; - private String ready_message = null; + + private static boolean debug = (System.getProperty("IVY_DEBUG")!=null) ; + private static int serial=0; /* an unique ID for each regexps */ private ServerSocket app; private IvyWatcher watch; private Thread server; - - private Hashtable regexp_out = new Hashtable(); private Hashtable callbacks = new Hashtable(); private Vector clients = new Vector(); private Vector ivyApplicationListenerList = new Vector(); private String messages_classes[] = null; - private int myport; /* Application port number */ - - public synchronized boolean ivyRunning(){ return ivyRunning; } + int applicationPort; /* Application port number */ + boolean ivyRunning = false; + Hashtable regexp_out = new Hashtable(); + String ready_message = null; + + /** + * Readies the structures for the software bus connexion. + * + * All the dirty work is done un the start() method + * @see #start + * @param name The name of your Ivy agent on the software bus + * @param message The hellow message you will send once ready + * @param appcb A callback handling the notification of connexions and + * disconnections, may be null + */ public Ivy( String name, String message, IvyApplicationListener appcb) { appName = name; ready_message = message; if ( appcb != null ) ivyApplicationListenerList.addElement( appcb ); } - void classes( String msg_classes[] ) { messages_classes = msg_classes; } - - public Hashtable getRegexpOut() { return regexp_out; } - - public String getReadyMessage() { return ready_message; } - - void addClient( Socket socket ) throws IOException { - IvyClient client = new IvyClient( this, socket); - clients.addElement( client ); - } - - void removeClient( IvyClient client ) { - clients.removeElement( client ); + /** + * connects the Ivy bus to a domain or list of domains + * @param domainbus a domain of the form 10.0.0:1234, it is similar to the + * netmask without the trailing .255. This will determine the meeting point + * of the different applications. Right now, this is done with an UDP + * broadcast. Beware of routing problems ! You can also use a comma + * separated list of domains. + * + */ + public void start(String domainbus) throws IvyException { + try { + app = new ServerSocket(0); + applicationPort = app.getLocalPort(); + } catch (IOException e) { + throw new IvyException("can't open TCP service socket " + e ); + } + traceDebug("TCP service open on port "+applicationPort); + watch = new IvyWatcher(this); + ivyRunning = true; + server = new Thread(this); + server.start(); + watch.start(getDomain(domainbus)); } - void callCallback(IvyClient client, Integer key, String msgarg) { - IvyMessageListener callback=(IvyMessageListener)callbacks.get(key); - if (callback==null){ - traceDebug("(callCallback) Not regexp matching id "+key.intValue()); - return; + /** + * disconnects from the Ivy bus. + */ + public void stop() { + try { + ivyRunning = false; + watch.stop(); + app.close(); + for ( int i = 0 ; i < clients.size(); i++ ) { + IvyClient client = (IvyClient)clients.elementAt(i); + client.close("normal Ivy Stopping..."); + // advertise that this is a normal + //close for debugging purposes + } + } catch (IOException e) { + traceDebug("IOexception Stop "); } - StringTokenizer st = new StringTokenizer(msgarg,IvyClient.EndArg); - String args[] = new String[st.countTokens()]; - int i=0; - while (st.hasMoreTokens()){ args[i++] = st.nextToken();} - callback.receive( client, args ); + clients.removeAllElements(); } - public int getApplicationPort() { return myport; } - + /** + * Performs a pattern matching according to everyone's regexps, and sends + * the results to the relevant ivy agents. + *

There is one thread for each client connected, we could also + * create another thread each time we send a message. + * @param message A String which will be compared to the regular + * expressions of the different clients + * @return the number of messages actually sent + */ public int sendMsg( String message ) { - int count = 0; - // envoie le message à tous les clients du bus - // TODO: il faudrait mettre une Thread emission par client */ + int count = 0; + // TODO: il faudrait mettre une Thread emission par client */ for ( int i = 0 ; i < clients.size(); i++ ) { IvyClient client = (IvyClient)clients.elementAt(i); count += client.sendMsg( message ); } - return count; + return count; } - static private int serial=0; + /** + * Subscribes to a regular expression. + * + * The callback will be executed with + * the saved parameters of the regexp as arguments when a message will sent + * by another agent. A program doesn't receive its own messages. + *

Example: + *
the Ivy agent A performs

b.bindMsg("^Hello (*)",cb);
+ *
the Ivy agent B performs
b2.sendMsg("Hello world");
+ *
a thread in A will uun the callback cb with its second argument set + * to a array of String, with one single element, "world" + * @param regexp a perl regular expression, groups are done with parenthesis + * @param callback any objects implementing the IvyMessageListener + * interface, on the AWT/Swing framework + * @return the id of the regular expression + */ public int bindMsg(String regexp, IvyMessageListener callback ) { - // associe une nouvelle regexp à un nouveau callback + // creates a new binding (regexp,callback) Integer key = new Integer(serial++); regexp_out.put(key,regexp); callbacks.put(key,callback ); - // indique aux autres clients la nouvelle regexp + // notifies the other clients this new regexp for (int i=0;iivy<-- "+s); } - - + // TODO find out if this is useful or not ... + private void classes( String msg_classes[] ) { + messages_classes = msg_classes; + } -} // class Ivy +} -- cgit v1.1