aboutsummaryrefslogtreecommitdiff
path: root/src/Ivy.java
diff options
context:
space:
mode:
authorjestin2005-07-06 20:03:49 +0000
committerjestin2005-07-06 20:03:49 +0000
commit0cef96242b0e0aa10b4b33ee0f4b175048dbe3e0 (patch)
tree06afd0e92815bcdfa856a67c765862b551e39e4d /src/Ivy.java
parentfe015aed1f9aa5f2d7247f9262d7f12c59536379 (diff)
downloadivy-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-xsrc/Ivy.java116
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");