Author: bdonlan
Date: 2005-05-26 20:03:06 -0400 (Thu, 26 May 2005)
New Revision: 735

Added:
   trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultUserStore.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/EntityBase.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/FileUserStore.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/PersistBot.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/PersistTest.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/PersistantLobby.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/UserStore.java
   
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/ReservedNameException.java
   trunk/clients/Javer2/store/
Modified:
   trunk/clients/Javer2/nbproject/project.properties
   trunk/clients/Javer2/server.conf
   trunk/clients/Javer2/src/org/haverdev/haver/server/Channel.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/ChannelBase.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/ChatChannel.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultLobby.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/Entity.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/NormalContext.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/StatsBot.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/User.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java
   trunk/clients/Javer2/src/org/haverdev/haver/server/UserEntity.java
   
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/BadNameException.java
Log:
User and channel persistance; fixed some error messages

Modified: trunk/clients/Javer2/nbproject/project.properties
===================================================================
--- trunk/clients/Javer2/nbproject/project.properties   2005-05-25 07:40:52 UTC 
(rev 734)
+++ trunk/clients/Javer2/nbproject/project.properties   2005-05-27 00:03:06 UTC 
(rev 735)
@@ -37,7 +37,7 @@
 javadoc.use=true
 javadoc.version=false
 javadoc.windowtitle=
-main.class=org.haverdev.javer2.JaverForm
+main.class=org.haverdev.haver.server.Main
 manifest.file=manifest.mf
 platform.active=Java_HotSpot_TM__Client_VM_1.4.2_08-b03
 run.classpath=\

Modified: trunk/clients/Javer2/server.conf
===================================================================
--- trunk/clients/Javer2/server.conf    2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/server.conf    2005-05-27 00:03:06 UTC (rev 735)
@@ -16,9 +16,17 @@
 
 # Default chat channels
 haver.ChatChannels=lobby,conspiracy,haver,creatures
+#haver.ChatChannels=
 
+#haver.UserStore=org.haverdev.haver.server.DefaultUserStore
+haver.UserStore=org.haverdev.haver.server.FileUserStore
+org.haverdev.haver.server.FileUserStore.path=store
+
 # The lobby implementation.
-haver.Lobby=org.haverdev.haver.server.DefaultLobby
+# haver.Lobby=org.haverdev.haver.server.DefaultLobby
+haver.Lobby=org.haverdev.haver.server.PersistantLobby
+org.haverdev.haver.server.PersistantLobby.storePath=serverdata.xml.gz
+org.haverdev.haver.server.PersistantLobby.commitInterval=120
 
 # State configurations. You can list more than one command handler here and
 # they will be tried in listed order
@@ -42,7 +50,7 @@
 haver.Plugins=org.haverdev.haver.server.EntityLoader
 
 # Entities to load
-org.haverdev.haver.server.EntityLoader.entities=stats
+org.haverdev.haver.server.EntityLoader.entities=stats persist
 
 # Entity implementation
 stats.class=org.haverdev.haver.server.StatsBot
@@ -50,6 +58,9 @@
 # What string to pass to the constructor
 stats.argument=&StatsBot
 
+persist.class=org.haverdev.haver.server.PersistBot
+persist.argument=&PersistBot
+
 # Defaults
 log4j.rootLogger=DEBUG, __A1
 log4j.appender.__A1=org.apache.log4j.ConsoleAppender

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Channel.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Channel.java     
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Channel.java     
2005-05-27 00:03:06 UTC (rev 735)
@@ -6,6 +6,7 @@
 
 package org.haverdev.haver.server;
 import org.haverdev.haver.server.exceptions.*;
+
 /**
  * A representation of a Haver channel
  * @author bdonlan
@@ -17,7 +18,7 @@
      * @param name Name of the entity
      * @return whether the entity is in the channel
      */
-    public boolean contains(String namespace, String name);
+    public boolean contains(String namespace, String name) throws 
PropagatedException;
     /**
      * Determine if a given entity is in the channel
      * @param what The entity to check
@@ -82,5 +83,5 @@
      * @param name Name of the target entity
      * @return The entity if found, or <code>null</code> if not found.
      */
-    public Entity lookup(String namespace, String name);
+    public Entity lookup(String namespace, String name) throws 
PropagatedException;
 }

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/ChannelBase.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/ChannelBase.java 
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/ChannelBase.java 
2005-05-27 00:03:06 UTC (rev 735)
@@ -11,13 +11,17 @@
  *
  * @author bdonlan
  */
-public abstract class ChannelBase implements Channel {
+public abstract class ChannelBase extends EntityBase implements Channel {
     
     HashSet everything = new HashSet();
     HashMap namespaces = new HashMap();
 
     static final String[] emptyArray = {};
     
+    public ChannelBase() {
+        setPersistant(true);
+    }
+    
     public synchronized String[] getNames(String namespace) {
         HashMap subset = (HashMap)namespaces.get(namespace.toLowerCase());
         if (subset == null)

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/ChatChannel.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/ChatChannel.java 
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/ChatChannel.java 
2005-05-27 00:03:06 UTC (rev 735)
@@ -11,38 +11,37 @@
  * @author bdonlan
  */
 public class ChatChannel extends ChannelBase {
-    String name;
-    
+
     /** Creates a new instance of ChatChannel */
     public ChatChannel(String name) {
-        this.name = name.intern();
+        setName(name);
     }
+    
+    public ChatChannel() {
 
+    }
+    
     public void distributePart(Entity who) {
         User[] notify = quitListeners();
         for (int i = 0; i < notify.length; i++) {
-            notify[i].notifyPart(name, who);
+            notify[i].notifyPart(this, who);
         }
     }
 
     public void distributeJoin(Entity who) {
         User[] notify = quitListeners();
         for (int i = 0; i < notify.length; i++) {
-            notify[i].notifyJoin(name, who);
+            notify[i].notifyJoin(this, who);
         }
     }
 
     public void distributePublicMessage(Entity from, String[] args) {
         User[] who = quitListeners();
         for (int i = 0; i < who.length; i++) {
-            who[i].notifyPublicMessage(name, from.getName(), args);
+            who[i].notifyPublicMessage(this, from, args);
         }
     }
 
-    public String getName() {
-        return name;
-    }
-
     public User[] quitListeners() {
         Entity[] ents = filterContents("user");
         User[] users = new User[ents.length];

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultLobby.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultLobby.java        
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultLobby.java        
2005-05-27 00:03:06 UTC (rev 735)
@@ -12,13 +12,16 @@
  *
  * @author bdonlan
  */
-public final class DefaultLobby extends ChannelBase {
-    String name;
-    
+public class DefaultLobby extends ChannelBase {
+
     public DefaultLobby(String name) {
-        this.name = name;
+        setName(name);
     }
     
+    public DefaultLobby() {
+        setName("&lobby");
+    }
+
     public void distributePart(Entity who) {
     }
 
@@ -32,9 +35,5 @@
     public User[] quitListeners() {
         return new User[0];
     }
-
-    public String getName() {
-        return "&lobby";
-    }
-    
+   
 }

Added: trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultUserStore.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultUserStore.java    
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultUserStore.java    
2005-05-27 00:03:06 UTC (rev 735)
@@ -0,0 +1,37 @@
+/*
+ * DefaultUserStore.java
+ *
+ * Created on May 26, 2005, 7:33 PM
+ */
+
+package org.haverdev.haver.server;
+import java.util.*;
+import java.lang.ref.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class DefaultUserStore implements UserStore {
+    HashMap active = new HashMap();
+    
+    /** Creates a new instance of DefaultUserStore */
+    public DefaultUserStore() {
+    }
+    
+    public synchronized UserEntity getUser(String name) {
+        Reference r = (Reference)active.get(name);
+        UserEntity u = null;
+        if (r != null)
+            u = (UserEntity)r.get();
+        if (u == null) {
+            u = new UserEntity(name);
+            active.put(name, new WeakReference(u));
+        }
+        
+        return u;
+    }
+    
+    public void dirtyUser(UserEntity who) {
+    }
+}


Property changes on: 
trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultUserStore.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Entity.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Entity.java      
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Entity.java      
2005-05-27 00:03:06 UTC (rev 735)
@@ -21,4 +21,6 @@
      * @return The name of the entity
      */
     public String getName();
+    
+    public boolean isPersistant();
 }

Added: trunk/clients/Javer2/src/org/haverdev/haver/server/EntityBase.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/EntityBase.java  
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/EntityBase.java  
2005-05-27 00:03:06 UTC (rev 735)
@@ -0,0 +1,51 @@
+/*
+ * EntityBase.java
+ *
+ * Created on May 26, 2005, 6:02 PM
+ */
+
+package org.haverdev.haver.server;
+
+/**
+ *
+ * @author bdonlan
+ */
+public abstract class EntityBase implements Entity {
+    
+    String name = null;
+    boolean persistant = false;
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public boolean equals(Object obj) {
+        if (obj instanceof Entity) {
+            Entity obje = (Entity)obj;
+            return obje.getName().equals(getName()) &&
+                   obje.getNamespace().equals(getNamespace());
+        }
+        return false;
+    }
+
+    public String toString() {
+        return "[Entity: " + getNamespace() + " " + getName() + "]";
+    }
+
+    public int hashCode() {
+        return getNamespace().hashCode() ^ getName().hashCode();
+    }
+    
+    public boolean isPersistant() {
+        return persistant;
+    }
+    
+    public void setPersistant(boolean p) {
+        persistant = p;
+    }
+    
+}


Property changes on: 
trunk/clients/Javer2/src/org/haverdev/haver/server/EntityBase.java
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/clients/Javer2/src/org/haverdev/haver/server/FileUserStore.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/FileUserStore.java       
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/FileUserStore.java       
2005-05-27 00:03:06 UTC (rev 735)
@@ -0,0 +1,109 @@
+/*
+ * FileUserStore.java
+ *
+ * Created on May 26, 2005, 7:18 PM
+ */
+
+package org.haverdev.haver.server;
+import java.io.*;
+import java.util.*;
+import java.lang.ref.*;
+import java.beans.*;
+
+import org.apache.log4j.Logger;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class FileUserStore implements UserStore {
+    HashMap cache = new HashMap();
+    String path;
+    boolean busy = false;
+    
+    static Logger log = Logger.getLogger(FileUserStore.class);
+    
+    /** Creates a new instance of FileUserStore */
+    public FileUserStore() {
+        path = 
System.getProperty("org.haverdev.haver.server.FileUserStore.path");
+        if (path == null)
+            throw new 
IllegalArgumentException("org.haverdev.haver.server.FileUserStore.path must be 
configured");
+        path = path + File.separator;
+    }
+
+    public synchronized UserEntity getUser(String name) {
+        SoftReference ref = (SoftReference) cache.get(name);
+        UserEntity user = null;
+        if (ref != null)
+            user = (UserEntity)ref.get();
+        
+        if (user == null) {
+            try {
+                user = loadUser(name);
+            }
+            catch (FileNotFoundException e) {}
+            catch (Throwable t) {
+                log.error("While loading user " + name, t);
+            }
+            cache.put(name, new SoftReference(user));
+        }
+        
+        if (user == null)
+            user = new UserEntity(name);
+        return user;
+    }
+
+    public void dirtyUser(UserEntity who) {
+        // TODO: merge requests
+        try {
+            commitUser(who);
+        } catch (Throwable t) {
+            log.error("While committing user " + who, t);
+        }
+    }
+    
+    synchronized void commitUser(UserEntity who) throws IOException {
+        if (busy) return;
+        
+        if (!who.isPersistant()) {
+            if (cache.containsKey(who.getName())) {
+                new File(path + who.getName()).delete();
+                cache.remove(who.getName());
+                return;
+            }
+        }
+        
+        if (!cache.containsKey(who.getName()))
+            cache.put(who.getName(), new SoftReference(who));
+        
+        XMLEncoder e = new XMLEncoder
+                (new BufferedOutputStream
+                (new FileOutputStream
+                (path + who.getName()
+                )));
+        try {
+            busy = true;
+            e.writeObject(who);
+        } finally {
+            busy = false;
+        }
+        e.close();
+    }
+    
+    synchronized UserEntity loadUser(String who) throws IOException {
+        UserEntity u;
+        try {
+            busy = true;
+            XMLDecoder d = new XMLDecoder
+                    (new BufferedInputStream
+                    (new FileInputStream
+                    (path + who)));
+            u = (UserEntity)d.readObject();
+            d.close();
+        } finally {
+            busy = false;
+        }
+        return u;
+    }
+    
+}


Property changes on: 
trunk/clients/Javer2/src/org/haverdev/haver/server/FileUserStore.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java        
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java        
2005-05-27 00:03:06 UTC (rev 735)
@@ -25,12 +25,16 @@
         }
         if (Lobby.theLobby.contains("user", args[1]))
             throw new UserAlreadyExists(args[1]);
-        if (!Misc.checkName(args[1]))
-            throw new BadNameException(args[1]);
+        Misc.checkName(args[1], false);
+        
+        conn.entity = Main.theStore.getUser(args[1]);
+        conn.entity.attach(conn);
+        
         log.info("User logged in: " + args[1]);
+        
         String[] msg = {"HELLO", args[1]};
         conn.sendLine(msg);
-        conn.entity = new UserEntity(conn, args[1]);
+
         //conn.context = new NormalContext(conn, "normal");
         advance();
         conn.readThread.setName("User " + args[1]);

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java        
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java        
2005-05-27 00:03:06 UTC (rev 735)
@@ -16,6 +16,8 @@
  */
 public final class Main {
     
+    static public UserStore theStore = null;
+    
     /** Main is never instantiated */
     private Main() {
     }
@@ -36,6 +38,15 @@
         return defaults;
     }
     
+    public static final void initStore(String impl) throws Throwable {
+        ClassLoader loader = ClassLoader.getSystemClassLoader();
+        Class theClass = loader.loadClass(impl);
+        Class[] nothing_p = {};
+        Object[] nothing_a = {};
+        Constructor m = theClass.getConstructor(nothing_p);
+        theStore = (UserStore)m.newInstance(nothing_a);
+    }
+    
     public static final void initPlugin(String what) throws Throwable {
         ClassLoader loader = ClassLoader.getSystemClassLoader();
         Class theClass = loader.loadClass(what);
@@ -65,6 +76,7 @@
         PropertyConfigurator.configure(props);
         
         Lobby.initLobby(props.getProperty("haver.Lobby"));
+        initStore(props.getProperty("haver.UserStore", 
"org.haverdev.haver.server.DefaultUserStore"));
         
         String portStr = props.getProperty("haver.ListenPort", "7070");
         int port = Integer.decode(portStr).intValue();

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java        
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java        
2005-05-27 00:03:06 UTC (rev 735)
@@ -9,14 +9,15 @@
 import java.net.*;
 import java.util.regex.*;
 
+import org.haverdev.haver.server.exceptions.*;
 /**
  *
  * @author bdonlan
  */
-public class Misc {
+public final class Misc {
     
     public static final String version = "org.haverdev.haver.server/0.01";
-    public static final Pattern ident = Pattern.compile("[a-z][a-z0-9_.'@-]+", 
Pattern.CASE_INSENSITIVE);
+    public static final Pattern ident = 
Pattern.compile("^&?[a-z][a-z0-9_.'@-]+$", Pattern.CASE_INSENSITIVE);
     
     /** Static methods only */
     private Misc() {
@@ -26,17 +27,21 @@
         return s.getInetAddress().toString() + ":" + s.getPort();
     }
     
-    public static boolean checkName(String name) {
+    public static void checkName(String name, boolean reserved_ok) throws 
PropagatedException {
         Matcher m = ident.matcher(name);
         if (!m.matches())
-            return false;
+            throw new BadNameException(name);
         if (m.start() != 0)
-            return false;
+            throw new BadNameException(name);
         if (m.end() != name.length())
-            return false;
-        return true;
+            throw new BadNameException(name);
+        if (!reserved_ok && name.charAt(0) == '&')
+            throw new ReservedNameException(name);
     }
     
+    public static void checkName(String name) throws PropagatedException {
+        checkName(name, true);
+    }
         
     /**
      * Reverses Haver escaping.

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/NormalContext.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/NormalContext.java       
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/NormalContext.java       
2005-05-27 00:03:06 UTC (rev 735)
@@ -26,7 +26,7 @@
         if (margs.length == 0)
             throw new MissingMessageType();
         System.arraycopy(args, 2, margs, 0, margs.length);
-        them.sendPrivateMessage(conn.entity.getName(), margs);
+        them.sendPrivateMessage(conn.entity, margs);
     }
     
     public void handle_LIST(String[] args) throws PropagatedException {

Added: trunk/clients/Javer2/src/org/haverdev/haver/server/PersistBot.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/PersistBot.java  
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/PersistBot.java  
2005-05-27 00:03:06 UTC (rev 735)
@@ -0,0 +1,71 @@
+/*
+ * PersistBot.java
+ *
+ * Created on May 26, 2005, 7:04 PM
+ */
+
+package org.haverdev.haver.server;
+import org.apache.log4j.Logger;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class PersistBot extends EntityBase implements User {
+    
+    /** Creates a new instance of PersistBot */
+    public PersistBot(String name) {
+        setName(name);
+    }
+
+    public void notifyQuit(Entity who, String type, String detail) {
+    }
+
+    static final String[] helpMsg = { "say", "Send me a message with either 
'on' or 'off' to enable or disable persistance" };
+    static final String[] okMsg = { "say", "ok." };
+    
+    public void sendPrivateMessage(Entity from, String[] args) {
+        User ufrom = (User)from;
+        EntityBase efrom = (EntityBase)from; // XXX
+        
+        String arg;
+        
+        if (args[0].equals("say"))
+            arg = args[1];
+        else
+            arg = args[0];
+        
+        if (arg.equals("on"))
+            efrom.setPersistant(true);
+        else if (arg.equals("off"))
+            efrom.setPersistant(false);
+        else if (arg.equals("commit")) {
+            try {
+                ((PersistantLobby)Lobby.theLobby).commit();
+            } catch (java.io.IOException e) {
+                Logger.getLogger(getClass()).error("While forcing a commit", 
e);
+            }
+        }
+        else {
+            ufrom.sendPrivateMessage(this, helpMsg);
+            return;
+        }
+        ufrom.sendPrivateMessage(this, okMsg);
+    }
+
+    public void notifyPublicMessage(Entity channel, Entity from, String[] 
args) {
+
+    }
+
+    public void notifyPart(Entity channel, Entity what) {
+    }
+
+    public void notifyJoin(Entity channel, Entity what) {
+    }
+
+    public String getNamespace() {
+        return "user";
+    }
+    
+    
+}


Property changes on: 
trunk/clients/Javer2/src/org/haverdev/haver/server/PersistBot.java
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/clients/Javer2/src/org/haverdev/haver/server/PersistTest.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/PersistTest.java 
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/PersistTest.java 
2005-05-27 00:03:06 UTC (rev 735)
@@ -0,0 +1,37 @@
+/*
+ * PersistTest.java
+ *
+ * Created on May 26, 2005, 5:33 PM
+ */
+
+package org.haverdev.haver.server;
+import java.beans.*;
+import java.io.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class PersistTest {
+    
+    /** Creates a new instance of PersistTest */
+    private PersistTest() {
+    }
+    
+    public static void main(String[] args) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        UserEntity user = new UserEntity("bd_");
+        user.setPersistant(true);
+        
+        XMLEncoder e = new XMLEncoder(baos);
+        //e.setPersistenceDelegate(chan.getClass(), chan.delegate);
+        e.writeObject(user);
+        e.close();
+        System.out.println(baos.toString());
+        ByteArrayInputStream in = new ByteArrayInputStream(baos.toByteArray());
+        XMLDecoder d = new XMLDecoder(in);
+        Object o = d.readObject();
+        System.out.println("Ok, " + o);
+    }
+    
+}


Property changes on: 
trunk/clients/Javer2/src/org/haverdev/haver/server/PersistTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/clients/Javer2/src/org/haverdev/haver/server/PersistantLobby.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/PersistantLobby.java     
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/PersistantLobby.java     
2005-05-27 00:03:06 UTC (rev 735)
@@ -0,0 +1,100 @@
+/*
+ * PersistentLobby.java
+ *
+ * Created on May 26, 2005, 6:35 PM
+ */
+
+package org.haverdev.haver.server;
+import java.io.*;
+import java.beans.*;
+import java.util.zip.*;
+import java.util.*;
+
+import org.apache.log4j.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class PersistantLobby extends DefaultLobby {
+    static final Timer commitTimer = new Timer(true);
+    TimerTask commitTask;
+    
+    String storePath;
+    
+    static final Logger logger = Logger.getLogger(PersistantLobby.class);
+    
+    /** Creates a new instance of PersistentLobby */
+    public PersistantLobby() throws java.io.IOException {
+        super();
+        setPersistant(false);
+        storePath = 
System.getProperty("org.haverdev.haver.server.PersistantLobby.storePath");
+        
+        long commitInterval =
+                
Long.getLong("org.haverdev.haver.server.PersistantLobby.commitInterval", 
120).longValue() * 1000;
+        
+        commitTask = null;
+        
+        try {
+            loadAll();
+        } catch (FileNotFoundException e) {
+            logger.warn("storePath \"" + storePath + "\" not found, starting 
fresh...");
+        }
+        
+        commitTask = new TimerTask() {
+            public void run() {
+                try {
+                    commit();
+                } catch (Throwable t) {
+                    logger.error("While committing", t);
+                }
+            }
+        };
+
+        commitTimer.schedule(commitTask, commitInterval, commitInterval);
+    }
+    
+    public PersistantLobby(String name) throws IOException {
+        this();
+        setName(name);
+    }
+    
+    void loadAll() throws IOException {
+        FileInputStream fs = new FileInputStream(storePath);
+        GZIPInputStream zs = new GZIPInputStream(fs);
+        BufferedInputStream bs = new BufferedInputStream(zs);
+        XMLDecoder d = new XMLDecoder(bs);
+        while (true) {
+            try {
+                Object o = d.readObject();
+                if (o instanceof Entity) {
+                    register((Entity)o);
+                } else {
+                    logger.error("Deserialized non-entity object: " + o);
+                }
+            }
+            catch (ArrayIndexOutOfBoundsException e) { break; }
+        }
+        d.close();
+    }
+    
+    public void commit() throws IOException {
+        XMLEncoder e = new XMLEncoder
+                (new BufferedOutputStream
+                (new GZIPOutputStream
+                (new FileOutputStream
+                (storePath))));
+        logger.debug("Committing...");
+        Entity[] everything = getContents();
+        for (int i = 0; i < everything.length; i++)
+            if (everything[i].isPersistant())
+                e.writeObject(everything[i]);
+        e.close();
+    }
+
+    protected void finalize() throws Throwable {
+        commit();
+        super.finalize();
+    }
+    
+}


Property changes on: 
trunk/clients/Javer2/src/org/haverdev/haver/server/PersistantLobby.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/StatsBot.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/StatsBot.java    
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/StatsBot.java    
2005-05-27 00:03:06 UTC (rev 735)
@@ -10,14 +10,16 @@
  *
  * @author bdonlan
  */
-public class StatsBot implements User {
-    String name;
+public class StatsBot extends EntityBase implements User {
     
     /** Creates a new instance of StatsBot */
     public StatsBot(String name) {
-        this.name = name;
+        setName(name);
     }
     
+    public StatsBot() {
+    }
+    
     static String[] formats = { " bytes", " Kbytes", " Mbytes", " Gbytes" };
     
     static String formatSize(long s) {
@@ -29,16 +31,14 @@
         return "" + s + formats[idx];
     }
     
-    public void notifyPart(String channel, Entity what) {
+    public void notifyPart(Entity channel, Entity what) {
     }
 
-    public void notifyJoin(String channel, Entity what) {
+    public void notifyJoin(Entity channel, Entity what) {
     }
 
-    public void sendPrivateMessage(String from, String[] args) {
-        User efrom = (User)Lobby.theLobby.lookup("user", from);
-        if (efrom == null)
-            return;
+    public void sendPrivateMessage(Entity from, String[] args) {
+        User ufrom = (User)from;
         Runtime rt = Runtime.getRuntime();
 
         String[] version = { "say", Misc.version };
@@ -60,28 +60,20 @@
                 + formatSize(rt.maxMemory())   + "/"
                 + formatSize(rt.totalMemory()) + "/"
         };
-        efrom.sendPrivateMessage(name, version);
-        efrom.sendPrivateMessage(name, jvm_a);
-        efrom.sendPrivateMessage(name, osinfo);
-        efrom.sendPrivateMessage(name, memstats);
-
-        
+        ufrom.sendPrivateMessage(this, version);
+        ufrom.sendPrivateMessage(this, jvm_a);
+        ufrom.sendPrivateMessage(this, osinfo);
+        ufrom.sendPrivateMessage(this, memstats);
     }
 
-    public void notifyPublicMessage(String channel, String from, String[] 
args) {
+    public void notifyPublicMessage(Entity channel, Entity from, String[] 
args) {
     }
 
-    public void notifyQuit(String who, String type, String detail) {
+    public void notifyQuit(Entity who, String type, String detail) {
     }
 
     public String getNamespace() {
         return "user";
     }
 
-    public String getName() {
-        return name;
-    }
-    
-    
-    
 }

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/User.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/User.java        
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/User.java        
2005-05-27 00:03:06 UTC (rev 735)
@@ -11,9 +11,9 @@
  * @author bdonlan
  */
 public interface User extends Entity {
-    public void sendPrivateMessage(String from, String[] args);
-    public void notifyPublicMessage(String channel, String from, String[] 
args);
-    public void notifyJoin(String channel, Entity what);
-    public void notifyPart(String channel, Entity what);
-    public void notifyQuit(String who, String type, String detail);
+    public void sendPrivateMessage(Entity from, String[] args);
+    public void notifyPublicMessage(Entity channel, Entity from, String[] 
args);
+    public void notifyJoin(Entity channel, Entity what);
+    public void notifyPart(Entity channel, Entity what);
+    public void notifyQuit(Entity who, String type, String detail);
 }

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java      
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java      
2005-05-27 00:03:06 UTC (rev 735)
@@ -164,14 +164,16 @@
     }
     
     protected synchronized void cutConnection() {
-        synchronized (writer) {
-            try { writer.close(); } catch (Throwable t) { }
-            try {
-                Thread.sleep(1000); // Hopefully flush the writer
-                                    // XXX: blocking close/flush
-            } catch (InterruptedException e) {}
-            try { sock.close(); } catch (Throwable t) { }
-            writer = null;
+        if (writer != null) {
+            synchronized (writer) {
+                try { writer.close(); } catch (Throwable t) { }
+                try {
+                    Thread.sleep(1000); // Hopefully flush the writer
+                                        // XXX: blocking close/flush
+                } catch (InterruptedException e) {}
+                try { sock.close(); } catch (Throwable t) { }
+                writer = null;
+            }
         }
         synchronized (pingLock) {
             if (pingTimer != null) pingTimer.cancel();

Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/UserEntity.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserEntity.java  
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserEntity.java  
2005-05-27 00:03:06 UTC (rev 735)
@@ -12,32 +12,67 @@
  *
  * @author bdonlan
  */
- class UserEntity implements User {
-     String name;
-     HashSet channels = new HashSet();
-     UserConnection conn;
+public class UserEntity extends EntityBase implements User {
+     HashSet channels = null;
+     UserConnection conn = null;
      
-     UserEntity(UserConnection conn, String name) throws PropagatedException {
-         this.name = name.intern();
+     HashMap props = new HashMap();
+     
+     public void setPersistant(boolean p) {
+         super.setPersistant(p);
+         Main.theStore.dirtyUser(this);
+         // TODO
+     }
+     
+     public UserEntity() {
+         
+     }
+     
+     public UserEntity(String name) {
+         setName(name);
+     }
+     
+     public UserEntity(UserConnection conn, String name) throws 
PropagatedException {
+         setName(name);
+         attach(conn);
+     }
+     
+     public synchronized void attach(UserConnection conn) throws 
PropagatedException {
+         if (this.conn != null)
+             throw new IllegalStateException("Trying to attach when already 
live");
          this.conn = conn;
+         channels = new HashSet();
          join(Lobby.theLobby);
      }
      
-     public void notifyPart(String channel, Entity what) {
-         String[] msg = {"PART", channel, what.getName()};
+     public void detach() {
+         if (conn == null)
+             return;
+         quit("discon", null);
+     }
+
+     // XXX: not synchronized due to possible race.
+     // TODO: find a better fix
+     public void notifyPart(Entity channel, Entity what) {
+         if (conn == null) return; // XXX: better fail?
+         String[] msg = {"PART", channel.getName(), what.getName()};
          conn.sendLine(msg);
      }
      
-     public void notifyJoin(String channel, Entity what) {
-         String[] msg = {"JOIN", channel, what.getName()};
+     // XXX: not synchronized due to possible race.
+     // TODO: find a better fix
+     public  void notifyJoin(Entity channel, Entity what) {
+         if (conn == null) return; // XXX: better fail?
+         String[] msg = {"JOIN", channel.getName(), what.getName()};
          conn.sendLine(msg);
      }
      
-     public void notifyPublicMessage(String channel, String from, String[] 
args) {
+     public synchronized void notifyPublicMessage(Entity channel, Entity from, 
String[] args) {
+         if (conn == null) return; // XXX: better fail?
          String[] msg = new String[args.length + 3];
          msg[0] = "IN";
-         msg[1] = channel;
-         msg[2] = from;
+         msg[1] = channel.getName();
+         msg[2] = from.getName();
          System.arraycopy(args, 0, msg, 3, args.length);
          conn.sendLine(msg);
      }
@@ -46,45 +81,29 @@
          return "user";
      }
      
-     public String getName() {
-         return name;
-     }
-     
-     public void sendPrivateMessage(String from, String[] args) {
+     public synchronized void sendPrivateMessage(Entity from, String[] args) {
+         if (conn == null) return; // XXX: better fail?
          String[] msg = new String[args.length + 2];
          msg[0] = "FROM";
-         msg[1] = from;
+         msg[1] = from.getName();
          System.arraycopy(args, 0, msg, 2, args.length);
          conn.sendLine(msg);
      }
      
-     public void notifyQuit(String who, String type, String detail) {
+     // XXX: not synchronized due to possible race.
+     // TODO: find a better fix
+     public void notifyQuit(Entity who, String type, String detail) {
+         if (conn == null) return;
          if (detail != null) {
-             String[] msg = { "QUIT", who, type, detail };
+             String[] msg = { "QUIT", who.getName(), type, detail };
              conn.sendLine(msg);
          } else {
-             String[] msg = { "QUIT", who, type };
+             String[] msg = { "QUIT", who.getName(), type };
              conn.sendLine(msg);
          }
      }
      
-     public boolean equals(Object obj) {
-         if (obj == null)
-             return false;
-         if (!(obj instanceof User))
-             return false;
-         return ((User)obj).getName().equals(name);
-     }
-     
-     public String toString() {
-         return "user: " + name;
-     }
-     
-     public int hashCode() {
-         return name.hashCode() ^ "user".hashCode();
-     }
-     
-     public void quit(String why, String detail) {
+     public synchronized void quit(String why, String detail) {
          Iterator i = channels.iterator();
          // XXX
          HashSet interested_parties = new HashSet();
@@ -99,10 +118,17 @@
          i = interested_parties.iterator();
          while (i.hasNext()) {
              User u = (User)i.next();
-             u.notifyQuit(name, why, detail);
+             u.notifyQuit(this, why, detail);
          }
+         channels = null;
+         conn = null;
      }
      
+     public synchronized void drop(Channel channel) {
+         channel.unregister(this);
+         channels.remove(channel);
+     }
+     
      public synchronized void join(Channel channel) throws PropagatedException 
{
          if (channels.contains(channel)) throw new 
AlreadyThereJoin(channel.getName());
          channel.register(this);
@@ -113,7 +139,6 @@
      public synchronized void part(Channel channel) throws PropagatedException 
{
          if (!channels.contains(channel)) throw new 
NotPresentPart(channel.getName());
          channel.distributePart(this);
-         channel.unregister(this);
-         channels.remove(channel);
+         drop(channel);
      }
  }
\ No newline at end of file

Added: trunk/clients/Javer2/src/org/haverdev/haver/server/UserStore.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserStore.java   
2005-05-25 07:40:52 UTC (rev 734)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserStore.java   
2005-05-27 00:03:06 UTC (rev 735)
@@ -0,0 +1,19 @@
+/*
+ * UserStore.java
+ *
+ * Created on May 26, 2005, 7:17 PM
+ */
+
+package org.haverdev.haver.server;
+
+/**
+ *
+ * @author bdonlan
+ */
+public interface UserStore {
+    
+    // This should _only_ be used for login purposes. It does not serve as
+    // a &lobby substitute.
+    public UserEntity getUser(String name);
+    public void dirtyUser(UserEntity who);
+}


Property changes on: 
trunk/clients/Javer2/src/org/haverdev/haver/server/UserStore.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: 
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/BadNameException.java
===================================================================
--- 
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/BadNameException.java
 2005-05-25 07:40:52 UTC (rev 734)
+++ 
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/BadNameException.java
 2005-05-27 00:03:06 UTC (rev 735)
@@ -14,7 +14,7 @@
     
     /** Creates a new instance of BadNameException */
     public BadNameException(String name) {
-        super("syntax.name", name);
+        super("invalid.user", name);
     }
     
 }

Added: 
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/ReservedNameException.java
===================================================================
--- 
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/ReservedNameException.java
    2005-05-25 07:40:52 UTC (rev 734)
+++ 
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/ReservedNameException.java
    2005-05-27 00:03:06 UTC (rev 735)
@@ -0,0 +1,20 @@
+/*
+ * ReservedNameException.java
+ *
+ * Created on May 26, 2005, 7:58 PM
+ */
+
+package org.haverdev.haver.server.exceptions;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class ReservedNameException extends SimplePropagatedException {
+    
+    /** Creates a new instance of ReservedNameException */
+    public ReservedNameException(String name) {
+        super("reserved.user", name);
+    }
+    
+}


Property changes on: 
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/ReservedNameException.java
___________________________________________________________________
Name: svn:eol-style
   + native


Reply via email to