Author: bdonlan
Date: 2005-06-21 14:42:08 -0400 (Tue, 21 Jun 2005)
New Revision: 790

Removed:
   trunk/java/src/org/haverdev/javer2/Main.java
Modified:
   trunk/java/src/org/haverdev/client/Callback.java
   trunk/java/src/org/haverdev/client/Client.java
   trunk/java/src/org/haverdev/javer2/CMod.java
   trunk/java/src/org/haverdev/javer2/ChannelPane.java
   trunk/java/src/org/haverdev/javer2/JaverForm.java
Log:
Steps toward a more sane client class

Modified: trunk/java/src/org/haverdev/client/Callback.java
===================================================================
--- trunk/java/src/org/haverdev/client/Callback.java    2005-06-21 06:46:53 UTC 
(rev 789)
+++ trunk/java/src/org/haverdev/client/Callback.java    2005-06-21 18:42:08 UTC 
(rev 790)
@@ -19,14 +19,14 @@
      * @param source haver.Client instance associated with this event
      * @throws java.io.IOException 
      */
-    public void onConnect(Client source) throws Throwable {}
+    public void onConnect(Client source) {}
     /**
      * Called when a connection attempt fails.
      * @param source haver.Client instance associated with this event
      * @param e IOException which caused the connection failure
      * @throws java.io.IOException 
      */
-    public void onConnectFailed(Client source, java.io.IOException e) throws 
Throwable {}
+    public void onConnectFailed(Client source, java.io.IOException e) {}
     /**
      * Called when an established connection is lost
      * @param source haver.Client instance associated with this event
@@ -34,34 +34,39 @@
      * not have an associated exception (e.g., connection broken)
      * @throws java.io.IOException 
      */
-    public void onDisconnected(Client source, java.io.IOException e) throws 
Throwable {}
+    public void onDisconnected(Client source, java.io.IOException e) {}
     /**
      * Called when a message is received from the server
      * @param source haver.Client instance associated with this event
      * @param args Arguments of the message
      * @throws java.io.IOException 
      */
-    public void onIncomingLine(Client source, String[] args) throws Throwable 
{}
+    public void onIncomingLine(Client source, String[] args) {}
     /**
      * Called when a message is sent to the server
      * @param source haver.Client instance associated with this event
      * @param args Arguments of the message
      * @throws java.io.IOException 
      */
-    public void onOutgoingLine(Client source, String[] args) throws Throwable 
{}    
+    public void onOutgoingLine(Client source, String[] args) {}  
+    
+    interface NameReturn {
+        public void setName(String name);
+    }
+    
     /**
      * Called when the server requires identification
      * @param source haver.Client instance associated with this event
      * @throws java.io.IOException 
      */
-    public void onNeedIdent(Client source) throws Throwable {}
+    public void onNeedIdent(Client source, NameReturn nr) {}
     /**
      * Called when the name given by the client has been accepted
      * @param source haver.Client instance associated with this event
      * @param name Name that was accepted by the server
      * @throws java.io.IOException 
      */
-    public void onAccept(Client source, String name) throws Throwable {}
+    public void onAccept(Client source, String name) {}
     
     /**
      * Called when the server responds to a listing request
@@ -71,20 +76,20 @@
      * @param list List of objects held by the channel
      * @throws java.io.IOException 
      */
-    public void onReceivedList(Client source, String channel, String 
namespace, String[] list) throws Throwable {}
+    public void onReceivedList(Client source, String channel, String 
namespace, String[] list) {}
     
-    public void onPublicMessage(Client source, String channel, String from, 
String type, String[] args) throws Throwable {}
+    public void onPublicMessage(Client source, String channel, String from, 
String type, String[] args) {}
     
-    public void onPrivateMessage(Client source, String from, String type, 
String[] args) throws Throwable {}
+    public void onPrivateMessage(Client source, String from, String type, 
String[] args) {}
     
-    public void onJoin(Client source, String channel, String who) throws 
Throwable {}
+    public void onJoin(Client source, String channel, String who) {}
     
-    public void onPart(Client source, String channel, String who) throws 
Throwable {}
+    public void onPart(Client source, String channel, String who) {}
     
-    public void onQuit(Client source, String who, String type, String detail) 
throws Throwable {}
+    public void onQuit(Client source, String who, String type, String detail) 
{}
     
     // XXX: this is a hack and should not be used in apps
-    void onFail(Client source, String[] args) throws Throwable {};
+    void onFail(Client source, String[] args) {};
     
     public void onAuthenticationFailed(Client source) {};
 }

Modified: trunk/java/src/org/haverdev/client/Client.java
===================================================================
--- trunk/java/src/org/haverdev/client/Client.java      2005-06-21 06:46:53 UTC 
(rev 789)
+++ trunk/java/src/org/haverdev/client/Client.java      2005-06-21 18:42:08 UTC 
(rev 790)
@@ -9,7 +9,7 @@
 import java.util.*;
 import java.net.*;
 import java.lang.reflect.*;
-import org.haverdev.haver.*;
+import org.haverdev.common.*;
 
 /**
  * A Haver client class
@@ -17,24 +17,59 @@
  */
 public class Client {
 
+    private static class WriteLine {
+        String line;
+        
+        WriteLine(String line) { this.line = line; }
+        public String toString() { return line; }
+    }
     
-    HashSet listening = new java.util.HashSet();
+    private static class WriteClose { }
+    
+    int state = 0;
+    
+    // No connections, no activity.
+    static final int STATE_IDLE = 0;
+    // Awaiting socket connection
+    static final int STATE_CONNECTING = 1;
+    // Socket connection established, C: HAVER sent. Awaiting S: HAVER
+    static final int STATE_HELLO = 2;
+    // Sent name, authenticating or waiting for S: HELLO
+    static final int STATE_AUTH = 3;
+    // S: HELLO sent; ready for client commands
+    static final int STATE_ONLINE = 5;
+    // Sent C: BYE, waiting for S: BYE.
+    static final int STATE_DISCONNECTING = 6;
+    
+    // Non-null in all states except STATE_IDLE and STATE_CONNECTING
+    ObjectQueue writeQ = null;
+
     CallbackDist dist;
+    
+    // Non-null in all states except STATE_IDLE and STATE_CONNECTING
     Socket theSocket = null;
-    boolean connecting = false;
-    Thread io = null;
-    Client self = this;
-    PrintWriter writer = null;
     BufferedReader reader = null;
-    NonblockingOutputStream s;
+    
+    Thread inputThread = null;
+    Thread outputThread = null;
+    
+    // The name we will (or have) authenticated to the server with.
     String name = null;
+    
+    // The hostname the server claims to have
     String hostname = null;
+    
+    HashSet listening = new java.util.HashSet();
     HashMap authProviders = new HashMap();
     
-    static final String[] greeting = {"HAVER", "haver.Client/0.00", "auth"};
+    /* The exception that caused a disconnect.
+     * This is set in the dist.onDisconnected function, and reset when the
+     * reader thread dies (which is synchronized to happen after the writer
+     * thread in all cases).
+     */
+    IOException closeException = null;
     
-    String host;
-    int port;
+    static final String[] greeting = {"HAVER", "haver.Client/0.01", "auth"};
     
     public String getName() {
         return name;
@@ -68,86 +103,10 @@
     public synchronized void removeAuthProvider(String p) {
         authProviders.remove(p);
     }
+ 
+    final Client self = this; // For inner classes
     
     /**
-     * Reverses Haver escaping.
-     * @param val String to unescape
-     * @return The unescaped string
-     */
-    protected static final String unescape(String val) {
-        //if (val != null) return val;
-        StringBuffer out = new StringBuffer();
-        int pin = 0;
-        int nextEsc = -1;
-        while (-1 != (nextEsc = val.indexOf("\033", pin))) {
-            out.append(val.substring(0, nextEsc - 1));
-            switch (val.charAt(nextEsc + 1)) {
-                case 'r':
-                    out.append('\r');
-                    break;
-                case 'n':
-                    out.append('\n');
-                    break;
-                case 'e':
-                    out.append('\033');
-                    break;
-                case 't':
-                    out.append('\t');
-                    break;
-                default:
-                    out.append(val.charAt(nextEsc + 1));
-                    break;
-            }
-            pin = nextEsc + 2;
-        }
-        out.append(val.substring(pin));
-        return out.toString();
-    }
-    
-    /**
-     * Escapes a string according to the Haver protocol
-     * @param val String to escape
-     * @return Escaped string
-     */
-    protected static final String escape(String val) {
-        return val.replaceAll("\033", "\033e")
-               .replaceAll("\n", "\033n")
-               .replaceAll("\r", "\033r")
-               .replaceAll("\t", "\033t");
-    }
-    
-    /**
-     * Decodes a raw line from the Haver protocol.
-     * @param inLine Line to decode. May end in '\r\n' but must only be one 
line.
-     * @return An array containing the unescaped arguments of the line.
-     */
-    protected static final String[] decodeLine(String inLine) {
-        inLine = inLine.replaceAll("[\n\r]", ""); // We'll assume you only 
passed one
-                                            // line in.
-        String[] args = inLine.split("\t");
-        for (int i = 0; i < args.length; i++) {
-            args[i] = unescape(args[i]);
-        }
-        return args;
-    }
-    
-    /**
-     * Encodes a set of arguments for line transmission
-     * @param args Unescaped arguments to encode
-     * @return Escaped and joined line ready for transmission, complete with 
ending \r\n
-     */
-    protected static final String encodeLine(String[] args) {
-        StringBuffer out = new StringBuffer();
-        for (int i = 0; i < args.length; i++) {
-            if (i != 0)
-                out.append("\t");
-            out.append(escape(args[i]));
-        }
-        out.append("\r\n");
-        return out.toString();
-    }
-
-    /**
      * Internal class for distributing callback events to all listeners
      */
     protected class CallbackDist extends Callback {
@@ -172,14 +131,12 @@
             }
         }
         
-        public void onDisconnected(Client source, IOException e) throws 
IOException {
-            try {reader.close();} catch (Throwable t) {}
-            try {writer.close();} catch (Throwable t) {}
-            try {theSocket.close();} catch (Throwable t) {}
-            reader = null;
-            writer = null;
-            theSocket = null;
-            io = null;
+        public void onDisconnected(Client source, IOException e) {
+            synchronized (self) {
+                if (closeException != null)
+                    return;
+                closeException = e;
+            }
             
             Iterator i = iterator();
             while (i.hasNext()) {
@@ -193,7 +150,7 @@
 
         }
 
-        public void onConnectFailed(Client source, IOException e) throws 
IOException {
+        public void onConnectFailed(Client source, IOException e) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
@@ -205,8 +162,8 @@
             }
         }
 
-        public void onConnect(Client source) throws IOException {
-            // Konnichiha, saaba-san!
+        public void onConnect(Client source) {
+            // Gokigenyo, saaba-san!
             sendLine(greeting);
             
             Iterator i = iterator();
@@ -214,162 +171,138 @@
                 Callback c = (Callback)i.next();
                 try {
                     c.onConnect(source);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
 
-        public void onOutgoingLine(Client source, String[] args) throws 
IOException {
+        public void onOutgoingLine(Client source, String[] args) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
                     c.onOutgoingLine(source, args);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
 
-        public void onIncomingLine(Client source, String[] args) throws 
IOException {
+        public void onIncomingLine(Client source, String[] args) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
                     c.onIncomingLine(source, args);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
 
-        public void onNeedIdent(Client source) throws IOException {
+        public void onNeedIdent(Client source, NameReturn nr) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
-                    c.onNeedIdent(source);
-                } catch (IOException e) {
-                    throw e;
+                    c.onNeedIdent(source, nr);
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
 
-        public void onAccept(Client source, String name) throws IOException {
+        public void onAccept(Client source, String name) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
                     c.onAccept(source, name);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
 
-        public void onReceivedList(Client source, String channel, String 
namespace, String[] list) throws IOException {
+        public void onReceivedList(Client source, String channel, String 
namespace, String[] list) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
                     c.onReceivedList(source, channel, namespace, list);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
 
-        public void onPublicMessage(Client source, String channel, String 
from, String type, String[] args) throws IOException {
+        public void onPublicMessage(Client source, String channel, String 
from, String type, String[] args) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
                     c.onPublicMessage(source, channel, from, type, args);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
 
-        public void onPrivateMessage(Client source, String from, String type, 
String[] args) throws IOException {
+        public void onPrivateMessage(Client source, String from, String type, 
String[] args) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
                     c.onPrivateMessage(source, from, type, args);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
 
-        public void onQuit(Client source, String who, String type, String 
detail) throws IOException {
+        public void onQuit(Client source, String who, String type, String 
detail) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
                     c.onQuit(source, who, type, detail);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
 
-        public void onPart(Client source, String channel, String who) throws 
IOException {
+        public void onPart(Client source, String channel, String who) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
                     c.onPart(source, channel, who);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
 
-        public void onJoin(Client source, String channel, String who) throws 
IOException {
+        public void onJoin(Client source, String channel, String who) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
                     c.onJoin(source, channel, who);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
             }
         }
         
-        void onFail(Client source, String[] args) throws IOException {
+        void onFail(Client source, String[] args) {
             Iterator i = iterator();
             while (i.hasNext()) {
                 Callback c = (Callback)i.next();
                 try {
                     c.onFail(source, args);
-                } catch (IOException e) {
-                    throw e;
                 } catch (Throwable e) {
                     e.printStackTrace();
                 }
@@ -395,9 +328,9 @@
      * @param host Hostname to connect to
      * @param port Port number to connect to
      */
-    protected void run(String host, int port) {
+    protected void connectStart(String host, int port) {
         synchronized (this) {
-            if (Thread.currentThread() != io) {
+            if (Thread.currentThread() != inputThread) {
                 throw new IllegalStateException("Client.run called outside io 
thread");
             }
         }
@@ -406,60 +339,107 @@
             Socket mySock = new Socket(host, port);
             theSocket = mySock;
         } catch (IOException e) {
-            try {
-                io = null;
-                dist.onConnectFailed(this, e);
-            } catch (IOException e2) {}
+            inputThread = null;
+            dist.onConnectFailed(this, e);
             return;
         }
-        run();
+        state = STATE_HELLO;
+        readerStart();
     }
     
-    protected void run() {
+    protected void readerStart() {
         try {
-            writer = new PrintWriter
-                        (new OutputStreamWriter
-                        (s = new NonblockingOutputStream
-                        (new BufferedOutputStream
-                        (theSocket.getOutputStream()))));
-            s.setAutoFlush(true);
+            
+            writeQ = new ObjectQueue();
+            
+            outputThread = new Thread() {
+                public void run() {
+                    writeLoop();
+                }
+            };
+            outputThread.start();
+            
             reader = new BufferedReader
                     (new InputStreamReader
                     (theSocket.getInputStream()));
             dist.onConnect(this);
             ioLoop(new Flag());
         } catch (IOException e) {
-            try {
-                // XXX: may be called more than once
-                dist.onDisconnected(this, e);
-            } catch (IOException e2) {
+            dist.onDisconnected(this, e);
+        } finally {
+            if (closeException == null)
+                dist.onDisconnected(this, null);
+            synchronized (this) {
+                if (writeQ != null) {
+                    writeQ.post(new WriteClose());
+                    try {
+                        wait();
+                    } catch (InterruptedException e) {
+                        assert false;
+                    }
+                }
+                theSocket = null;
+                reader = null;
+                name = hostname = null;
+                closeException = null;
+                state = STATE_IDLE;
             }
-            return;
         }
     }
     
+    protected void writeLoop() {
+        if (Thread.currentThread() != outputThread) {
+            throw new IllegalStateException("Callable from the outputThread 
only");
+        }
+        PrintWriter writer = null;
+        try {
+            writer = new PrintWriter
+                    (new OutputStreamWriter
+                    (new BufferedOutputStream
+                    (theSocket.getOutputStream())));
+            while (true) {
+                Object o = writeQ.block();
+                if (o instanceof WriteLine) {
+                    writer.print(o);
+                    if (!writeQ.hasData())
+                        writer.flush();
+                } else {
+                    writer.close();
+                    writer = null;
+                    theSocket.close();
+                    return;
+                }
+            }
+        } catch (InterruptedException e) {
+        } catch (IOException e) {
+            closeException = e;
+        } finally {
+            synchronized (this) {
+                if (writer != null) {
+                    try { writer.close();    } catch (Throwable t) {}
+                    try { theSocket.close(); } catch (Throwable t) {}
+                }
+                outputThread = null;
+                writeQ = null;
+                notifyAll();
+            }
+        }
+    }
+    
     /**
      * Sends a command to the server.
      * @param args Arguments of the line to send
      * @throws java.io.IOException 
      */
     protected synchronized void sendLine(String[] args) {
-        if (writer != null) {
-            String l = encodeLine(args);
-            System.out.print("C: " + l);
-            writer.print(l);
-            writer.flush();
+        if (writeQ != null) {
+            writeQ.post(new WriteLine(HaverEncoding.encodeLine(args)));
         }
     }
     
     protected synchronized void killConnection() {
-        // Kill the connection. Don't ask questions, just do it.
-        try {
-            writer.flush();
-        } catch (Throwable t) {}
-        try {
-            theSocket.close();
-        } catch (Throwable t) {}
+        if (writeQ != null)
+            writeQ.post(new WriteClose()); // XXX: C: BYE?
     }
     
     /**
@@ -468,14 +448,14 @@
      * @throws java.io.IOException 
      */
     protected void ioLoop(Flag f) throws IOException {
-        while (io != null && f.ok) {
+        while (f.ok) {
             String l = reader.readLine();
             if (l == null) {
                 dist.onDisconnected(this, null);
                 return;
             }
             System.out.println("S: " + l);
-            String[] args = decodeLine(l);
+            String[] args = HaverEncoding.decodeLine(l);
             dist.onIncomingLine(this, args);
             dispatch(args);
         }
@@ -487,37 +467,34 @@
      * @param port Port number to connect to
      * @throws java.lang.IllegalStateException Thrown if the client is already 
connected or connecting.
      */
-    public synchronized void connect(String host, int port)
+    public synchronized void connect(final String host, final int port)
             throws IllegalStateException
     {
-        if (io != null && io.isAlive()) {
-            throw new IllegalStateException("Already connecting");
+        if (state != STATE_IDLE) {
+            throw new IllegalStateException("Must be idle to connect");
         }
-        name = null;
-        theSocket = null;
-        this.host = host;
-        this.port = port;
-        io = new Thread(new Runnable() {
+        state = STATE_CONNECTING;
+        inputThread = new Thread() {
             public void run() {
-                self.run(self.host, self.port);
+                connectStart(host, port);
             }
-        });
-        io.start();
+        };
+        inputThread.start();
     }
     
-    public synchronized void connect(Socket s) throws IllegalStateException 
+    public synchronized void connect(final Socket s) throws 
IllegalStateException 
     {
-        if (io != null && io.isAlive()) {
+        if (state != STATE_IDLE) {
             throw new IllegalStateException("Already connecting");
         }
-        name = null;
+        state = STATE_HELLO;
         theSocket = s;
-        io = new Thread(new Runnable() {
+        inputThread = new Thread(new Runnable() {
             public void run() {
-                self.run();
+                readerStart();
             }
         });
-        io.start();
+        inputThread.start();
     }
     
     /**
@@ -574,7 +551,7 @@
          * @throws java.io.IOException 
          */
         public synchronized Object block() throws IOException, 
InterruptedException {
-            if (Thread.currentThread() == io) {
+            if (Thread.currentThread() == inputThread) {
                 ioLoop(flag);
             } else {
                 try {
@@ -590,7 +567,7 @@
         }
     }
     
-    static final String[] fatals = {
+    static final String[] fatals = { // XXX
         "exists.user", "A user by that name already exists",
                 "invalid.name", "The given name is invalid",
                 "reserved.name", "The given name is reserved for server use",
@@ -614,23 +591,6 @@
      */
     protected class ConnectMonitor extends SyncMonitor {
         
-        /**
-         * true if connection completed successfully
-         */
-        public boolean done = false;
-        /**
-         * Name for login
-         */
-        public String name;
-        
-        public ConnectMonitor(String name) {
-            this.name = name;
-        }
-        
-        public void onNeedIdent(Client source) throws IOException {
-            source.ident(name);
-        }
-
         public void onAccept(Client source, String name) {
             done(null);
         }
@@ -655,14 +615,24 @@
      * connection is lost.
      */
     public void syncConnect(String host, int port, String name) throws 
IOException, InterruptedException {
-        ConnectMonitor m = new ConnectMonitor(name);
-        connect(host, port);
+        ConnectMonitor m = new ConnectMonitor();
+        synchronized (this) {
+            if (state != STATE_IDLE)
+                throw new IllegalStateException("Already connected");
+            this.name = name;
+            connect(host, port);
+        }
         m.block();
     }
     
     public void syncConnect(Socket s, String name) throws IOException, 
InterruptedException {
-        ConnectMonitor m = new ConnectMonitor(name);
-        connect(s);
+        ConnectMonitor m = new ConnectMonitor();
+        synchronized (this) {
+            if (state != STATE_IDLE)
+                throw new IllegalStateException("Already connected");
+            this.name = name;
+            connect(s);
+        }
         m.block();
     }
     
@@ -691,7 +661,7 @@
      * @param args Arguments of line, including command.
      * @throws java.io.IOException 
      */
-    protected void dispatch(String[] args) throws IOException {
+    protected void dispatch(String[] args){
         String cmd = args[0].toUpperCase();
         cmd = cmd.replaceAll(":", "_");
         Class me = this.getClass();
@@ -701,15 +671,11 @@
             Object[] args2 = {args};
             m.invoke(this, args2);
         } catch (InvocationTargetException e) {
-            Throwable thingy = e.getTargetException();
-            if (thingy instanceof IOException) {
-                throw (IOException) thingy;
-            }
-            thingy.printStackTrace();
+            e.printStackTrace();
         }
         catch (NoSuchMethodException e) {} // unhandled server event
         catch (IllegalAccessException e) {
-            // eep!
+            // Very bad, this is.
             e.printStackTrace();
         }
     }
@@ -718,6 +684,10 @@
     AuthProvider currentProvider = null;
     
     protected synchronized void handle_AUTH_TYPE(String[] args) {
+        availableAuth = new LinkedHashSet();
+        if (currentProvider != null)
+            removeNotify(currentProvider);
+        currentProvider = null;
         for (int i = 1; i < args.length; i++) {
             if (authProviders.containsKey(args[i]))
                 availableAuth.add(args[i]);
@@ -736,6 +706,8 @@
     protected synchronized void tryAuth() {
         if (availableAuth.size() == 0) {
             dist.onAuthenticationFailed(this);
+            name = null;
+            obtainName();
             return;
         }
         String authType = (String) availableAuth.iterator().next();
@@ -763,16 +735,31 @@
      */
     protected void handle_HAVER(String[] args) throws IOException {
         hostname = args[1];
-        dist.onNeedIdent(this);
+        obtainName();
     }
     
-    /**
-     * Identify with the given name
-     * @param name Name to identify with
-     * @throws java.io.IOException 
-     */
-    public void ident(String name) throws IOException {
-        this.name = name;
+    class NameReturn implements Callback.NameReturn {
+        public void setName(String name) {
+            synchronized (self) {
+                if (self.name != null) return;
+                self.name = name;
+            }            
+        }
+    }
+    
+    protected void obtainName() {
+        if (name != null) {
+            sendName();
+        } else {
+            dist.onNeedIdent(this, new NameReturn());
+            if (name == null)
+                this.killConnection();
+            else
+                sendName();
+        }
+    }
+
+    protected void sendName() {
         String[] l = {"IDENT", name};
         sendLine(l);
     }
@@ -787,6 +774,7 @@
         currentProvider = null;
         name = args[1];
         dist.onAccept(this, args[1]);
+        state = STATE_ONLINE;
     }
     
     /**

Modified: trunk/java/src/org/haverdev/javer2/CMod.java
===================================================================
--- trunk/java/src/org/haverdev/javer2/CMod.java        2005-06-21 06:46:53 UTC 
(rev 789)
+++ trunk/java/src/org/haverdev/javer2/CMod.java        2005-06-21 18:42:08 UTC 
(rev 790)
@@ -78,11 +78,11 @@
         voteTask = null;
     }
     
-    public void onDisconnected(Client source, java.io.IOException e) throws 
java.io.IOException {
+    public void onDisconnected(Client source, java.io.IOException e) {
         System.exit(0);
     }
 
-    public synchronized void onPrivateMessage(Client source, String from, 
String type, String[] args) throws java.io.IOException {
+    public synchronized void onPrivateMessage(Client source, String from, 
String type, String[] args) {
         if (current_state != STATE_VOTE) return;
         boolean vote;
         if (args[0].equals("yes"))
@@ -101,7 +101,7 @@
         tallyVotes();
     }
 
-    public synchronized void onPublicMessage(Client source, String channel, 
String from, String type, String[] args) throws java.io.IOException {
+    public synchronized void onPublicMessage(Client source, String channel, 
String from, String type, String[] args) {
         
         if (!channel.equals(this.channel)) return;
         if (!type.equals("say")) return;
@@ -120,7 +120,7 @@
         }
     }
     
-    public void idleMsg(String from, String msg) throws IOException {
+    public void idleMsg(String from, String msg) {
         if (!msg.equals("!start")) return;
         current_state = STATE_JOIN;
         startTask = new TimerTask() {
@@ -139,7 +139,7 @@
         players = new HashSet();
     }
     
-    public void joinMsg(String from, String msg) throws IOException {
+    public void joinMsg(String from, String msg) {
         if (!msg.equals("!join")) return;
         if (players.contains(from)) {
             c.sendPrivateMessage(from, "say", "You have already joined.");
@@ -151,7 +151,7 @@
     
     String innocent = null;
     
-    public synchronized void startGame() throws IOException {
+    public synchronized void startGame() {
         if (current_state != STATE_JOIN) return;
         if (players.size() < 3) {
             c.sendPublicMessage(channel, "say", "Not enough players, 
aborting.");
@@ -183,7 +183,7 @@
         t.schedule(voteTask, 1000 * chatTimeout);
     }
     
-    public synchronized void startVote() throws IOException {
+    public synchronized void startVote() {
         if (current_state != STATE_CHAT) return;
         c.sendPublicMessage(channel, "say", "Time's up, so stop these baseless 
public accusations, and begin private accusations. To me.");
         c.sendPublicMessage(channel, "say", "Message me with 'yes' if you 
think there's a conspiracy, or 'no' if you think it's all a bunch of baseless 
liberal propaganda.");
@@ -191,7 +191,7 @@
         votes = new HashMap();
     }
     
-    public synchronized void tallyVotes() throws IOException {
+    public synchronized void tallyVotes() {
         if (current_state != STATE_VOTE) return;
         if (votes.size() < players.size()) return;
         HashMap wins = new HashMap();
@@ -250,8 +250,10 @@
         reset();
     }
 
-    public void onAccept(Client source, String name) throws IOException, 
InterruptedException {
-        c.syncJoin(channel);
+    public void onAccept(Client source, String name) {
+        try { c.syncJoin(channel); }
+        catch (InterruptedException e) {}
+        catch (IOException e) { e.printStackTrace(); }
         logMessage("joined");
     }
 }

Modified: trunk/java/src/org/haverdev/javer2/ChannelPane.java
===================================================================
--- trunk/java/src/org/haverdev/javer2/ChannelPane.java 2005-06-21 06:46:53 UTC 
(rev 789)
+++ trunk/java/src/org/haverdev/javer2/ChannelPane.java 2005-06-21 18:42:08 UTC 
(rev 790)
@@ -26,7 +26,7 @@
     class Listener extends Callback {
         // TODO: part self
         
-        public void onQuit(Client source, String who, String type, String 
detail) throws Throwable {
+        public void onQuit(Client source, String who, String type, String 
detail) {
             synchronized (users) {
                 if (users.contains(who)) {
                     users.remove(who);
@@ -36,7 +36,7 @@
             }
         }
 
-        public void onPart(Client source, String chan, String who) throws 
Throwable {
+        public void onPart(Client source, String chan, String who) {
             if (!channel.equals(chan))
                 return;
             synchronized (users) {
@@ -46,7 +46,7 @@
             refreshList();
         }
 
-        public void onJoin(Client source, String chan, String who) throws 
Throwable {
+        public void onJoin(Client source, String chan, String who) {
             if (!channel.equals(chan))
                 return;
             synchronized (users) {
@@ -56,7 +56,7 @@
             refreshList();
         }
 
-        public void onReceivedList(Client source, String chan, String 
namespace, String[] list) throws Throwable {
+        public void onReceivedList(Client source, String chan, String 
namespace, String[] list) {
             if (!channel.equals(chan))
                 return;
             synchronized (users) {
@@ -68,7 +68,7 @@
             refreshList();
         }
 
-        public void onPublicMessage(Client source, String chan, String from, 
String type, String[] args) throws Throwable {
+        public void onPublicMessage(Client source, String chan, String from, 
String type, String[] args) {
             if (!channel.equals(chan))
                 return;
             if (type.equals("say"))

Modified: trunk/java/src/org/haverdev/javer2/JaverForm.java
===================================================================
--- trunk/java/src/org/haverdev/javer2/JaverForm.java   2005-06-21 06:46:53 UTC 
(rev 789)
+++ trunk/java/src/org/haverdev/javer2/JaverForm.java   2005-06-21 18:42:08 UTC 
(rev 790)
@@ -44,7 +44,7 @@
     SocketFactory factory;
     
     class Watcher extends Callback {
-        public void onPrivateMessage(Client source, final String from, final 
String type, final String[] args) throws Throwable {
+        public void onPrivateMessage(Client source, final String from, final 
String type, final String[] args) {
             SwingUtilities.invokeLater(new Runnable() {
                 public void run() {
                     QueryPane q = findPrivateQuery(from);

Deleted: trunk/java/src/org/haverdev/javer2/Main.java
===================================================================
--- trunk/java/src/org/haverdev/javer2/Main.java        2005-06-21 06:46:53 UTC 
(rev 789)
+++ trunk/java/src/org/haverdev/javer2/Main.java        2005-06-21 18:42:08 UTC 
(rev 790)
@@ -1,69 +0,0 @@
-/*
- * Main.java
- *
- * Created on May 21, 2005, 8:46 PM
- */
-
-package org.haverdev.javer2;
-import org.haverdev.haver.*;
-import org.haverdev.client.Client;
-
-/**
- *
- * @author bdonlan
- */
-public class Main extends org.haverdev.client.Callback {
-    Client c;
-    
-    /** Creates a new instance of Main */
-    public Main() throws Throwable {
-        c = new Client();
-        c.addNotify(this);
-        c.syncConnect("localhost", 15455, "bd_");
-        System.out.println("out");
-    }
-    
-    /**
-     * @param args the command line arguments
-     */
-    public static void main(String[] args) throws Throwable {
-        // TODO code application logic here
-        new Main();
-    }
-
-    public String join(String joinBy, String[] parts) {
-        if (parts.length == 0) return "";
-        
-        StringBuffer b = new StringBuffer();
-        for (int i = 0; i < parts.length; i++) {
-            b.append(joinBy);
-            b.append(parts[i]);
-        }
-        return b.toString().substring(joinBy.length());
-    }
-    
-    public void onDisconnected(Client source, java.io.IOException e) throws 
java.io.IOException {
-        System.out.println("dc");
-    }
-
-    public void onConnect(Client source) throws java.io.IOException {
-        System.out.println("connected");
-    }
-
-    public void onOutgoingLine(Client source, String[] args) throws 
java.io.IOException {
-        //System.out.println("out:");
-    }
-
-    public void onIncomingLine(Client source, String[] args) throws 
java.io.IOException {
-        //System.out.println("in");
-    }
-    
-    public void onAccept(Client source, String nick) throws 
java.io.IOException {
-        System.out.println("Accepted: " + nick);
-        try {
-            String[] channels = source.syncList("&lobby", "channel");
-            System.out.println("channels: " + join(", ", channels));
-        } catch (Throwable t) { t.printStackTrace(); }
-    }
-    
-}


Reply via email to