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