aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/Ivy.java85
-rwxr-xr-xsrc/IvyClient.java80
-rw-r--r--src/IvyDaemon.java140
-rwxr-xr-xsrc/IvyWatcher.java4
-rw-r--r--src/Makefile5
-rw-r--r--src/Probe.java178
6 files changed, 277 insertions, 215 deletions
diff --git a/src/Ivy.java b/src/Ivy.java
index b3f8bfb..fbc9161 100755
--- a/src/Ivy.java
+++ b/src/Ivy.java
@@ -1,20 +1,9 @@
/**
* a software bus package
*
- * @author François-Régis Colin
* @author Yannick Jestin
* @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a>
*
- */
-package fr.dgac.ivy ;
-
-import java.net.*;
-import java.io.*;
-import java.util.*;
-
-/**
- * A class connecting to the Ivy software bus.
- * For example:
*<pre>
*Ivy bus = new Ivy("Dummy agent","ready",null);
*bus.bindMsg("(.*)",myMessageListener);
@@ -22,25 +11,34 @@ import java.util.*;
*</pre>
*
* CHANGELOG:
+ * 1.2.3:
+ * - adds a IVYBUS property to propagate the domain once set. This way,
+ * children forked through Ivy java can inherit from the current value.
+ * - adds synchronized flags to allow early disconnexion
* 1.2.2:
- * - added the String domains(String d) function, in order to display the
+ * added the String domains(String d) function, in order to display the
* domain list
* 1.2.1:
- * - bus.start(null) now starts on DEFAULT_DOMAIN
- * - added the getDomains in order to correctly display the domain list
- * - checks if the serverThread exists before interrupting it
- * - no has unBindMsg(String)
+ * bus.start(null) now starts on DEFAULT_DOMAIN
+ * added the getDomains in order to correctly display the domain list
+ * checks if the serverThread exists before interrupting it
+ * no has unBindMsg(String)
* 1.2.0:
- * - setSoTimeout is back on the server socket
- * - added a regression test main()
- * - clients is now a Hashtable. the deletion now works better
- * - getIvyClientsByName allows the research of IvyClient by name
- * - getDomain doesnt throw IvyException anymore
- * - removed the close() disconnect(IvyClient c). Fixes a big badaboum bug
- * - getDomain becomes public
- * - adding the sendToSelf feature
- * - fixed the printStackTrace upon closing of the ServerSocket after a close()
+ * setSoTimeout is back on the server socket
+ * added a regression test main()
+ * clients is now a Hashtable. the deletion now works better
+ * getIvyClientsByName allows the research of IvyClient by name
+ * getDomain doesnt throw IvyException anymore
+ * removed the close() disconnect(IvyClient c). Fixes a big badaboum bug
+ * getDomain becomes public
+ * adding the sendToSelf feature
+ * fixed the printStackTrace upon closing of the ServerSocket after a close()
*/
+package fr.dgac.ivy ;
+import java.net.*;
+import java.io.*;
+import java.util.*;
+
public class Ivy implements Runnable {
/**
@@ -63,7 +61,7 @@ public class Ivy implements Runnable {
* the library version, useful for development purposes only, when java is
* invoked with -DIVY_DEBUG
*/
- public static final String libVersion ="1.2.2";
+ public static final String libVersion ="1.2.3";
private boolean debug;
private static int serial=0; /* an unique ID for each regexp */
@@ -116,6 +114,8 @@ public class Ivy implements Runnable {
*/
public void start(String domainbus) throws IvyException {
if (domainbus==null) domainbus=DEFAULT_DOMAIN;
+ Properties sysProp = System.getProperties();
+ sysProp.put("IVYBUS",domainbus);
try {
app = new ServerSocket(0);
app.setSoTimeout(TIMEOUTLENGTH);
@@ -152,8 +152,9 @@ public class Ivy implements Runnable {
/**
* disconnects from the Ivy bus
*/
- public void stop() {
- if (stopped ) return;
+ public synchronized void stop() {
+ if (stopped) return;
+ stopped=true;
traceDebug("beginning stopping the bus");
try {
// stopping the serverThread
@@ -173,7 +174,6 @@ public class Ivy implements Runnable {
traceDebug("IOexception Stop ");
}
traceDebug("the bus should have stopped so far");
- stopped = true;
}
/**
@@ -360,9 +360,9 @@ public class Ivy implements Runnable {
//
/////////////////////////////////////////////////////////////////:
- void addClient(Socket socket,boolean peerCalling) throws IOException {
- IvyClient client = new IvyClient(
- this, socket,peerCalling,new Integer(clientSerial++));
+ synchronized void addClient(Socket socket,boolean peerCalling) throws IOException {
+ if (stopped) return;
+ IvyClient client = new IvyClient( this, socket,peerCalling,new Integer(clientSerial++));
clients.put(client.getClientKey(),client);
traceDebug(getClientNames());
}
@@ -379,16 +379,16 @@ public class Ivy implements Runnable {
int index=0, last=0, length=s.length();
Vector v = new Vector();
if (length!=0) while (true) {
- index=s.indexOf(separator,last);
- if (index==-1) {
- v.addElement(s.substring(last,length));
- break;
- } else if (index<s.length()) {
- v.addElement(s.substring(last,index));
- last=index+1;
- } else {
- break;
- }
+ index=s.indexOf(separator,last);
+ if (index==-1) {
+ v.addElement(s.substring(last,length));
+ break;
+ } else if (index<s.length()) {
+ v.addElement(s.substring(last,index));
+ last=index+1;
+ } else {
+ break;
+ }
}
String[] tab = new String[v.size()];
v.copyInto(tab);
@@ -439,6 +439,7 @@ public class Ivy implements Runnable {
while(thisThread==serverThread){
try {
Socket socket = app.accept();
+ if ((thisThread!=serverThread)||stopped) break; // early disconnexion
addClient(socket,true); // the peer called me
} catch (InterruptedIOException ie) {
if (thisThread!=serverThread) break;
diff --git a/src/IvyClient.java b/src/IvyClient.java
index ba30d74..8cd330e 100755
--- a/src/IvyClient.java
+++ b/src/IvyClient.java
@@ -1,15 +1,6 @@
-package fr.dgac.ivy ;
-
-import java.lang.Thread;
-import java.net.*;
-import java.io.*;
-import java.util.*;
-import gnu.regexp.*;
-
/**
* A private Class for the the peers on the bus.
*
- * @author François-Régis Colin
* @author Yannick Jestin
* @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a>
*
@@ -19,6 +10,9 @@ import gnu.regexp.*;
* created for each remote client.
*
* CHANGELOG:
+ * 1.2.3:
+ * - direct Messages
+ * - deals with early stops during readline
* 1.2.2:
* - cleared a bug causing the CPU to be eating when a remote client left the
* bus. closes Damien Figarol bug reported on december, 2002. It is handled
@@ -38,6 +32,12 @@ import gnu.regexp.*;
* 1.0.10:
* - removed the timeout bug eating all the CPU resources
*/
+package fr.dgac.ivy ;
+import java.lang.Thread;
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import gnu.regexp.*;
public class IvyClient implements Runnable {
@@ -134,6 +134,27 @@ public class IvyClient implements Runnable {
public void delRegexp(int id) {send( DelRegexp,id,"");}
/**
+ * sends a direct message to the peer
+ * @param id the numeric value provided to the remote client
+ * @param message the string that will be match-tested
+ */
+ public void sendDirectMsg(int id,String message) { send(DirectMsg,id,message); }
+
+ /**
+ * closes the connexion to the peer.
+ * @param notify should I send Bye message ?
+ * the thread managing the socket is stopped
+ */
+ void close(boolean notify) throws IOException {
+ traceDebug("closing connexion to "+appName);
+ if (doping&&(pinger!=null)) { pinger.stopPinging(); }
+ if (notify) sendBye("hasta la vista");
+ stopListening();
+ // bus.clientDisconnect(this);
+ socket.close(); // should I also close in and out ?
+ }
+
+ /**
* sends the substrings of a message to the peer for each matching regexp.
* @param message the string that will be match-tested
* @return the number of messages sent to the peer
@@ -152,20 +173,6 @@ public class IvyClient implements Runnable {
return count;
}
- /**
- * closes the connexion to the peer.
- * @param notify should I send Bye message ?
- * the thread managing the socket is stopped
- */
- void close(boolean notify) throws IOException {
- traceDebug("closing connexion to "+appName);
- if (doping&&(pinger!=null)) { pinger.stopPinging(); }
- if (notify) sendBye("hasta la vista");
- stopListening();
- // bus.clientDisconnect(this);
- socket.close(); // should I also close in and out ?
- }
-
void stopListening() {
Thread t = clientThread;
if (t==null) return; // we can be summoned to quit from two path at a time
@@ -189,12 +196,17 @@ public class IvyClient implements Runnable {
*/
public void run() {
Thread thisThread = Thread.currentThread();
- traceDebug("Connected from "+ socket.getInetAddress().getHostName()+ ":"+socket.getPort());
String msg = null;
- // System.out.println("IvyClient Thread started"); // THREADDEBUG
- while ( clientThread==thisThread ) {
+ try {
+ traceDebug("Connected from "+ socket.getInetAddress().getHostName()+ ":"+socket.getPort());
+ } catch (Exception ie) {
+ traceDebug("Interrupted while resolving remote hostname");
+ }
+ traceDebug("Thread started");
+ while (clientThread==thisThread) {
try {
if ((msg=in.readLine()) != null ) {
+ if (clientThread!=thisThread) break; // early stop during readLine()
if (doping && (pingerThread!=null)) pingerThread.interrupt();
newParseMsg(msg);
} else {
@@ -207,12 +219,12 @@ public class IvyClient implements Runnable {
System.out.println("I have been interrupted. I'm about to leave my thread loop");
if (thisThread!=clientThread) break;
} catch (IOException e) {
- if (clientThread!=thisThread) break;
- System.out.println("abnormally Disconnected from "+ socket.getInetAddress().getHostName()+":"+socket.getPort());
+ traceDebug("abnormally Disconnected from "+ socket.getInetAddress().getHostName()+":"+socket.getPort());
+ break;
}
- } // while
+ }
traceDebug("normally Disconnected from "+ appName);
- // System.out.println("IvyClient Thread stopped"); // THREADDEBUG
+ traceDebug("Thread stopped");
}
private void sendBuffer( String buffer ) throws IvyException {
@@ -420,6 +432,7 @@ public class IvyClient implements Runnable {
public String toString() {
return "IvyClient "+bus.appName+":"+appName;
}
+
private void traceDebug(String s){
if (debug) System.out.println("-->IvyClient "+bus.appName+":"+appName+"<-- "+s);
}
@@ -428,7 +441,7 @@ public class IvyClient implements Runnable {
boolean isPinging = false;
public void run() {
isPinging=true;
- // System.out.println("Pinger Thread started"); // THREADDEBUG
+ traceDebug("Pinger Thread started");
while (isPinging) {
try {
Thread.sleep(PINGTIMEOUT);
@@ -436,10 +449,9 @@ public class IvyClient implements Runnable {
} catch (InterruptedException ie) {
}
}
- // System.out.println("Pinger Thread stopped"); // THREADDEBUG
+ traceDebug("Pinger Thread stopped");
}
public void stopPinging() { isPinging=false; pingerThread.interrupt();}
}
-} // class IvyClient
-/* EOF */
+}
diff --git a/src/IvyDaemon.java b/src/IvyDaemon.java
index 72c83ec..56019c1 100644
--- a/src/IvyDaemon.java
+++ b/src/IvyDaemon.java
@@ -1,79 +1,92 @@
/**
- * sample implementation of an Ivy Daemon, like ivyd.
- * @author Yannick Jestin
- * @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a>
- */
-package fr.dgac.ivy ;
-import java.io.*;
-import java.net.*;
-import java.util.Properties ;
-import gnu.getopt.Getopt;
-
-/**
- * toy tool to send anonymous messages to an Ivy bus through a simple tcp
- * socket.
- * IvyDaemon runs in the background and forwards all the incoming trafic to
- * the bus, line by line. The default port is 3456.
+ * IvyDaemon: simple TCP to Ivy relay.
*
* @author Yannick Jestin
* @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a>
*
+ * This is a sample implementation of an Ivy Daemon, like ivyd
+ * sends anonymous messages to an Ivy bus through a simple tcp socket,
+ * line by line. The default port is 3456.
+ *
+ * (c) CENA
+ *
* changelog:
+ * 1.2.3
+ * - adds the traceDebug
+ * - uses the clientThread paradigm to programm the thread sync
+ * - invalid port number as a command line argument now stops the program
+ * - cleans up the code
+ * - adds a "quiet" option on the command line
* 1.2.2
- * changes the setProperty to a backward compatible construct
+ * - changes the setProperty to a backward compatible construct
* 1.0.12
- * - class goes public access !
+ * - class goes public access !
*/
+package fr.dgac.ivy ;
+import java.io.*;
+import java.net.*;
+import java.util.Properties ;
+import gnu.getopt.Getopt;
public class IvyDaemon implements Runnable {
- public static int DEFAULT_SERVICE_PORT = 3456 ;
- ServerSocket serviceSocket;
- boolean isRunning=false;
- Ivy bus;
- public static void main(String[] args) {
- Getopt opt = new Getopt("IvyDaemon",args,"b:dp:");
+ private ServerSocket serviceSocket;
+ private boolean isRunning=false;
+ private static boolean debug = (System.getProperty("IVY_DEBUG")!=null) ;
+ private volatile Thread clientThread;// volatile to ensure the quick communication
+ private Ivy bus;
+
+ public static int DEFAULT_SERVICE_PORT = 3456 ;
+ public static final String DEFAULTNAME = "IvyDaemon";
+ public static final String helpmsg = "usage: java fr.dgac.ivy.IvyDaemon [options]\n\t-b BUS\tspecifies the Ivy bus domain\n\t-p\tport number, default "+DEFAULT_SERVICE_PORT+"\n\t-n ivyname (default "+DEFAULTNAME+")\n\t-q\tquiet, no tty output\n\t-d\tdebug\n\t-h\thelp\nListens on the TCP port, and sends each line read on the Ivy bus. It is useful to launch one Ivy Daemon and let scripts send their message on the bus.\n";
+ public static void main(String[] args) throws IvyException, IOException {
+ Ivy bus;
+ Getopt opt = new Getopt("IvyDaemon",args,"n:b:dqp:h");
int c;
int servicePort = DEFAULT_SERVICE_PORT;
- String domain=Ivy.DEFAULT_DOMAIN;
+ String name = DEFAULTNAME;
+ boolean quiet = false;
+ String domain=Ivy.getDomain(null);
while ((c = opt.getopt()) != -1) switch (c) {
+ case 'n':
+ name=opt.getOptarg();
+ break;
case 'b':
domain=opt.getOptarg();
break;
+ case 'q':
+ quiet=true;
+ break;
case 'd':
Properties sysProp = System.getProperties();
sysProp.put("IVY_DEBUG","yes");
- //System.setProperty("IVY_DEBUG","yes");
break;
case 'p':
String s="";
try {
servicePort = Integer.parseInt(s=opt.getOptarg());
} catch (NumberFormatException nfe) {
- System.out.println("Invalid port number: " + s +
- "switching to default port "+servicePort);
+ System.out.println("Invalid port number: " + s );
+ System.exit(0);
}
break;
+ case 'h':
default:
+ System.out.println(helpmsg);
+ System.exit(0);
}
- IvyDaemon d = new IvyDaemon(domain,servicePort);
+ bus=new Ivy(name,name+" ready",null);
+ if (!quiet) System.out.println("broadcasting on "+bus.domains(domain));
+ bus.start(domain);
+ if (!quiet) System.out.println("listening on "+servicePort);
+ IvyDaemon d = new IvyDaemon(bus,servicePort);
}
- public IvyDaemon(String domain,int servicePort) {
- // connexion to the Bus
- try {
- bus=new Ivy("IvyDaemon","IvyDaemon ready",null);
- System.out.println("broadcasting on "+domain);
- bus.start(domain);
- serviceSocket = new ServerSocket(servicePort) ;
- System.out.println("listening on "+servicePort);
- isRunning=true;
- (new Thread(this)).start(); // loops on the service Socket, awaiting connexion
- } catch (IvyException ie) {
- System.out.println("Caught an exception. quitting. "+ie.getMessage());
- } catch (IOException ioe) {
- System.out.println("Caught an IOexception. quitting. "+ioe.getMessage());
- }
+ public IvyDaemon(Ivy bus,int servicePort) throws IOException {
+ this.bus=bus;
+ serviceSocket = new ServerSocket(servicePort) ;
+ clientThread=new Thread(this);
+ clientThread.start();
}
/*
@@ -81,33 +94,44 @@ public class IvyDaemon implements Runnable {
* it could be a thread, but as long as we've got one ....
*/
public void run() {
- // System.out.println("IvyDaemon Thread started"); // THREADDEBUG
- while(isRunning){
+ Thread thisThread = Thread.currentThread();
+ traceDebug("Thread started");
+ while ( clientThread==thisThread ) {
try {
- Socket socket = serviceSocket.accept();
- new SubReader(
- new BufferedReader(new InputStreamReader(socket.getInputStream())));
+ new SubReader(serviceSocket.accept());
} catch( IOException e ) {
- System.out.println("IvyDaemon DEBUG TCP socket reader caught an exception " + e.getMessage());
+ traceDebug("TCP socket reader caught an exception " + e.getMessage());
}
}
- // System.out.println("IvyDaemon Thread stopped"); // THREADDEBUG
+ traceDebug("Thread stopped");
}
class SubReader extends Thread {
BufferedReader in;
- SubReader(BufferedReader in) {this.in=in;start();}
+ SubReader(Socket socket) throws IOException {
+ in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
+ start();
+ }
public void run() {
- // System.out.println("Subreader Thread started"); // THREADDEBUG
+ traceDebug("Subreader Thread started");
String msg = null;
try {
- while ( ((msg=in.readLine()) != null )) { bus.sendMsg(msg); }
+ while (true) {
+ msg=in.readLine();
+ if (msg==null) break;
+ bus.sendMsg(msg);
+ }
} catch (IOException ioe) {
- System.out.println("exception ..." + ioe.getMessage());
+ traceDebug("Subreader exception ...");
+ ioe.printStackTrace();
+ System.exit(0);
}
- // System.out.println("Subreader Thread stopped"); // THREADDEBUG
+ traceDebug("Subreader Thread stopped");
}
- } // subclass SubReader
+ }
+
+ private void traceDebug(String s){
+ if (debug) System.out.println("-->IvyDaemon "+bus.appName+"<-- "+s);
+ }
-} // class IvyDaemon
-// EOF
+}
diff --git a/src/IvyWatcher.java b/src/IvyWatcher.java
index 7157c18..b54a08f 100755
--- a/src/IvyWatcher.java
+++ b/src/IvyWatcher.java
@@ -22,6 +22,9 @@ import java.util.Enumeration;
* thing.
*
* CHANGELOG:
+ * 1.2.3:
+ * - checks whether I have been interrupted just after the receive (start()
+ * then stop() immediately).
* 1.2.1:
* - changed the fill character from 0 to 10, in order to prevent a nasty bug
* on Windows XP machines
@@ -87,6 +90,7 @@ class IvyWatcher implements Runnable {
int port;
try {
broadcast.receive(packet);
+ if (listenThread!=thisThread) break; // I was summoned to leave during the receive
String msg = new String(packet.getData()) ;
for (int i=0;i<buf.length;i++) { buf[i]=10; }
// clean up the buffer after each message
diff --git a/src/Makefile b/src/Makefile
index 1f5d2d8..caaeb90 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,11 +1,12 @@
# Be sure to set this before compiling ...
-RTPATH = /usr/lib/j2re1.3/lib/rt.jar
-# RTPATH = /usr/local/j2sdk1.4.1/jre/lib/rt.jar
+ RTPATH = /usr/lib/j2re1.3/lib/rt.jar
+RTPATH = /usr/local/j2sdk1.4.1/jre/lib/rt.jar
JIKESPATH = ${RTPATH}:/usr/share/java/gnu.getopt.jar:/usr/share/java/repository
JAVACOPTS = -d . -deprecation
.SUFFIXES: .java .class
SRCS = *.java
OBJS = $(SRCS:.java=.class)
+ #JAVAC = gcj-3.2 -classpath $(JIKESPATH)
JAVAC = jikes -classpath $(JIKESPATH)
#JAVAC = javac
DOCS = ../doc/html/api
diff --git a/src/Probe.java b/src/Probe.java
index d560298..bd37089 100644
--- a/src/Probe.java
+++ b/src/Probe.java
@@ -1,15 +1,19 @@
-package fr.dgac.ivy ;
-import java.io.*;
-import java.util.*;
-import gnu.getopt.Getopt;
-
/**
* terminal implementation in java of the ivyprobe.
+ *
* @author Yannick Jestin
* @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a>
- *
+ *
+ * (c) CENA
*
* Changelog:
+ * 1.2.3
+ * - now allows directMessages with the .direct command
+ * - the parseMsg is being rewritten with regexps
+ * - now handles the IVY_DEBUG property
+ * - now handles the -q quiet option
+ * - now handles the ^D ( end of input ) in a clean fashion
+ * - the constructor is public, you can embed a Probe in other programs
* 1.2.2
* - changes setProperty to a backward-compatible construct
* - now uses the bus.domains(String domain) in order to display the domain
@@ -30,47 +34,45 @@ import gnu.getopt.Getopt;
* exits on end of user input
* handles multiple domains - it was a IvyWatcher problem -
*/
-class Probe implements IvyApplicationListener, IvyMessageListener, Runnable {
+package fr.dgac.ivy ;
+import java.io.*;
+import java.util.*;
+import gnu.getopt.Getopt;
+import gnu.regexp.*;
+
+public class Probe implements IvyApplicationListener, IvyMessageListener, Runnable {
+
+ public static final String helpCommands = "Available commands:\n.die CLIENTNAME sends a die message\n.direct CLIENTNAME ID MESSAGE sends the direct message to the client, with a message id set to the numerical ID\n.bye quits the application\n.quit idem\n.list lists the available clients\n.ping sends a ping request if IVY_PING is enabled\n.bind REGEXP binds to a regexp at runtime\n.unbind REGEXP unbinds to a regexp at runtime";
- /**
- * help message for the standalone program
- */
- public static final String helpCommands = "Available commands:\n.die CLIENTNAME sends a die message\n.bye quits the application\n.quit idem\n.list lists the available clients\n.ping sends a ping request if IVY_PING is enabled\n.bind REGEXP binds to a regexp at runtime\n.unbind REGEXP unbinds to a regexp at runtime";
public static final String helpmsg = "usage: java fr.dgac.ivy.Probe [options] [regexp]\n\t-b BUS\tspecifies the Ivy bus domain\n\t-n ivyname (default JPROBE)\n\t-q\tquiet, no tty output\n\t-d\tdebug\n\t-t\ttime stamp each message\n\t-h\thelp\n\n\t regexp is a Perl5 compatible regular expression";
public static void main(String[] args) throws IvyException {
- Getopt opt = new Getopt("Probe",args,"n:b:dht");
+ Getopt opt = new Getopt("Probe",args,"n:b:dqht");
int c;
boolean timestamp=false;
+ boolean quiet=false;
String domain=Ivy.getDomain(null);
String name="JPROBE";
while ((c = opt.getopt()) != -1) switch (c) {
- case 'b':
- domain=opt.getOptarg();
- break;
- case 'n':
- name=opt.getOptarg();
- break;
- case 't':
- timestamp=true;
- break;
case 'd':
Properties sysProp = System.getProperties();
sysProp.put("IVY_DEBUG","yes");
- //System.setProperty("IVY_DEBUG","yes");
break;
+ case 'b': domain=opt.getOptarg(); break;
+ case 'n': name=opt.getOptarg(); break;
+ case 'q': quiet=true; break;
+ case 't': timestamp=true; break;
case 'h':
- default:
- System.out.println(helpmsg);
- System.exit(0);
- } // getopt
- Probe p = new Probe(timestamp);
- Ivy bus=new Ivy(name,name+" ready",p);
+ default: System.out.println(helpmsg); System.exit(0);
+ }
+ Probe p = new Probe(new BufferedReader(new InputStreamReader(System.in)),timestamp,quiet,System.getProperty("IVY_DEBUG")!=null);
+ p.setExitOnDie(true);
+ Ivy bus=new Ivy(name,name+" ready",null);
for (int i=opt.getOptind();i<args.length;i++) {
- System.out.println("you want to subscribe to " + args[i]);
+ if (!quiet) System.out.println("you want to subscribe to " + args[i]);
bus.bindMsg(args[i],p);
}
- System.out.println(bus.domains(domain));
+ if (!quiet) System.out.println(bus.domains(domain));
bus.start(domain);
p.start(bus);
}
@@ -78,75 +80,94 @@ class Probe implements IvyApplicationListener, IvyMessageListener, Runnable {
private BufferedReader in;
private volatile Thread looperThread;
private Ivy bus;
- private boolean timestamp;
+ private boolean timestamp,quiet,debug,exitOnDie=false;
+ private RE directMsgRE;
- Probe(boolean timestamp) {
- in = new BufferedReader(new InputStreamReader(System.in));
- looperThread=new Thread(this);
+
+ public Probe(BufferedReader in, boolean timestamp,boolean quiet,boolean debug) {
+ this.in=in;
this.timestamp=timestamp;
+ this.quiet=quiet;
+ this.debug = debug;
+ try {
+ directMsgRE = new RE("^\\.direct ([^ ]*) ([0-9]+) (.*)");
+ } catch (REException ree) {
+ System.err.println("Regexp fatal error in the Probe program.");
+ ree.printStackTrace();
+ System.exit(0);
+ }
}
- public void start(Ivy bus) {
+ public void start(Ivy bus) throws IvyException {
+ if (looperThread!=null) throw new IvyException("Probe already started");
this.bus=bus;
+ bus.addApplicationListener(this);
+ looperThread=new Thread(this);
looperThread.start();
}
+ public void setExitOnDie(boolean b) { exitOnDie=b; }
+
public void run() {
- // System.out.println("Probe Thread started"); // THREADDEBUG
+ traceDebug("Thread started");
Thread thisThread=Thread.currentThread();
String s;
+ // "infinite" loop on keyboard input
while (looperThread==thisThread) {
- // infinite loop on keyboard input
try {
s=in.readLine();
+ if (s==null) break;
parseCommand(s);
} catch (NullPointerException e) {
// EOF triggered by a ^D, for instance
- bus.stop();
+ break;
} catch (IOException e) {
- System.out.println("ioe ?");
- e.printStackTrace();
- bus.stop();
- } catch (InterruptedException ie) {
- System.out.println("allo ?");
+ // System input was closed
+ break;
}
- } //while
- System.out.println("End of looping");
- // System.out.println("Probe Thread stopped"); // THREADDEBUG
- System.exit(0);
+ }
+ println("End of input. Good bye !");
+ bus.stop();
+ traceDebug("Probe Thread stopped");
}
- void parseCommand(String s) throws IOException, InterruptedException {
- // System.out.println("parsing the ["+s+"] (length "+s.length()+") string");
+ void parseCommand(String s) throws IOException {
+ REMatch result;
+ traceDebug("parsing the ["+s+"] (length "+s.length()+") string");
// crude parsing of the ".xyz" commands
- // TODO use regexps instends of String.lastIndexOf(String)
+ // TODO use regexps instends of String.lastIndexOf(String). Example
+ // provided with .direct !
if (s.length()==0) {
- System.out.println(date()+"-> Sent to " +bus.sendMsg(s)+" peers");
+ println("-> Sent to " +bus.sendMsg(s)+" peers");
+ } else if ((result=directMsgRE.getMatch(s))!=null) {
+ String target = result.toString(1);
+ int id = Integer.parseInt(result.toString(2));
+ String message = result.toString(3);
+ Vector v=bus.getIvyClientsByName(target);
+ if (v.size()==0) println("no Ivy client with the name \""+target+"\"");
+ for (int i=0;i<v.size();i++) ((IvyClient)v.elementAt(i)).sendDirectMsg(id,message);
+ return;
} else if (s.lastIndexOf(".die ")>=0){
String target=s.substring(5);
Vector v=bus.getIvyClientsByName(target);
- if (v.size()==0) {
- System.out.println("no Ivy client with the name \""+target+"\"");
- }
- for (int i=0;i<v.size();i++) {
- ((IvyClient)v.elementAt(i)).sendDie();
- }
+ if (v.size()==0) println("no Ivy client with the name \""+target+"\"");
+ for (int i=0;i<v.size();i++) ((IvyClient)v.elementAt(i)).sendDie();
} else if (s.lastIndexOf(".unbind ")>=0){
String regexp=s.substring(8);
if (bus.unBindMsg(regexp)) {
- System.out.println("you want to unsubscribe to " + regexp);
+ println("you want to unsubscribe to " + regexp);
} else {
- System.out.println("you can't unsubscribe to " + regexp + ", your're not subscribed to it");
+ println("you can't unsubscribe to " + regexp + ", your're not subscribed to it");
}
} else if (s.lastIndexOf(".bind ")>=0){
String regexp=s.substring(6);
- System.out.println("you want to subscribe to " + regexp);
+ println("you want to subscribe to " + regexp);
bus.bindMsg(regexp,this);
} else if (s.lastIndexOf(".ping ")>=0){
String target=s.substring(6);
Vector v=bus.getIvyClientsByName(target);
if (v.size()==0) {
- System.out.println("no Ivy client with the name \""+target+"\"");
+ println("no Ivy client with the name \""+target+"\"");
}
for (int i=0;i<v.size();i++) {
((IvyClient)v.elementAt(i)).sendPing("test");
@@ -156,49 +177,48 @@ class Probe implements IvyApplicationListener, IvyMessageListener, Runnable {
System.exit(0);
} else if (s.lastIndexOf(".list")>=0) {
Vector v = bus.getIvyClients();
- System.out.println(v.size()+" clients on the bus");
+ println(v.size()+" clients on the bus");
for (int i=0;i<v.size();i++) {
- System.out.println("-> "+((IvyClient)v.elementAt(i)).getApplicationName());
+ println("-> "+((IvyClient)v.elementAt(i)).getApplicationName());
}
} else if ( s.lastIndexOf(".help")>=0) {
- System.out.println(helpCommands);
+ println(helpCommands);
} else if ( s.charAt(0)=='.') {
- System.out.println("this command is not recognized");
- System.out.println(helpCommands);
+ println("this command is not recognized");
+ println(helpCommands);
} else {
- System.out.println(date()+"-> Sent to " +bus.sendMsg(s)+" peers");
+ println("-> Sent to " +bus.sendMsg(s)+" peers");
}
} // parseCommand
public void connect(IvyClient client) {
- System.out.println(client.getApplicationName() + " connected " );
+ println(client.getApplicationName() + " connected " );
for (java.util.Enumeration e=client.getRegexps();e.hasMoreElements();)
- System.out.println(client.getApplicationName() + " subscribes to "
- +e.nextElement() );
+ println(client.getApplicationName() + " subscribes to " +e.nextElement() );
}
public void disconnect(IvyClient client) {
- System.out.println(client.getApplicationName() + " disconnected " );
+ println(client.getApplicationName() + " disconnected " );
}
public void die(IvyClient client, int id) {
- System.out.println("received die msg from " + client.getApplicationName() );
- Thread t = looperThread;
- looperThread = null;
- t.interrupt(); // TODO does'nt work
- System.exit(0);
+ println("received die msg from " + client.getApplicationName() +" good bye");
+ /* I cannot stop the readLine(), because it is native code */
+ if (exitOnDie) System.exit(0);
}
public void directMessage(IvyClient client, int id, String arg) {
- System.out.println(client.getApplicationName() + " direct Message "+ id + arg );
+ println(client.getApplicationName() + " direct Message "+ id + arg );
}
public void receive(IvyClient client, String[] args) {
- String s=date()+client.getApplicationName() + " sent";
+ String s=client.getApplicationName() + " sent";
for (int i=0;i<args.length;i++) s+=" '"+args[i]+"'";
- System.out.println(s);
+ println(s);
}
+ private void traceDebug(String s){ if (debug) System.out.println("-->Probe<-- "+s); }
+ private void println(String s){ if (!quiet) System.out.println(date()+s); }
private String date() {
if (!timestamp) return "";
Date d = new Date();