diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/Ivy.java | 114 | ||||
-rwxr-xr-x | src/IvyClient.java | 287 | ||||
-rw-r--r-- | src/TestIvySwing.java | 173 |
3 files changed, 345 insertions, 229 deletions
diff --git a/src/Ivy.java b/src/Ivy.java index 6fce37b..8756c94 100755 --- a/src/Ivy.java +++ b/src/Ivy.java @@ -8,6 +8,7 @@ package fr.dgac.ivy ; import java.net.*; import java.io.*; import java.util.Vector; +import java.util.Hashtable; import java.util.StringTokenizer; public class Ivy implements Runnable, IvyApplicationListener { @@ -19,41 +20,30 @@ public class Ivy implements Runnable, IvyApplicationListener { public String appName; private boolean ivyRunning = false; private String ready_message = null; - private Vector regexp_out; private ServerSocket app; private IvyWatcher watch; private Thread server; - private Vector clients; - private Vector callbacks; - private Vector ivyApplicationListenerList; + + 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; - } - // constructeur - public Ivy( String name, String message, IvyApplicationListener appcb) - { + public synchronized boolean ivyRunning(){ return ivyRunning; } + + public Ivy( String name, String message, IvyApplicationListener appcb) { appName = name; - ivyApplicationListenerList = new Vector(); ready_message = message; - callbacks = new Vector(); - clients = new Vector(); - regexp_out = new Vector(); - if ( appcb != null ) - ivyApplicationListenerList.addElement( appcb ); + if ( appcb != null ) ivyApplicationListenerList.addElement( appcb ); } - void classes( String msg_classes[] ) { - messages_classes = msg_classes; - } - public Vector getRegexpOut() { - return regexp_out; - } - public String getReadyMessage() { - return ready_message; - } + 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); @@ -64,27 +54,20 @@ public class Ivy implements Runnable, IvyApplicationListener { clients.removeElement( client ); } - void callCallback( IvyClient client, int msgid, String msgarg ) { - IvyMessageListener callback; - String args[]; - if ( (msgid <0) || (msgid > callbacks.size()) ) { - traceDebug("(callCallback) Not regexp matching id "+msgid); + 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; } - callback = (IvyMessageListener)callbacks.elementAt(msgid); - StringTokenizer st = new StringTokenizer(msgarg, IvyClient.EndArg); - args = new String[st.countTokens()]; + 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 ); + while (st.hasMoreTokens()){ args[i++] = st.nextToken();} + callback.receive( client, args ); } - public int getApplicationPort() { - return myport; - } + public int getApplicationPort() { return myport; } public int sendMsg( String message ) { int count = 0; @@ -97,34 +80,28 @@ public class Ivy implements Runnable, IvyApplicationListener { return count; } + static private int serial=0; public int bindMsg(String regexp, IvyMessageListener callback ) { // associe une nouvelle regexp à un nouveau callback - regexp_out.addElement( regexp ); - callbacks.addElement( callback ); - int id = regexp_out.indexOf( regexp ); - /* indique aux autres clients la nouvelle regexp */ - for ( int i = 0 ; i < clients.size(); i++ ) { - IvyClient client = (IvyClient)clients.elementAt(i); - client.sendRegexp(id, regexp ); + Integer key = new Integer(serial++); + regexp_out.put(key,regexp); + callbacks.put(key,callback ); + // indique aux autres clients la nouvelle regexp + for (int i=0;i<clients.size();i++){ + ((IvyClient)clients.elementAt(i)).sendRegexp(key.intValue(),regexp); } - return id; + return key.intValue(); } public void unBindMsg(int id) { - // TODO: Est ce que la suppression d'1 element - // ne provoque pas le tassement - // et donc la modif des autres indexes? - if ( id >=0 && id < regexp_out.size() ) - { - regexp_out.removeElementAt( id ); - callbacks.removeElementAt( id ); - - for ( int i = 0 ; i < clients.size(); i++ ) - { - IvyClient client = (IvyClient)clients.elementAt(i); - client.delRegexp(id ); - } - } + Integer key = new Integer(id); + if ( ( regexp_out.remove(key) == null ) + || (callbacks.remove(key) == null ) ) { + System.err.println("attention j'enlève une regexp inexistante"); + } + for (int i=0;i<clients.size();i++ ) { + ((IvyClient)clients.elementAt(i)).delRegexp(id ); + } } /* gestion des applications listener et callback associe */ public int addApplicationListener(IvyApplicationListener callback){ @@ -207,19 +184,18 @@ public class Ivy implements Runnable, IvyApplicationListener { boolean CheckRegexp( String exp ) { /* accepte tout par default */ - int i; boolean regexp_ok = true; - if ( exp.startsWith( "^" ) && messages_classes != null ) { - regexp_ok = false; - for ( i = 0 ; i < messages_classes.length; i++ ) { - if ( messages_classes[i].equals( exp.substring(1)) ) return true; + if ( exp.startsWith( "^" )&&messages_classes!=null) { + regexp_ok=false; + for (int i=0 ; i < messages_classes.length;i++) { + if (messages_classes[i].equals(exp.substring(1))) return true; } } return regexp_ok; } public boolean checkConnected( IvyClient clnt ) { - if ( clnt.appPort == 0 ) return false; + if ( clnt.getAppPort() == 0 ) return false; for ( int i = 0 ; i < clients.size(); i++ ) { IvyClient client = (IvyClient)clients.elementAt(i); if ( clnt != client && client.sameClient( clnt ) ) return true; diff --git a/src/IvyClient.java b/src/IvyClient.java index 8ec226d..7ec220f 100755 --- a/src/IvyClient.java +++ b/src/IvyClient.java @@ -1,9 +1,5 @@ /* -** ** IvyClient -** Wed Aug 27 15:02:00 MET DST 1997 -> rajout des fonction ping & pong -** -** correction: un Die va faire finir le Thread, pas l'*ensemble* */ package fr.dgac.ivy ; @@ -11,14 +7,18 @@ package fr.dgac.ivy ; import java.lang.Thread; import java.net.*; import java.io.*; -import java.util.Date; -import java.util.Vector; -import java.util.StringTokenizer; +import java.util.*; import gnu.regexp.*; public class IvyClient extends Thread { - // les types de messages + /* + * les types de messages + * on ne *change* pas, sous peine d'incompatibilité avec les autres + * implémentations ( C, C++, etc... ). + * quoi que :) + * + */ public final static int Bye = 0; /* l'application emettrice se termine */ public final static int AddRegexp = 1;/* expression reguliere d'un client */ public final static int Msg = 2 ; /* message reel */ @@ -30,25 +30,25 @@ public class IvyClient extends Thread { public final static int Die = 8; /* demande de terminaison de l'appli */ public final static int Ping = 9; /* demande de réponse pong */ public final static int Pong = 10; /* réponse au ping */ - public final static String StartArg = "\002";/* separateur debut args */ public final static String EndArg = "\003"; /* separateur inter arguments */ - protected String appName; - public int appPort; + private String appName; + private int appPort; - // gestion du protocole ping - long lastRead = 0; - long pingDate = 0 ; - long pingLag =0 ; - - Ivy bus; - Socket socket; - BufferedReader in; - OutputStream out; + /* + * gestion du protocole ping + * ne marche pas encore + */ + private long lastRead = 0; + private long pingDate = 0 ; + private long pingLag =0 ; - Vector regexp_in; - Vector regexp_id; + private Ivy bus; + private Socket socket; + private BufferedReader in; + private OutputStream out; + private Hashtable regexp_in = new Hashtable(); static private boolean debug = (System.getProperty("IVY_DEBUG")!=null) ; @@ -60,206 +60,172 @@ public class IvyClient extends Thread { lastRead = (new Date()).getTime(); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = socket.getOutputStream(); - regexp_in = new Vector(); - regexp_id = new Vector(); - sendService( bus.getRegexpOut() ); + sendService( bus.getRegexpOut()); start(); } + /* + * quelques accesseurs + */ public InetAddress getRemoteAddress() { return socket.getInetAddress(); } public String getApplicationName() { return appName ; } + public int getAppPort() { return appPort ; } void sendBuffer( String buffer ) { - buffer += "\n"; - try { - out.write(buffer.getBytes() ); - out.flush(); - } catch ( IOException e ) - { - // TODO: write error - } + buffer += "\n"; + try { + out.write(buffer.getBytes() ); + out.flush(); + } catch ( IOException e ) { + // TODO: write error + System.err.println("IvyClient.sendBuffer.write failed. FIX ME"); + } } + void send( int type, int id, String arg) { - String buffer = type+" "+id+StartArg+arg; + String buffer = type+" "+id+StartArg+arg; sendBuffer(buffer ); } - void sendRegexp( int id, String regexp ) - { - send( AddRegexp,id,regexp); - } + void sendRegexp( int id, String regexp ) { send( AddRegexp,id,regexp); } - public void sendDie( ) - { - send( Die,0,""); - } + public void sendDie( ) { send( Die,0,""); } - public void sendDie(String message) - { - send( Die,0,message); - } + public void sendDie(String message) { send( Die,0,message); } - void sendPing() - { + void sendPing() { pingDate = (new Date()).getTime(); // on marque le message par la date actuelle send( Ping, 0, String.valueOf(pingDate) ); } - void sendService( Vector regexps ) - { + /* + * notifie la liste des regexps aux autres clients du bus + */ + private void sendService( Hashtable regexps ) { send( StartRegexp, bus.getApplicationPort(), bus.appName); - for ( int id = 0 ; id < regexps.size(); id++ ) - { - String regexp; - regexp = (String)regexps.elementAt(id); - sendRegexp( id,regexp); + for (Enumeration e = regexps.keys(); e.hasMoreElements(); ) { + Integer key = (Integer)e.nextElement(); + sendRegexp( key.intValue(),(String)regexps.get(key)); } send( EndRegexp,0, ""); } - void send( int type, Integer id, int nbsub, REMatch result) - { - String buffer = type+" "+id+StartArg; + void send( int type, Integer id, int nbsub, REMatch result) { + String buffer = type+" "+id+StartArg; traceDebug ( "Send matching result \n" ); // ????Start at 1 because group 0 represent entire matching for(int sub = 1; sub <= nbsub; sub++) { - if (result.getSubStartIndex(sub) > -1) { - buffer += result.toString(sub)+EndArg; - traceDebug( "Send arg "+result.toString(sub)); - } + if (result.getSubStartIndex(sub) > -1) { + buffer += result.toString(sub)+EndArg; + traceDebug( "Send arg "+result.toString(sub)); + } } - sendBuffer( buffer ); + sendBuffer( buffer ); } - public int sendMsg( String message ) - { - REMatch result; - RE regexp; - Integer id; - int count = 0; - for ( int i = 0 ; i < regexp_in.size(); i++ ) - { - regexp = (RE)regexp_in.elementAt(i); - id = (Integer) regexp_id.elementAt(i); - result = regexp.getMatch(message); - if ( result != null ) - { - send( Msg,id,regexp.getNumSubs(),result); - count ++; - } + public int sendMsg( String message ) { + int count = 0; + for (Enumeration e = regexp_in.keys();e.hasMoreElements();) { + Integer key = (Integer)e.nextElement(); + RE regexp = (RE)regexp_in.get(key); + REMatch result = regexp.getMatch(message); + if ( result != null ) { + send(Msg,key,regexp.getNumSubs(),result); + count++; + } } - return count; + return count; } - void close(String msg) throws IOException - { - traceDebug( msg ); + void close(String msg) throws IOException { + traceDebug( msg ); socket.close(); //stop(); - } +} - public boolean sameClient( IvyClient clnt ) - { - if ( appPort != 0 && appPort == clnt.appPort ) { - if ( getRemoteAddress() == clnt.getRemoteAddress() ) return true; - } - return false; + public boolean sameClient( IvyClient clnt ) { + return ( appPort != 0 && appPort == clnt.appPort ) + && ( getRemoteAddress() == clnt.getRemoteAddress() ) ; } - public void delRegexp( int id ) - { - send( DelRegexp,id,""); - } - public void run() - { - String msg = null; - String token = null; - int i; - int msgtype; /* type du dernier message recu */ - Integer msgid; /* id du dernier message recu */ - String msgarg = null; /* argument du dernier message recu */ - RE regexp = null; /* regexp compile */ + public void delRegexp( int id ) { send( DelRegexp,id,"");} + public void run() { + String msg = null; try { - traceDebug("Connected from "+ socket.getInetAddress().getHostName()+":"+socket.getPort()); - - parseInput: - while( (msg = in.readLine()) != null ) { - - /* étape un : extrait le message */ + while((msg=in.readLine()) != null ) { + int msgtype; /* type du dernier message recu */ + Integer msgid; /* id du dernier message recu */ + RE regexp = null; /* regexp compile */ + String token = null; + /* + * ETAPE UN : extraire le message + */ lastRead = (new Date()).getTime(); StringTokenizer st = new StringTokenizer(msg); - traceDebug("Receive msg '"+msg+"'"); - if ( ! st.hasMoreTokens()) { + if (!st.hasMoreTokens()){ close("Bad format no type '"+msg+"'"); break; } - token = st.nextToken(); - if ( token.length() == 0 ) { + token=st.nextToken(); + if (token.length()==0) { close("Bad format no type '"+msg+"'"); break; } - try { msgtype = Integer.parseInt( token ); } - catch ( NumberFormatException e ) { + try { + msgtype = Integer.parseInt(token); + } catch ( NumberFormatException e ) { close("Bad format error parsing type'"+msg+"'"); break; } - if ( ! st.hasMoreTokens()) { + if (!st.hasMoreTokens()) { close("Bad format no id '"+msg+"'"); break; } - msgid = Integer.valueOf( st.nextToken(StartArg) ); - if ( st.hasMoreTokens()) { - msgarg = st.nextToken("\n"); - } + msgid=Integer.valueOf(st.nextToken(StartArg)); + /* + * DONE: il trainait un bug ici: on oubliait de réinitialiser msgarg + * à la chaine vide, et du coup, pour les regexps sans groupe (), + * ça envoyait des messages un peu fantaisistes + */ + String msgarg=""; + if (st.hasMoreTokens()) msgarg=st.nextToken("\n"); - /* étape deux : traitement adapté */ - switch( msgtype ){ + /* + *ETAPE DEUX : traitement adapté au type de message + */ + switch (msgtype) { case Bye: break; case AddRegexp: - if ( bus.CheckRegexp( msgarg ) ) { - // Attempt to compile the pattern. If the pattern is not valid, - // report the error and exit. + if ( bus.CheckRegexp(msgarg) ) { try { - regexp = new RE(msgarg); - if ( regexp.getNumSubs()!= 0 ) - { - /* check to see if any subexp */ - /* these are needed to send msg */ - regexp_in.addElement( regexp ); - regexp_id.addElement( msgid ); - } - else System.err.println("Bad pattern: No () groups"); + regexp_in.put(msgid,new RE(msgarg)); } catch (REException e) { System.err.println("Bad pattern: "+e.getMessage()); } - } else System.err.println("Warning exp='"+ - msgarg+"' can't match removing from "+appName); + } else { + System.err.println( + "Warning exp='"+msgarg+"' can't match removing from "+appName); + } break; case DelRegexp: - i = regexp_id.indexOf( msgid ); - if ( i >=0 ) - { - regexp_in.removeElementAt(i); - regexp_id.removeElementAt(i); - } + regexp_in.remove(msgid); break; case EndRegexp: - /* - ** call application callback avec event Connected - */ - bus.connect( this ); - if ( bus.getReadyMessage() != null ) - sendMsg( bus.getReadyMessage() ); + /* + * call application callback avec event Connected + */ + bus.connect(this); + if (bus.getReadyMessage()!=null) sendMsg(bus.getReadyMessage()); break; case Msg: /* - ** call callback avec les arguments - */ - bus.callCallback( this, msgid.intValue(), msgarg ); + * call callback avec les arguments + */ + bus.callCallback(this,msgid,msgarg); break; case Error: traceDebug("Error msg "+msgid+" "+msgarg); @@ -267,24 +233,23 @@ public class IvyClient extends Thread { case StartRegexp: appName=msgarg; appPort=msgid.intValue(); - if ( bus.checkConnected( this ) ) - close( "Quitting Application already connected" ); + if ( bus.checkConnected(this) ) + close("Quitting Application already connected"); break; case DirectMsg: traceDebug("Direct Message id="+msgid+" msg='"+msgarg+"'"); - /* - ** call directCallback avec les arguments - */ + * call directCallback avec les arguments + */ bus.directMessage( this, msgid.intValue(), msgarg ); break; case Die: traceDebug("Die Message received . argh !"); /* - ** call diecallBack aavant de quitter - */ + * call diecallBack aavant de quitter + */ bus.die( this,msgid.intValue()); - break parseInput; + break; case Ping: traceDebug("Ping Message"); // répond avec le même argument .. Pour le moment c'est inutile @@ -297,10 +262,11 @@ public class IvyClient extends Thread { break; default: System.err.println("*** IvyClient *** unhandled msg type "+ - msgtype+" "+msgid+msgarg); + msgtype+" "+msgid+msgarg); break; } // switch sur le type de message } // while readline + // plus rien à lire .... ou alors break donc erreur traceDebug("zarbi Disconnected from "+ socket.getInetAddress().getHostName()+":"+socket.getPort()); @@ -320,3 +286,4 @@ public class IvyClient extends Thread { if (debug) System.out.println("-->ivyclient<-- "+s); } } // class IvyClient +/* EOF */ diff --git a/src/TestIvySwing.java b/src/TestIvySwing.java new file mode 100644 index 0000000..a6d3777 --- /dev/null +++ b/src/TestIvySwing.java @@ -0,0 +1,173 @@ +package fr.dgac.ivy ; + +import java.awt.BorderLayout; +import java.awt.event.*; +import javax.swing.* ; + +class TestIvySwing extends JPanel implements IvyApplicationListener { + + private static int index; + private static int nbTIS=0; + String localname; + + Ivy bus ; + String regexp = "^AIRCRAFT:";; + JLabel laRegex; + JTextArea ta ; + JTextField tfRegex, tfSend ; + JButton buApply, buSend, buClear ; + JComboBox ports; + int regexp_id; + REGCB reg; + + public TestIvySwing() throws IvyException { + super(new BorderLayout()); + nbTIS++; + // un textarea au centre + ta = new JTextArea(25,40); + ta.setEditable(false); + add(new JScrollPane(ta),BorderLayout.CENTER); + // une zone regex au nord + JPanel p = new JPanel(new BorderLayout()); + p.add(new JLabel("Regex:"),BorderLayout.WEST); + tfRegex = new JTextField(); + tfRegex.addActionListener(reg=new REGCB()); + p.add(tfRegex,BorderLayout.CENTER); + p.add(laRegex=new JLabel(regexp),BorderLayout.EAST); + add(p,BorderLayout.NORTH); + // une zone messages au sud du nord, mais au nord du centre + JPanel p2 = new JPanel(new BorderLayout()); + p2.add(new JLabel("Msg:"),BorderLayout.WEST); + tfSend = new JTextField(""); + tfSend.addActionListener(new SENDCB()); + p2.add(tfSend,BorderLayout.CENTER); + p.add(p2,BorderLayout.SOUTH); + // au sud, je rajoute un bouton pour spawner un autre testeur + JButton tmpb ; + (p = new JPanel()).add(tmpb=new JButton("spawn")); + tmpb.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { newTestIvy(); + } catch (IvyException ie) {} + } + }); + p.add(tmpb=new JButton("clear")); + tmpb.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ta.setText(""); + } + }); + + ports=new JComboBox(); + ports.addItem("127.255.255.255:2010"); + ports.addItem("143.196.53.255:2010"); + ports.addItem("143.196.53.255:2020"); + ports.addItem("143.196.53.255:3110"); + ports.addActionListener(new ComboCB()); + p.add(ports); + add(p,BorderLayout.SOUTH); + // gestion du fovus clavier + tfRegex.setNextFocusableComponent(tfSend); + tfSend.setNextFocusableComponent(tfRegex); + tfSend.setRequestFocusEnabled(true); + localname = "TestIvySwing ("+index+")"; + index++; + bus = new Ivy(localname,localname+" prêt",this); + regexp_id = bus.bindMsg(regexp,reg); + bus.start(null); + append( "Ivy Domain: "+ bus.getDomain(null) ); + } + + public String getLocalname(){ return localname;} + + public void stop() { bus.stop(); } + + public void connect(IvyClient client) { + append(client.getApplicationName() + " connected " ); + } + + public void disconnect(IvyClient client) { + append(client.getApplicationName() + " disconnected " ); + } + + public void die(IvyClient client, int id) { + append(client.getApplicationName() + " die "+ id ); + } + + public void directMessage(IvyClient client, int id, String arg) { + append(client.getApplicationName() + " direct Message "+ id + arg ); + } + + /* inner */ class ComboCB implements ActionListener { + public void actionPerformed(ActionEvent e) { + String newDomain=(String)ports.getSelectedItem(); + bus.stop(); + try { + bus.start(newDomain); + } catch (IvyException ie ) { + System.err.println("auuuugh "+newDomain); + } + } + } // ComboCB + + /* inner */ class REGCB implements ActionListener, IvyMessageListener { + public void actionPerformed(ActionEvent e) { + // enlever l'ancienne regex + bus.unBindMsg(regexp_id); + // ajoute la nouvelle regex + regexp=tfRegex.getText(); + regexp.trim(); + regexp_id = bus.bindMsg(regexp,this); + tfRegex.setText(""); + laRegex.setText(regexp); + } + public void receive(IvyClient client, String[] args) { + String out="client " + client.getApplicationName() + " envoie: [ "; + for (int i=0;i<args.length;i++) { + out+=args[i]+ ((i<args.length-1)?" , ":""); + } + out+=" ]"; + append(out); + } + } + + /* inner */ class SENDCB implements ActionListener { + public void actionPerformed(ActionEvent e) { + int count; + String tosend = tfSend.getText(); + tfSend.setText(""); + if ( (count = bus.sendMsg(tosend)) != 0 ) + append("Sending '" + tosend + "' count " + count ); + else + append("not Sending '" + tosend + "' nobody cares"); + } + } + + private void append(String s) { ta.append(s + "\n"); } + + + public static void newTestIvy() throws IvyException { + TestIvySwing tb = new TestIvySwing(); + JFrame f = new JFrame(tb.getLocalname()); + f.addWindowListener( tb.new WCCB(f,tb)) ; + f.getContentPane().add(tb, BorderLayout.CENTER); + f.pack(); + f.setVisible(true); + } + + /* inner */ class WCCB extends WindowAdapter { + private JFrame f; + public WCCB(JFrame f, TestIvySwing b) { this.f=f; } + public void windowClosing(WindowEvent e) { + bus.stop(); + f.dispose(); + if (--nbTIS == 0) System.exit(0); + // je quitte l'appli au départ du dernier TIS + } + public void windowActivated(WindowEvent e) { tfSend.grabFocus(); } + } // WCCB + + public static void main(String[] args) throws IvyException { newTestIvy(); } +} + +// EOF |