diff options
author | jestin | 2005-07-06 20:03:49 +0000 |
---|---|---|
committer | jestin | 2005-07-06 20:03:49 +0000 |
commit | 0cef96242b0e0aa10b4b33ee0f4b175048dbe3e0 (patch) | |
tree | 06afd0e92815bcdfa856a67c765862b551e39e4d /src/Ivy.java | |
parent | fe015aed1f9aa5f2d7247f9262d7f12c59536379 (diff) | |
download | ivy-java-0cef96242b0e0aa10b4b33ee0f4b175048dbe3e0.zip ivy-java-0cef96242b0e0aa10b4b33ee0f4b175048dbe3e0.tar.gz ivy-java-0cef96242b0e0aa10b4b33ee0f4b175048dbe3e0.tar.bz2 ivy-java-0cef96242b0e0aa10b4b33ee0f4b175048dbe3e0.tar.xz |
Voir les fichiers eux-même pour les nouveautés. Préparation de 1.2.8
Diffstat (limited to 'src/Ivy.java')
-rwxr-xr-x | src/Ivy.java | 116 |
1 files changed, 103 insertions, 13 deletions
diff --git a/src/Ivy.java b/src/Ivy.java index 3236ba4..2fc6307 100755 --- a/src/Ivy.java +++ b/src/Ivy.java @@ -13,6 +13,13 @@ *</pre> * * CHANGELOG: + * 1.2.8: + * - added getDomainArgs(String,String[]) as a facility to parse the + * command line in search of a -b domain + * - added getWBUId(), un function returning a string ID to perform + * queries, computed strings look like IDTest0:1105029280616:1005891134 + * - empties the watchers vector after a stop(), and handles the "stopped" + * better, FIXES FJ's bugreport stop/start * 1.2.7: * - minor fixes for accessing static final values * 1.2.6: @@ -71,13 +78,14 @@ package fr.dgac.ivy ; import java.net.*; import java.io.*; import java.util.*; +import gnu.getopt.Getopt; public class Ivy implements Runnable { /** * the name of the application on the bus */ - protected String appName; + String appName; /** * the protocol version number */ @@ -95,7 +103,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.7"; + public static final String libVersion ="1.2.8"; private boolean debug; private ServerSocket app; @@ -106,7 +114,7 @@ public class Ivy implements Runnable { private Vector ivyApplicationListenerList = new Vector(); private Vector ivyBindListenerList = new Vector(); private Vector sendThreads = new Vector(); - private boolean stopped = false; + private boolean stopped=true; protected int applicationPort; /* Application port number */ protected String ready_message = null; protected boolean doProtectNewlines = false ; @@ -115,6 +123,8 @@ public class Ivy implements Runnable { public final static int TIMEOUTLENGTH = 3000; private static int serial=0; private int myserial=serial++; + static long current = System.currentTimeMillis(); + private static java.util.Random generator = new java.util.Random(current*(serial+1)); /** * Readies the structures for the software bus connexion. @@ -191,6 +201,8 @@ public class Ivy implements Runnable { * */ public void start(String domainbus) throws IvyException { + if (!stopped) throw new IvyException("cannot start a bus that's already started"); + stopped=false; if (domainbus==null) domainbus=getDomain(null); Properties sysProp = System.getProperties(); sysProp.put("IVYBUS",domainbus); @@ -247,13 +259,15 @@ public class Ivy implements Runnable { Thread t=serverThread; serverThread=null; if (t!=null) t.interrupt(); // The serverThread might be stopped even before having been created + // TODO BUG avec gcj+kaffe, le close() reste pendu et ne rend pas la main app.close(); // stopping the IvyWatchers for (int i=0;i<watchers.size();i++){ ((IvyWatcher)watchers.elementAt(i)).stop(); } + watchers.clear(); // stopping the remaining IvyClients for (Enumeration e=clients.elements();e.hasMoreElements();) { IvyClient c = (IvyClient)e.nextElement(); - c.close(true); + if (c!=null) c.close(true); removeClient(c); } } catch (IOException e) { @@ -359,7 +373,8 @@ public class Ivy implements Runnable { * * The callback will be executed with * the saved parameters of the regexp as arguments when a message will sent - * by another agent. A program <em>doesn't</em> receive its own messages. + * by another agent. A program <em>doesn't</em> receive its own messages, + * except if sendToSelf() is set to true. * <p>Example: * <br>the Ivy agent A performs <pre>b.bindMsg("^Hello (*)",cb);</pre> * <br>the Ivy agent B performs <pre>b2.sendMsg("Hello world");</pre> @@ -385,6 +400,25 @@ public class Ivy implements Runnable { } /** + * Subscribes to a regular expression for one time only, useful for + * requests, in cunjunction with getWBUId() + * + * The callback will be executed once and only once, and the agent will + * unsubscribe + * @since 1.2.8 + * @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 bindMsgOnce(String sregexp, IvyMessageListener callback ) throws IvyException { + Once once = new Once(callback); + int id = bindMsg(sregexp,once); + once.setRegexpId(id); + return id; + } + + /** * unsubscribes a regular expression * * @param id the id of the regular expression, returned when it was bound @@ -452,6 +486,27 @@ public class Ivy implements Runnable { } } + // a private class used by bindMsgOnce, to ensure that a callback will be + // executed once, and only once + private class Once implements IvyMessageListener { + boolean received=false; + int id=-1; + IvyMessageListener callback=null; + Once(IvyMessageListener callback){this.callback=callback;} + void setRegexpId(int id){this.id=id;} + public void receive(IvyClient ic,String[] args){ + synchronized(this) { + // synchronized because it will most likely be called + // concurrently, and I *do* want to ensure that it won't + // execute twice + if (received||(callback==null)||(id==-1)) return; + received=true; + try {Ivy.this.unBindMsg(id);} catch (IvyException ie) { ie.printStackTrace(); } + callback.receive(ic,args); + } + } + } + /* invokes the application listeners upon arrival of a new Ivy client */ protected void clientConnects(IvyClient client){ for ( int i = 0 ; i < ivyApplicationListenerList.size(); i++ ) { @@ -480,7 +535,6 @@ public class Ivy implements Runnable { } } - /* * invokes the application listeners when we are summoned to die * then stops @@ -548,27 +602,61 @@ public class Ivy implements Runnable { return tab; } - public static String getDomain(String domainbus) { + /** + * returns the domain bus + * + * @param domainbus if non null, returns the argument + * @return It returns domainbus, if non null, + * otherwise it returns the IVYBUS property if non null, otherwise it + * returns Ivy.DEFAULT_DOMAIN + */ + public static String getDomain(String domainbus) { if ( domainbus == null ) domainbus = System.getProperty("IVYBUS"); if ( domainbus == null ) domainbus = DEFAULT_DOMAIN; return domainbus; } + /** + * returns the domain bus + * + * @since 1.2.8 + * @param progname The name of your program, for error message + * @param args the String[] of arguments passed to your main() + * @return returns the domain bus, ascending priority : ivy default bus, IVY_BUS + * property, -b domain on the command line + */ + public static String getDomainArgs(String progname, String[] args) { + Getopt opt = new Getopt(progname,args,"b:"); + int c; + if ( ((c=opt.getopt())!=-1) && c=='b' ) return opt.getOptarg(); + return getDomain(null); + } + + /** + * returns a "wana be unique" ID to make requests on the bus + * + * @since 1.2.8 + * @return returns a string wich is meant to be noisy enough to be unique + */ + public String getWBUId() { + return "ID<"+appName+myserial+":"+nextId()+":"+generator.nextInt()+">"; + } + private synchronized long nextId() { return current++; } void addClient(IvyClient c) { - clients.put(c.getClientKey(),c); + synchronized (clients) { clients.put(c.getClientKey(),c); } traceDebug("added "+c+" in clients: "+getClientNames(clients)); } void removeClient(IvyClient c) { - clients.remove(c.getClientKey()); + synchronized (clients) {clients.remove(c.getClientKey());} traceDebug("removed "+c+" from clients: "+getClientNames(clients)); } void addHalf(IvyClient c) { - half.put(c.getClientKey(),c); + synchronized(half){half.put(c.getClientKey(),c);} traceDebug("added "+c+" in half: "+getClientNames(half)); } void removeHalf(IvyClient c) { - half.remove(c.getClientKey()); + synchronized(half){half.remove(c.getClientKey());} traceDebug("removed "+c+" from half: "+getClientNames(half)); } @@ -633,7 +721,8 @@ public class Ivy implements Runnable { private String getClientNames(Hashtable t) { String s = "("; for (Enumeration e=t.elements();e.hasMoreElements();){ - s+=((IvyClient)e.nextElement()).getApplicationName()+","; + IvyClient ic = (IvyClient)e.nextElement(); + if (ic!=null) s+=ic.getApplicationName()+","; } return s+")"; } @@ -662,11 +751,12 @@ public class Ivy implements Runnable { public static void main(String[] args) { Ivy bus = new Ivy("Test Unitaire","TU ready",null); try { - bus.start(null); + bus.start(Ivy.getDomainArgs("IvyTest",args)); System.out.println("waiting 5 seconds for a coucou"); System.out.println(((bus.waitForMsg("^coucou",5000))!=null)?"coucou received":"coucou not received"); System.out.println("waiting 5 seconds for IvyProbe"); System.out.println(((bus.waitForClient("IVYPROBE",5000))!=null)?"Ivyprobe joined the bus":"nobody came"); + System.out.println("random values: "+bus.getWBUId()+", "+bus.getWBUId()+", "+bus.getWBUId()); bus.stop(); } catch (IvyException ie) { System.out.println("Ivy main test error"); |