/** * terminal implementation in java of the ivyprobe. * * @author Yannick Jestin * @author http://www.tls.cena.fr/products/ivy/ * * (c) CENA * * Changelog: * 1.2.16 * - now uses the synchronized wrappers of the Java API for all collections * 1.2.14 * - uses the "new" for: loop construct of Java5 * - throws RuntimeException instead of System.exit(), allows code reuse * - switch from gnu regexp (deprecated) to the built in java regexp * 1.2.13 * - adds support for RESyntaxException * 1.2.12 * - .ping is back * 1.2.9 * - added the .time command * - added the .bound * * 1.2.8 * - added a fr.dgac.ivy.tools subsection * 1.2.7 * - added a .where function * - added a .bound function * - added a .dieall-yes-i-am-sure function * 1.2.6 * - no more java ping * 1.2.5 * - uses apache regexp instead of gnu regexp * 1.2.4 * - now uses the bindListener paradigm to display the binding/unbinding dynamically * - adds the -s (send to self) command line switch * 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 * list * 1.2.1 * - new -t switch to print the date for each ivy message * - now displays the correct domain list * - now has .bind and .unbind commands * 1.2.0 * - Probe can now send empty strings on keyboard input * - rewritten with a looping thread on stdin to allow a cleaner exit on die * message : not very good * - processes .help, .die , .quit and .bye commands * - it is possible to rename the JPROBE on the bus with the -n switch, it can * circumvent name collisions during tests * e.g: java fr.dgac.ivy.tools.Probe -n JPROBE2 * 1.0.10 * exits on end of user input * handles multiple domains - it was a IvyWatcher problem - */ package fr.dgac.ivy.tools ; import fr.dgac.ivy.* ; import java.io.*; import java.util.*; import gnu.getopt.Getopt; import java.util.regex.*; public class Probe implements IvyApplicationListener, IvyMessageListener, IvyBindListener, Runnable { public static final String helpCommands = "Available commands:\n"+ ".die CLIENT\t\t\t* sends a die message\n"+ ".dieall-yes-i-am-sure\t\t* sends a die to all clients\n"+ ".direct CLIENT ID MSG\t\t* sends the direct message to the client\n"+ ".bye\t\t\t\t* quits the probe\n"+ ".quit\t\t\t\t* quites the probe\n"+ ".list\t\t\t\t* lists the clients on the bus\n"+ ".bind REGEXP\t\t\t* subscribes to a regexp\n"+ ".unbind REGEXP\t\t\t* unsubscribes to a regexp\n"+ ".bound CLIENT\t\t\t* lists the subscriptions of a client, .bound * to get all\n"+ ".bound\t\t\t\t* lists the probe's subscriptions\n"+ ".where CLIENT\t\t\t* displays the host where a client runs\n"+ ".time COUNT MESSAGE\t\t\t* measures the time it takes to send COUNT messages\n"+ ".ping CLIENT\t\t\t* measures the roundtrip time in millisecond to reach a client\n" ; public static final String helpmsg = "usage: java fr.dgac.ivy.tools.Probe [options] [regexp]\n"+ "\t-b BUS\tspecifies the Ivy bus domain\n"+ "\t-c CLASS\tuses a message class CLASS=Word1,Word2,Word3...\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-s\tsends to self\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:c:dqsht"); int c; boolean timestamp=false; boolean quiet=false; boolean sendsToSelf=false; String domain=null; String name="JPROBE"; String[] messageClass=null; while ((c = opt.getopt()) != -1) switch (c) { case 'd': Properties sysProp = System.getProperties(); sysProp.put("IVY_DEBUG","yes"); break; case 'b': domain=opt.getOptarg(); break; case 'c': messageClass = opt.getOptarg().split(","); break; case 'n': name=opt.getOptarg(); break; case 'q': quiet=true; break; case 't': timestamp=true; break; case 's': sendsToSelf=true; break; case 'h': default: System.out.println(helpmsg); return; } 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); bus.addBindListener(p); bus.sendToSelf(sendsToSelf); if (messageClass!=null) { System.out.println("using a message class filter of "+messageClass.length+" elements"); for (String cls: messageClass) System.out.println("\t "+cls); bus.setFilter(messageClass); } for (int i=opt.getOptind();i Sent to " +bus.sendMsg(s)+" peers"); } catch (IvyException ie) { println("-> not sent, the message contains incorrect characters"); } } else if (m.matches()) { String target = m.group(1); int id = Integer.parseInt(m.group(2)); String message = m.group(3); Collectionv=bus.getIvyClientsByName(target); if (v.size()==0) println("no Ivy client with the name \""+target+"\""); try { for (IvyClient ic : v) ic.sendDirectMsg(id,message); } catch (IvyException ie) { println("-> not sent, the message contains incorrect characters"); } } else if (s.lastIndexOf(".dieall-yes-i-am-sure")>=0){ for (IvyClient ic: bus.getIvyClients()) ic.sendDie("java probe wants you to leave the bus"); } else if (s.lastIndexOf(".die ")>=0){ String target=s.substring(5); Collectionv=bus.getIvyClientsByName(target); if (v.size()==0) println("no Ivy client with the name \""+target+"\""); for (IvyClient ic: v) ic.sendDie("java probe wants you to leave the bus"); } else if (s.lastIndexOf(".unbind ")>=0){ String regexp=s.substring(8); if (bus.unBindMsg(regexp)) { println("you have unsubscribed to " + regexp); } else { println("you can't unsubscribe to " + regexp + ", your're not subscribed to it"); } } else if (s.lastIndexOf(".bound *")>=0){ int total=0; int boundedtotal=0; for (IvyClient ic: bus.getIvyClients()) { for (String r : ic.getRegexps()) { total++; if (r.startsWith("^")) boundedtotal++; println(ic.getApplicationName()+" has subscribed to: "+r); } System.out.println("total: "+total+", unbounded:"+(total-boundedtotal)); } } else if (s.lastIndexOf(".bound ")>=0){ int total=0; int boundedtotal=0; String target=s.substring(7); Collectionv=bus.getIvyClientsByName(target); if (v.size()==0) println("no Ivy client with the name \""+target+"\""); for (IvyClient ic:v) { for (String r : ic.getRegexps()) { total++; if (r.startsWith("^")) boundedtotal++; println(target+" has subscribed to: "+r); } System.out.println("total: "+total+", unbounded:"+(total-boundedtotal)); } } else if (s.lastIndexOf(".bound")>=0){ println("you have subscribed to:"); for (String re : bus.getSelfIvyClient().getRegexps()) println("\t"+re); } else if (s.lastIndexOf(".bind ")>=0){ String regexp=s.substring(6); try { bus.bindMsg(regexp,this); println("you have now subscribed to " + regexp); } catch (IvyException ie) { System.out.println("warning, the regular expression '" + regexp + "' is invalid. Not bound !"); } } else if ( (s.lastIndexOf(".quit")>=0)||(s.lastIndexOf(".bye")>=0)){ bus.stop(); return false; } else if (s.lastIndexOf(".list")>=0) { Collection c = bus.getIvyClients(); println(c.size()+" clients on the bus"); for (IvyClient ic: c) println("-> "+ic.getApplicationName()); } else if ( s.lastIndexOf(".ping ")>=0) { String target=s.substring(6); Collectionv=bus.getIvyClientsByName(target); if (v.size()==0) println("no Ivy client with the name \""+target+"\""); for (IvyClient ic:v) { try { ic.ping(new PingCallback() { public void pongReceived(IvyClient ic,int elapsedTime){ System.out.println("round trip to "+ic.getApplicationName()+" "+elapsedTime+" ms"); } }); } catch (IvyException ie) { println("-> ping not sent, the remote client must have disconnected"); } } } else if ( s.lastIndexOf(".where ")>=0) { String target=s.substring(7); Collectionv=bus.getIvyClientsByName(target); if (v.size()==0) println("no Ivy client with the name \""+target+"\""); for (IvyClient ic: v) println(target+" runs on "+ic.getHostName()); } else if (mtime.matches()) { long before = new java.util.Date().getTime(); int times=Integer.parseInt(mtime.group(1)); try { int n=0; for (int i=0;i it took "+(after-before)+"ms to send "+times+" to " +n+" peers"); } catch (IvyException ie) { println("-> not sent, the line contains incorrect characters"); } } else if ( s.lastIndexOf(".help")>=0) { println(helpCommands); } else if ( s.charAt(0)=='.') { println("this command is not recognized"); println(helpCommands); } else { try { println("-> Sent to " +bus.sendMsg(s)+" peers"); } catch (IvyException ie) { println("-> not sent, the line contains incorrect characters"); } } return true; } // parseCommand public void bindPerformed(IvyClient client,int id,String re) { String s=""; if (!bus.checkRegexp(re)) s=" WITH NO EFFECT, because of the filters"; println(client.getApplicationName() + " subscribes to " +re+s); } public void unbindPerformed(IvyClient client,int id,String re) { println(client.getApplicationName() + " unsubscribes to " +re ); } public void connect(IvyClient client) { println(client.getApplicationName() + " connected " ); } public void disconnect(IvyClient client) { println(client.getApplicationName() + " disconnected " ); } public void die(IvyClient client, int id,String msgarg) { println("received die msg from " + client.getApplicationName() +" with the message: "+msgarg+", 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) { println(client.getApplicationName() + " sent the direct Message, id: "+ id + ", arg: "+ arg ); } public void receive(IvyClient client, String[] args) { StringBuffer s=new StringBuffer(client.getApplicationName()); s.append(" sent"); for (String arg: args) { s.append(" '"); s.append(arg); s.append("'"); } println(s.toString()); } 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(); java.text.DateFormat df = java.text.DateFormat.getTimeInstance(); return "["+df.format(d)+"] "; } }