Author: bdonlan
Date: 2005-05-24 22:59:42 -0400 (Tue, 24 May 2005)
New Revision: 731
Added:
trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultLobby.java
trunk/clients/Javer2/src/org/haverdev/haver/server/InitContext.java
trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
trunk/clients/Javer2/src/org/haverdev/haver/server/MergingContext.java
trunk/clients/Javer2/src/org/haverdev/haver/server/NormalContext.java
trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandHandler.java
trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandReflect.java
trunk/clients/Javer2/src/org/haverdev/haver/server/UserContextFactory.java
trunk/clients/Javer2/src/org/haverdev/haver/server/UserEntity.java
trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.form
trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.java
trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.form
trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.java
trunk/clients/Javer2/src/org/haverdev/javer2/Pane.java
trunk/clients/Javer2/src/org/haverdev/javer2/QueryPane.java
trunk/clients/Javer2/src/org/haverdev/javer2/ServerPane.java
trunk/clients/Javer2/src/org/haverdev/javer2/TextPane.form
trunk/clients/Javer2/src/org/haverdev/javer2/TextPane.java
Modified:
trunk/clients/Javer2/nbproject/project.properties
trunk/clients/Javer2/server.conf
trunk/clients/Javer2/src/org/haverdev/haver/Callback.java
trunk/clients/Javer2/src/org/haverdev/haver/Client.java
trunk/clients/Javer2/src/org/haverdev/haver/server/Channel.java
trunk/clients/Javer2/src/org/haverdev/haver/server/EntityLoader.java
trunk/clients/Javer2/src/org/haverdev/haver/server/Lobby.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/UserConnection.java
trunk/clients/Javer2/src/org/haverdev/javer2/CMod.java
Log:
Lots of things happened. Like the config file, that's important. Or the client
GUI (still woefully incomplete).
Modified: trunk/clients/Javer2/nbproject/project.properties
===================================================================
--- trunk/clients/Javer2/nbproject/project.properties 2005-05-24 21:42:18 UTC
(rev 730)
+++ trunk/clients/Javer2/nbproject/project.properties 2005-05-25 02:59:42 UTC
(rev 731)
@@ -37,7 +37,7 @@
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
-main.class=org.haverdev.haver.server.AcceptLoop
+main.class=org.haverdev.javer2.JaverForm
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-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/server.conf 2005-05-25 02:59:42 UTC (rev 731)
@@ -1,11 +1,56 @@
#Tue May 24 16:20:29 EDT 2005
+
+# This file is absolutely vital for the server to start. Sorry.
+
+# Which port to listen on
haver.ListenPort=7070
+
+# Time after a S: PING before disconnect
+haver.PingTimeout=30
+
+# Time after a C: PONG before the next ping
+haver.PingInterval=60
+
+# The amount of time the full login negotiation (from connect to S: ACCEPT) is
allowed
+haver.HandshakeTimeout=120
+
+# Default chat channels
haver.ChatChannels=lobby,conspiracy,haver,creatures
+# The lobby implementation.
+haver.Lobby=org.haverdev.haver.server.DefaultLobby
+
+# State configurations. You can list more than one command handler here and
+# they will be tried in listed order
+haver.state.init=init
+haver.state.login=login
+haver.state.normal=normal
+
+# The implementation class
+init.class=org.haverdev.haver.server.InitContext
+# The next class in the state machine
+init.successor=login
+
+login.class=org.haverdev.haver.server.LoginContext
+login.successor=normal
+
+normal.class=org.haverdev.haver.server.NormalContext
+
+# Optional stugg
+
+# Plugin classes to load
haver.Plugins=org.haverdev.haver.server.EntityLoader
-org.haverdev.haver.server.EntityLoader.entities=&stats
-&stats.class=org.haverdev.haver.server.StatsBot
+# Entities to load
+org.haverdev.haver.server.EntityLoader.entities=stats
+
+# Entity implementation
+stats.class=org.haverdev.haver.server.StatsBot
+
+# What string to pass to the constructor
+stats.argument=&StatsBot
+
+# Defaults
log4j.rootLogger=DEBUG, __A1
log4j.appender.__A1=org.apache.log4j.ConsoleAppender
log4j.appender.__A1.layout=org.apache.log4j.PatternLayout
Modified: trunk/clients/Javer2/src/org/haverdev/haver/Callback.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/Callback.java 2005-05-24
21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/Callback.java 2005-05-25
02:59:42 UTC (rev 731)
@@ -81,4 +81,7 @@
public void onPart(Client source, String channel, String who) throws
Throwable {}
public void onQuit(Client source, String who, String type, String detail)
throws Throwable {}
+
+ // XXX: this is a hack and should not be used in apps
+ void onFail(Client source, String[] args) throws Throwable {};
}
Modified: trunk/clients/Javer2/src/org/haverdev/haver/Client.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/Client.java 2005-05-24
21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/Client.java 2005-05-25
02:59:42 UTC (rev 731)
@@ -32,6 +32,10 @@
String host;
int port;
+ public String getName() {
+ return name;
+ }
+
/**
* Mutable boolean flag
*/
@@ -336,6 +340,20 @@
}
}
}
+
+ void onFail(Client source, String[] args) throws IOException {
+ 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();
+ }
+ }
+ }
}
@@ -376,6 +394,7 @@
ioLoop(new Flag());
} catch (IOException e) {
try {
+ // XXX: may be called more than once
dist.onDisconnected(this, e);
} catch (IOException e2) {
}
@@ -388,7 +407,7 @@
* @param args Arguments of the line to send
* @throws java.io.IOException
*/
- protected synchronized void sendLine(String[] args) throws IOException {
+ protected synchronized void sendLine(String[] args) {
if (writer != null) {
String l = encodeLine(args);
System.out.print("C: " + l);
@@ -468,6 +487,11 @@
*/
private Object ret = null;
+ protected synchronized void fail(IOException e) {
+ fail = e;
+ done(null);
+ }
+
public SyncMonitor() {
addNotify(this);
}
@@ -487,13 +511,11 @@
public synchronized void onDisconnected(Client source, IOException e) {
if (e == null)
e = new IOException("Disconnected unexpectedly");
- fail = e;
- done(null);
+ fail(e);
}
public synchronized void onConnectFailed(Client source, IOException e)
{
- fail = e;
- done(null);
+ fail(e);
}
/**
@@ -538,9 +560,14 @@
source.ident(name);
}
- public synchronized void onAccept(Client source, String name) {
+ public void onAccept(Client source, String name) {
done(null);
}
+
+ void onFail(Client source, String[] args) {
+ // XXX
+ fail(new IOException("Something broke: " + args[2]));
+ }
}
/**
@@ -649,7 +676,7 @@
* @param namespace Namespace to filter results by
* @throws java.io.IOException
*/
- public void requestList(String channel, String namespace) throws
IOException {
+ public void requestList(String channel, String namespace) {
String[] cmd = {"LIST", channel, namespace};
sendLine(cmd);
}
@@ -687,6 +714,11 @@
done(list);
}
}
+ void onFail(Client source, String[] args) {
+ // XXX
+ if (args.length >= 4 && args[1].equals("LIST") &&
args[3].equals(channel))
+ fail(new IOException("Something broke: " + args[2]));
+ }
}
/**
@@ -719,7 +751,7 @@
dist.onPublicMessage(this, channel, from, type, margs);
}
- public void sendPublicMessage(String channel, String type, String[] margs)
throws IOException {
+ public void sendPublicMessage(String channel, String type, String[] margs)
{
String[] cmd = new String[margs.length + 3];
cmd[0] = "IN";
cmd[1] = channel;
@@ -728,7 +760,7 @@
sendLine(cmd);
}
- public void sendPublicMessage(String channel, String type, String arg)
throws IOException {
+ public void sendPublicMessage(String channel, String type, String arg) {
String[] args = {arg};
sendPublicMessage(channel, type, args);
}
@@ -747,7 +779,7 @@
dist.onPrivateMessage(this, user, type, margs);
}
- public void sendPrivateMessage (String target, String type, String[]
margs) throws IOException {
+ public void sendPrivateMessage (String target, String type, String[]
margs) {
String[] args = new String[margs.length + 3];
args[0] = "TO";
args[1] = target;
@@ -756,7 +788,7 @@
sendLine(args);
}
- public void sendPrivateMessage (String target, String type, String arg)
throws IOException {
+ public void sendPrivateMessage (String target, String type, String arg) {
String[] args = {arg};
sendPrivateMessage(target, type, args);
}
@@ -780,7 +812,7 @@
dist.onQuit(this, who, type, detail);
}
- public void sendJoin(String channel) throws IOException {
+ public void sendJoin(String channel) {
String[] cmd = {"JOIN", channel};
sendLine(cmd);
}
@@ -797,6 +829,12 @@
this.done(null);
}
}
+
+ void onFail(Client source, String[] args) {
+ // XXX
+ if (args.length >= 4 && args[1].equals("JOIN") &&
args[3].equals(channel))
+ fail(new IOException("Something broke: " + args[2]));
+ }
}
public void syncJoin(String channel) throws IOException,
InterruptedException {
@@ -822,6 +860,12 @@
this.done(null);
}
}
+
+ void onFail(Client source, String[] args) {
+ // XXX
+ if (args.length >= 4 && args[1].equals("PART") &&
args[3].equals(channel))
+ fail(new IOException("Something broke: " + args[2]));
+ }
}
public void syncPart(String channel) throws IOException,
InterruptedException {
@@ -834,4 +878,9 @@
killConnection();
}
+ public void handle_FAIL(String[] args) throws IOException {
+ // XXX
+ dist.onFail(this, args);
+ }
+
}
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Channel.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Channel.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Channel.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -5,7 +5,7 @@
*/
package org.haverdev.haver.server;
-
+import org.haverdev.haver.server.exceptions.*;
/**
* A representation of a Haver channel
* @author bdonlan
@@ -64,17 +64,17 @@
* @param from Entity originating the message
* @param args The message itself
*/
- public void distributePublicMessage(Entity from, String[] args);
+ public void distributePublicMessage(Entity from, String[] args) throws
PropagatedException;
/**
* Notify all interested members of the channel about a join event
* @param who The entity that has joined
*/
- public void distributeJoin(Entity who);
+ public void distributeJoin(Entity who) throws PropagatedException;
/**
* Notify all interested members of the channel about a part event
* @param who The entity that left
*/
- public void distributePart(Entity who);
+ public void distributePart(Entity who) throws PropagatedException;
/**
* Find an entity with the given name and namespace in the channel
Added: trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultLobby.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultLobby.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultLobby.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,40 @@
+/*
+ * Lobby.java
+ *
+ * Created on May 23, 2005, 7:41 PM
+ */
+
+package org.haverdev.haver.server;
+import org.haverdev.haver.server.exceptions.*;
+import java.util.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public final class DefaultLobby extends ChannelBase {
+ String name;
+
+ public DefaultLobby(String name) {
+ this.name = name;
+ }
+
+ public void distributePart(Entity who) {
+ }
+
+ public void distributeJoin(Entity who) {
+ }
+
+ public void distributePublicMessage(Entity from, String[] args) throws
PropagatedException {
+ throw new Forbidden("&lobby");
+ }
+
+ public User[] quitListeners() {
+ return new User[0];
+ }
+
+ public String getName() {
+ return "&lobby";
+ }
+
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/haver/server/DefaultLobby.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/EntityLoader.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/EntityLoader.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/EntityLoader.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -22,6 +22,7 @@
static final void initEntity(String name) throws Throwable {
String clas = System.getProperty(name + ".class");
+ String arg = System.getProperty(name + ".argument", name);
if (clas == null)
throw new IllegalArgumentException("Missing " + name + ".class
property");
@@ -29,7 +30,7 @@
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class theClass = loader.loadClass(clas);
Class[] proto = {name.getClass()};
- Object[] args = {name};
+ Object[] args = {arg};
Constructor cons = theClass.getConstructor(proto);
Object ret = cons.newInstance(args);
Lobby.theLobby.register((Entity)ret);
Added: trunk/clients/Javer2/src/org/haverdev/haver/server/InitContext.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/InitContext.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/InitContext.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,35 @@
+/*
+ * InitContext.java
+ *
+ * Created on May 24, 2005, 7:39 PM
+ */
+
+package org.haverdev.haver.server;
+import org.haverdev.haver.server.exceptions.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class InitContext extends UserCommandReflect {
+ static final String[] greeting = { "HAVER", Misc.version };
+
+ public InitContext(UserConnection conn, String name) {
+ super(conn, name);
+ }
+
+ public void handle_HAVER(String[] args) throws PropagatedException {
+ log.info("Client identifies itself as " + args[1]);
+ conn.sendLine(greeting);
+ //conn.context = new LoginContext(conn, "login");
+ advance();
+ }
+
+ public void processCommand(String[] cmd) {
+ try {
+ super.processCommand(cmd);
+ } catch (PropagatedException e) {
+ conn.cutConnection();
+ }
+ }
+}
\ No newline at end of file
Property changes on:
trunk/clients/Javer2/src/org/haverdev/haver/server/InitContext.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Lobby.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Lobby.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Lobby.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -1,41 +1,34 @@
/*
* Lobby.java
*
- * Created on May 23, 2005, 7:41 PM
+ * Created on May 24, 2005, 6:31 PM
*/
package org.haverdev.haver.server;
-import java.util.*;
-
+import java.lang.reflect.*;
/**
*
* @author bdonlan
*/
-public final class Lobby extends ChannelBase {
- public static final Lobby theLobby = new Lobby();
+public final class Lobby {
- /** There can be only one */
+ /** Creates a new instance of Lobby */
private Lobby() {
- register(this);
- register(new ChatChannel("test"));
}
- public void distributePart(Entity who) {
- }
-
- public void distributeJoin(Entity who) {
- }
-
- public void distributePublicMessage(Entity from, String[] args) {
- throw new UnsupportedOperationException("&lobby does not support
messaging.");
- }
-
- public User[] quitListeners() {
- return new User[0];
- }
-
- public String getName() {
- return "&lobby";
- }
+ public static Channel theLobby = null;
+ public synchronized static void initLobby(String classname) throws
Throwable {
+ if (theLobby != null)
+ throw new IllegalStateException("Lobby is already set");
+ ClassLoader l = ClassLoader.getSystemClassLoader();
+ Class clas = l.loadClass(classname);
+ Class[] args_p = {"&lobby".getClass()};
+ Object[] args = {"&lobby"};
+
+ Constructor m = clas.getConstructor(args_p);
+ Channel c = (Channel)m.newInstance(args);
+ c.register(c);
+ theLobby = c;
+ }
}
Added: trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,39 @@
+/*
+ * LoginContext.java
+ *
+ * Created on May 24, 2005, 7:40 PM
+ */
+
+package org.haverdev.haver.server;
+import org.haverdev.haver.server.exceptions.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class LoginContext extends UserCommandReflect {
+
+ public LoginContext(UserConnection conn, String name) {
+ super(conn, name);
+ }
+
+ public void handle_IDENT(String[] args) throws PropagatedException {
+ synchronized (conn.pingLock) {
+ conn.handshakeAbort.cancel();
+ if (conn.writer == null) // Too late
+ return;
+ }
+ if (Lobby.theLobby.contains("user", args[1]))
+ throw new UserAlreadyExists(args[1]);
+ if (!Misc.checkName(args[1]))
+ throw new BadNameException(args[1]);
+ 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]);
+ conn.schedulePing();
+ }
+}
\ No newline at end of file
Property changes on:
trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -23,6 +23,10 @@
public static final Properties buildDefaults() {
Properties defaults = new Properties(System.getProperties());
defaults.setProperty("haver.ListenPort", "7070");
+ defaults.setProperty("haver.PingTimeout", "30");
+ defaults.setProperty("haver.PingInterval", "60");
+ defaults.setProperty("haver.HandshakeTimeout", "120");
+ defaults.setProperty("haver.Lobby",
"org.haverdev.haver.server.DefaultLobby");
defaults.setProperty("log4j.rootLogger", "DEBUG, __A1");
defaults.setProperty("log4j.appender.__A1",
"org.apache.log4j.ConsoleAppender");
defaults.setProperty("log4j.appender.__A1.layout",
"org.apache.log4j.PatternLayout");
@@ -60,6 +64,8 @@
System.setProperties(props);
PropertyConfigurator.configure(props);
+ Lobby.initLobby(props.getProperty("haver.Lobby"));
+
String portStr = props.getProperty("haver.ListenPort", "7070");
int port = Integer.decode(portStr).intValue();
Added: trunk/clients/Javer2/src/org/haverdev/haver/server/MergingContext.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/MergingContext.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/MergingContext.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,30 @@
+/*
+ * MergingContext.java
+ *
+ * Created on May 24, 2005, 6:48 PM
+ */
+
+package org.haverdev.haver.server;
+import java.util.*;
+import org.haverdev.haver.server.exceptions.*;
+/**
+ *
+ * @author bdonlan
+ */
+public class MergingContext extends java.util.LinkedHashSet implements
UserCommandHandler {
+
+ public synchronized void processCommand(String[] cmd) throws
PropagatedException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ UserCommandHandler ctx = (UserCommandHandler)i.next();
+ try {
+ ctx.processCommand(cmd);
+ return;
+ } catch (UnknownClientCommandException e) {
+ continue;
+ }
+ }
+ throw new UnknownClientCommandException(cmd);
+ }
+
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/haver/server/MergingContext.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -36,4 +36,83 @@
return false;
return true;
}
+
+
+ /**
+ * 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();
+ }
}
Added: trunk/clients/Javer2/src/org/haverdev/haver/server/NormalContext.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/NormalContext.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/NormalContext.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,99 @@
+/*
+ * NormalContext.java
+ *
+ * Created on May 24, 2005, 7:44 PM
+ */
+
+package org.haverdev.haver.server;
+import org.haverdev.haver.server.exceptions.*;
+import java.util.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class NormalContext extends UserCommandReflect {
+ public NormalContext(UserConnection conn, String name) {
+ super(conn, name);
+ }
+
+ public void handle_TO(String[] args) throws PropagatedException {
+ String who = args[1];
+ User them = (User)Lobby.theLobby.lookup("user", who);
+ if (them == null)
+ throw new UserNotFound(who);
+ String margs[] = new String[args.length - 2];
+ if (margs.length == 0)
+ throw new MissingMessageType();
+ System.arraycopy(args, 2, margs, 0, margs.length);
+ them.sendPrivateMessage(conn.entity.getName(), margs);
+ }
+
+ public void handle_LIST(String[] args) throws PropagatedException {
+ String channel = args[1];
+ String filter = args[2];
+ Channel theChannel = (Channel)Lobby.theLobby.lookup("channel",
channel);
+ if (theChannel == null)
+ throw new ChannelNotFound(channel);
+ String[] members = theChannel.getNames(filter);
+ String[] response = new String[members.length + 3];
+ System.arraycopy(args, 0, response, 0, 3);
+ System.arraycopy(members, 0, response, 3, members.length);
+ conn.sendLine(response);
+ }
+
+ public void handle_JOIN(String[] args) throws PropagatedException {
+ String channel = args[1];
+ Channel chan_e = (Channel)Lobby.theLobby.lookup("channel", channel);
+ if (chan_e == null)
+ throw new ChannelNotFound(channel);
+ // Special case!
+ if (chan_e == Lobby.theLobby)
+ throw new Forbidden("&lobby");
+ conn.entity.join(chan_e);
+ }
+
+ public void handle_PART(String[] args) throws PropagatedException {
+ String channel = args[1];
+ Channel chan_e = (Channel)Lobby.theLobby.lookup("channel", channel);
+ // Special case!
+ if (chan_e == Lobby.theLobby)
+ throw new Forbidden("&lobby");
+ conn.entity.part(chan_e);
+ }
+
+ public void handle_IN(String[] args) throws PropagatedException {
+ String channel = args[1]; // TODO: check presence
+ Channel chan_e = (Channel)Lobby.theLobby.lookup("channel", channel);
+ if (chan_e == null)
+ throw new ChannelNotFound(channel);
+ String[] margs = new String[args.length - 2];
+ if (margs.length == 0)
+ throw new MissingMessageType();
+ System.arraycopy(args, 2, margs, 0, margs.length);
+ chan_e.distributePublicMessage(conn.entity, margs);
+ }
+
+ public void handle_POKE(String[] args) {
+ args[0] = "OUCH";
+ conn.sendLine(args);
+ }
+
+ public void handle_PONG(String[] args) {
+ conn.ackPong(args[1]);
+ }
+
+ public void handle_BYE(String[] args) {
+ String detail = args.length > 1 ? args[1] : null;
+ conn.cutConnection("active", detail);
+ }
+
+ // Debug hack
+ public void handle_NOPING(String[] args) {
+ synchronized (conn.pingLock) {
+ if (conn.pingTimer != null) conn.pingTimer.cancel();
+ if (conn.pongTimer != null) conn.pongTimer.cancel();
+ conn.pingTimer = conn.pongTimer = null;
+ }
+ }
+}
\ No newline at end of file
Property changes on:
trunk/clients/Javer2/src/org/haverdev/haver/server/NormalContext.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added:
trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandHandler.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandHandler.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandHandler.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,15 @@
+/*
+ * UserCommandContext.java
+ *
+ * Created on May 24, 2005, 6:44 PM
+ */
+
+package org.haverdev.haver.server;
+import org.haverdev.haver.server.exceptions.*;
+/**
+ *
+ * @author bdonlan
+ */
+public interface UserCommandHandler {
+ public void processCommand(String[] cmd) throws PropagatedException;
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandHandler.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added:
trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandReflect.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandReflect.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandReflect.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,64 @@
+/*
+ * UserCommandReflect.java
+ *
+ * Created on May 24, 2005, 6:45 PM
+ */
+
+package org.haverdev.haver.server;
+import org.haverdev.haver.server.exceptions.*;
+import java.lang.reflect.*;
+import org.apache.log4j.Logger;
+
+/**
+ *
+ * @author bdonlan
+ */
+public abstract class UserCommandReflect implements UserCommandHandler {
+ Logger log = Logger.getLogger(getClass());
+
+ protected UserConnection conn;
+ protected String name;
+
+ public UserCommandReflect(UserConnection conn, String name) {
+ this.conn = conn;
+ this.name = name;
+ }
+
+ protected void advance() throws PropagatedException {
+ try {
+ synchronized (conn) { // XXX: racy?
+ conn.context = UserContextFactory.constructState(conn,
System.getProperty(name + ".successor"));
+ }
+ } catch (PropagatedException e) {
+ throw e;
+ } catch (Throwable t) {
+ throw new InternalCommandException("UNKNOWN", t);
+ }
+ }
+
+ public void processCommand(String[] cmd) throws PropagatedException {
+ if (!cmd[0].toUpperCase().equals(cmd[0])) throw new
UnknownClientCommandException(cmd);
+ Class myClass = getClass();
+ Class[] argTypes = {cmd.getClass()};
+ Method m;
+ try {
+ m = myClass.getMethod("handle_" + cmd[0], argTypes);
+ } catch(NoSuchMethodException e) {
+ throw new UnknownClientCommandException(cmd);
+ }
+ Object[] args = {cmd};
+ try {
+ m.invoke(this, args);
+ } catch (InvocationTargetException e) {
+ if (e.getTargetException() instanceof PropagatedException) {
+ PropagatedException pe =
(PropagatedException)e.getTargetException();
+ pe.setCmd(cmd[0]);
+ throw pe;
+ }
+ log.warn(e.getTargetException());
+ throw new InternalCommandException(cmd[0], e);
+ } catch (Throwable t) {
+ throw new InternalCommandException(cmd[0], t);
+ }
+ }
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandReflect.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -24,95 +24,69 @@
static Timer timer = new Timer(true);
- TimerTask pingTimer = null;
-
Socket sock;
NonblockingOutputStream nws;
PrintWriter writer;
BufferedReader reader;
Thread readThread;
- UserCommandContext context = new InitContext();
- UserEntity e = null;
+ UserCommandHandler context;
+ UserEntity entity = null;
- String lastPing = "";
- String lastPong = "";
+ String livePing = null;
+ TimerTask handshakeAbort = null;
+ TimerTask pingTimer = null;
+ TimerTask pongTimer = null;
- /**
- * 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;
+ Integer pingLock = new Integer(0);
+
+ protected void doPing() {
+ synchronized (pingLock) {
+ if (pingTimer != null) {
+ pingTimer.cancel();
+ pingTimer = null;
}
- pin = nextEsc + 2;
+ if (pongTimer != null) {
+ pongTimer.cancel();
+ pongTimer = null;
+ }
+ String[] line = { "PING", livePing = "" +
System.currentTimeMillis() };
+ sendLine(line);
+ pongTimer = new TimerTask() {
+ public void run() {
+ cutConnection("ping", null);
+ }
+ };
+ synchronized (timer) {
+ timer.schedule(pongTimer,
+ Integer.getInteger("haver.PingTimeout").intValue() * 1000);
+ }
}
- 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]);
+ protected void ackPong(String pong) {
+ synchronized (pingLock) {
+ if (!pong.equals(livePing)) return;
+ if (pongTimer != null) pongTimer.cancel();
+ pongTimer = null;
+ schedulePing();
}
- 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]));
+ protected void schedulePing() {
+ synchronized (pingLock) {
+ if (pingTimer != null) pingTimer.cancel();
+ if (pongTimer != null) pongTimer.cancel();
+ pongTimer = null;
+ pingTimer = new TimerTask() {
+ public void run() {
+ doPing();
+ }
+ };
+ synchronized (timer) {
+ timer.schedule(pingTimer,
+ Integer.getInteger("haver.PingInterval").intValue() *
1000);
+ }
}
- out.append("\r\n");
- return out.toString();
}
public final static String join(String joinBy, String[] parts) {
@@ -128,6 +102,13 @@
/** Creates a new instance of UserConnection */
public UserConnection(Socket s) throws IOException {
+ try {
+ context = UserContextFactory.constructState(this, "init");
+ } catch (Throwable t) {
+ log.error("When initializing client context", t);
+ s.close();
+ return;
+ }
sock = s;
nws = new NonblockingOutputStream(new
BufferedOutputStream(s.getOutputStream()));
nws.setAutoFlush(true);
@@ -142,22 +123,18 @@
readThread.setName(Misc.prettySocket(s));
readThread.start();
- pingTimer = new TimerTask() {
+ handshakeAbort = new TimerTask() {
public void run() {
- if (!(context instanceof NormalContext)){
- // XXX
- ioExcept(new IOException("Took too long to handshake"));
+ synchronized (pingLock) {
+ if (entity == null)
+ cutConnection(); // Took too long to handshake
}
- if (lastPing.equals(lastPong)) {
- lastPing = "" + System.currentTimeMillis();
- String[] ping = {"PING", lastPing};
- sendLine(ping);
- } else {
- cutConnection("ping", "Ping timeout: 30 secs");
- }
}
};
- timer.schedule(pingTimer, 120 * 1000, 30 * 1000);
+ synchronized (timer) {
+ timer.schedule(handshakeAbort,
+ Integer.getInteger("haver.HandshakeTimeout").intValue() *
1000);
+ }
}
public static final String[] greeting = {"HAVER", Misc.version};
@@ -187,14 +164,20 @@
}
protected synchronized void cutConnection() {
- 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;
- pingTimer.cancel();
+ 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();
+ if (pongTimer != null) pongTimer.cancel();
+ if (handshakeAbort != null) handshakeAbort.cancel();
+ }
}
protected synchronized void cutConnection(String reason, String detail) {
@@ -204,9 +187,9 @@
if (detail != null)
sayonara[2] = detail;
sendLine(sayonara);
- if (this.e != null)
- this.e.quit(reason, detail);
- e = null;
+ if (this.entity != null)
+ this.entity.quit(reason, detail);
+ entity = null;
cutConnection();
}
@@ -215,255 +198,19 @@
cutConnection("error", e.getMessage());
}
- public synchronized void sendLine(String[] args) {
- if (writer == null) return;
- String line = encodeLine(args);
- log.debug("S: " + line);
- writer.print(line);
- writer.flush();
+ public void sendLine(String[] args) {
+ String line = Misc.encodeLine(args);
+ synchronized (writer) {
+ if (writer == null) return;
+ log.debug("S: " + line);
+ writer.print(line);
+ writer.flush();
+ }
}
public synchronized void processLine(String line) throws
PropagatedException {
- String[] cmd = decodeLine(line);
+ String[] cmd = Misc.decodeLine(line);
context.processCommand(cmd);
}
-
- class UserEntity implements User {
- String name;
- HashSet channels = new HashSet();
-
- UserEntity(String name) throws PropagatedException {
- this.name = name.intern();
- join(Lobby.theLobby);
- }
-
- public void notifyPart(String channel, Entity what) {
- String[] msg = {"PART", channel, what.getName()};
- sendLine(msg);
- }
- public void notifyJoin(String channel, Entity what) {
- String[] msg = {"JOIN", channel, what.getName()};
- sendLine(msg);
- }
-
- public void notifyPublicMessage(String channel, String from, String[]
args) {
- String[] msg = new String[args.length + 3];
- msg[0] = "IN";
- msg[1] = channel;
- msg[2] = from;
- System.arraycopy(args, 0, msg, 3, args.length);
- sendLine(msg);
- }
-
- public final String getNamespace() {
- return "user";
- }
-
- public String getName() {
- return name;
- }
-
- public void sendPrivateMessage(String from, String[] args) {
- String[] msg = new String[args.length + 2];
- msg[0] = "FROM";
- msg[1] = from;
- System.arraycopy(args, 0, msg, 2, args.length);
- sendLine(msg);
- }
-
- public void notifyQuit(String who, String type, String detail) {
- if (detail != null) {
- String[] msg = { "QUIT", who, type, detail };
- sendLine(msg);
- } else {
- String[] msg = { "QUIT", who, type };
- 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) {
- Iterator i = channels.iterator();
- // XXX
- HashSet interested_parties = new HashSet();
- while (i.hasNext()) {
- Channel c = (Channel)i.next();
- c.unregister(this);
- // XXX: use set
- User[] quit_notice = c.quitListeners();
- for (int j = 0; j < quit_notice.length; j++)
- interested_parties.add(quit_notice[j]);
- }
- i = interested_parties.iterator();
- while (i.hasNext()) {
- User u = (User)i.next();
- u.notifyQuit(name, why, detail);
- }
- }
-
- public synchronized void join(Channel channel) throws
PropagatedException {
- if (channels.contains(channel)) throw new
AlreadyThereJoin(channel.getName());
- channel.register(this);
- channel.distributeJoin(this);
- channels.add(channel);
- }
-
- 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);
- }
- }
-
- public interface UserCommandContext {
- public void processCommand(String[] cmd) throws PropagatedException;
- }
-
- public abstract class UserCommandReflect implements UserCommandContext {
- public void processCommand(String[] cmd) throws PropagatedException {
- if (!cmd[0].toUpperCase().equals(cmd[0])) throw new
UnknownClientCommandException(cmd);
- Class myClass = getClass();
- Class[] argTypes = {cmd.getClass()};
- Method m;
- try {
- m = myClass.getMethod("handle_" + cmd[0], argTypes);
- } catch(NoSuchMethodException e) {
- throw new UnknownClientCommandException(cmd);
- }
- Object[] args = {cmd};
- try {
- m.invoke(this, args);
- } catch (InvocationTargetException e) {
- if (e.getTargetException() instanceof PropagatedException) {
- PropagatedException pe =
(PropagatedException)e.getTargetException();
- pe.setCmd(cmd[0]);
- throw pe;
- }
- log.warn(e.getTargetException());
- throw new InternalCommandException(cmd[0], e);
- } catch (Throwable t) {
- throw new InternalCommandException(cmd[0], t);
- }
- }
- }
-
- public class InitContext extends UserCommandReflect {
- public void handle_HAVER(String[] args) {
- log.info("Client identifies itself as " + args[1]);
- sendLine(greeting);
- context = new LoginContext();
- }
-
- public void processCommand(String[] cmd) {
- try {
- super.processCommand(cmd);
- } catch (PropagatedException e) {
- cutConnection();
- }
- }
- }
-
- public class LoginContext extends UserCommandReflect {
- public void handle_IDENT(String[] args) throws PropagatedException {
- if (Lobby.theLobby.contains("user", args[1]))
- throw new UserAlreadyExists(args[1]);
- if (!Misc.checkName(args[1]))
- throw new BadNameException(args[1]);
- log.info("User logged in: " + args[1]);
- String[] msg = {"HELLO", args[1]};
- sendLine(msg);
- e = new UserEntity(args[1]);
- context = new NormalContext();
- readThread.setName("User " + args[1]);
- }
- }
-
- public class NormalContext extends UserCommandReflect {
- public void handle_TO(String[] args) throws PropagatedException {
- String who = args[1];
- User them = (User)Lobby.theLobby.lookup("user", who);
- if (them == null)
- throw new UserNotFound(who);
- String margs[] = new String[args.length - 2];
- if (margs.length == 0)
- throw new MissingMessageType();
- System.arraycopy(args, 2, margs, 0, margs.length);
- them.sendPrivateMessage(e.getName(), margs);
- }
-
- public void handle_LIST(String[] args) throws PropagatedException {
- String channel = args[1];
- String filter = args[2];
- Channel theChannel = (Channel)Lobby.theLobby.lookup("channel",
channel);
- if (theChannel == null)
- throw new ChannelNotFound(channel);
- String[] members = theChannel.getNames(filter);
- String[] response = new String[members.length + 3];
- System.arraycopy(args, 0, response, 0, 3);
- System.arraycopy(members, 0, response, 3, members.length);
- sendLine(response);
- }
-
- public void handle_JOIN(String[] args) throws PropagatedException {
- String channel = args[1];
- Channel chan_e = (Channel)Lobby.theLobby.lookup("channel",
channel);
- // Special case!
- if (chan_e == Lobby.theLobby)
- throw new Forbidden("&lobby");
- e.join(chan_e);
- }
-
- public void handle_PART(String[] args) throws PropagatedException {
- String channel = args[1];
- Channel chan_e = (Channel)Lobby.theLobby.lookup("channel",
channel);
- // Special case!
- if (chan_e == Lobby.theLobby)
- throw new Forbidden("&lobby");
- e.part(chan_e);
- }
-
- public void handle_IN(String[] args) throws PropagatedException {
- String channel = args[1]; // TODO: check presence
- Channel chan_e = (Channel)Lobby.theLobby.lookup("channel",
channel);
- if (chan_e == null)
- throw new ChannelNotFound(channel);
- String[] margs = new String[args.length - 2];
- if (margs.length == 0)
- throw new MissingMessageType();
- System.arraycopy(args, 2, margs, 0, margs.length);
- chan_e.distributePublicMessage(e, margs);
- }
-
- public void handle_POKE(String[] args) {
- args[0] = "OUCH";
- sendLine(args);
- }
-
- public void handle_PONG(String[] args) {
- lastPong = args[1];
- }
-
- public void handle_BYE(String[] args) {
- String detail = args.length > 1 ? args[1] : null;
- cutConnection("active", detail);
- }
-
- }
}
Added:
trunk/clients/Javer2/src/org/haverdev/haver/server/UserContextFactory.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserContextFactory.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserContextFactory.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,38 @@
+/*
+ * UserContextFactory.java
+ *
+ * Created on May 24, 2005, 6:54 PM
+ */
+
+package org.haverdev.haver.server;
+import java.lang.reflect.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public final class UserContextFactory {
+
+ public static UserCommandHandler constructState(UserConnection conn,
String stateName) throws Exception {
+ MergingContext ctx = new MergingContext();
+ String subcontexts = System.getProperty("haver.state." + stateName);
+ if (subcontexts == null)
+ throw new IllegalArgumentException("Subhandler " + stateName + "
not configured");
+ String[] ctx_arr = subcontexts.split("[, ]+");
+ for (int i = 0; i < ctx_arr.length; i++)
+ ctx.add(constructSubhandler(conn, ctx_arr[i]));
+ return ctx;
+ }
+
+ public static UserCommandHandler constructSubhandler(UserConnection conn,
String name) throws Exception {
+ String classname = System.getProperty(name + ".class");
+ ClassLoader c = ClassLoader.getSystemClassLoader();
+ Class clas = c.loadClass(classname);
+
+ Class[] proto = {conn.getClass(), name.getClass()};
+ Object[] args = {conn, name};
+ Constructor cons = clas.getConstructor(proto);
+ Object ret = cons.newInstance(args);
+ return (UserCommandHandler)ret;
+ }
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/haver/server/UserContextFactory.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/Javer2/src/org/haverdev/haver/server/UserEntity.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserEntity.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserEntity.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,119 @@
+/*
+ * UserEntity.java
+ *
+ * Created on May 24, 2005, 7:42 PM
+ */
+
+package org.haverdev.haver.server;
+import org.haverdev.haver.server.exceptions.*;
+import java.util.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+ class UserEntity implements User {
+ String name;
+ HashSet channels = new HashSet();
+ UserConnection conn;
+
+ UserEntity(UserConnection conn, String name) throws PropagatedException {
+ this.name = name.intern();
+ this.conn = conn;
+ join(Lobby.theLobby);
+ }
+
+ public void notifyPart(String channel, Entity what) {
+ String[] msg = {"PART", channel, what.getName()};
+ conn.sendLine(msg);
+ }
+
+ public void notifyJoin(String channel, Entity what) {
+ String[] msg = {"JOIN", channel, what.getName()};
+ conn.sendLine(msg);
+ }
+
+ public void notifyPublicMessage(String channel, String from, String[]
args) {
+ String[] msg = new String[args.length + 3];
+ msg[0] = "IN";
+ msg[1] = channel;
+ msg[2] = from;
+ System.arraycopy(args, 0, msg, 3, args.length);
+ conn.sendLine(msg);
+ }
+
+ public final String getNamespace() {
+ return "user";
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void sendPrivateMessage(String from, String[] args) {
+ String[] msg = new String[args.length + 2];
+ msg[0] = "FROM";
+ msg[1] = from;
+ System.arraycopy(args, 0, msg, 2, args.length);
+ conn.sendLine(msg);
+ }
+
+ public void notifyQuit(String who, String type, String detail) {
+ if (detail != null) {
+ String[] msg = { "QUIT", who, type, detail };
+ conn.sendLine(msg);
+ } else {
+ String[] msg = { "QUIT", who, 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) {
+ Iterator i = channels.iterator();
+ // XXX
+ HashSet interested_parties = new HashSet();
+ while (i.hasNext()) {
+ Channel c = (Channel)i.next();
+ c.unregister(this);
+ // XXX: use set
+ User[] quit_notice = c.quitListeners();
+ for (int j = 0; j < quit_notice.length; j++)
+ interested_parties.add(quit_notice[j]);
+ }
+ i = interested_parties.iterator();
+ while (i.hasNext()) {
+ User u = (User)i.next();
+ u.notifyQuit(name, why, detail);
+ }
+ }
+
+ public synchronized void join(Channel channel) throws PropagatedException
{
+ if (channels.contains(channel)) throw new
AlreadyThereJoin(channel.getName());
+ channel.register(this);
+ channel.distributeJoin(this);
+ channels.add(channel);
+ }
+
+ 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);
+ }
+ }
\ No newline at end of file
Property changes on:
trunk/clients/Javer2/src/org/haverdev/haver/server/UserEntity.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/clients/Javer2/src/org/haverdev/javer2/CMod.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/CMod.java 2005-05-24
21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/CMod.java 2005-05-25
02:59:42 UTC (rev 731)
@@ -46,7 +46,8 @@
}
public static void main(String[] args) throws Throwable {
- new CMod("localhost", 15678, "cmod", "test");
+ for (int i = 0; i < 300; i++)
+ new CMod("localhost", 7070, "cmod-" + i, "lobby");
}
static final int STATE_IDLE = 0;
Added: trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.form
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.form
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.form
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.0" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+ <SubComponents>
+ <Container class="javax.swing.JSplitPane" name="jSplitPane1">
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="Center"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
+ <SubComponents>
+ <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"
value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
+ <JSplitPaneConstraints position="left"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+ <SubComponents>
+ <Component class="javax.swing.JTextArea" name="jTextArea1">
+ <Properties>
+ <Property name="editable" type="boolean" value="false"/>
+ <Property name="lineWrap" type="boolean" value="true"/>
+ <Property name="wrapStyleWord" type="boolean" value="true"/>
+ </Properties>
+ </Component>
+ </SubComponents>
+ </Container>
+ <Container class="javax.swing.JScrollPane" name="jScrollPane2">
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"
value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
+ <JSplitPaneConstraints position="right"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+ <SubComponents>
+ <Component class="javax.swing.JList" name="userList">
+ </Component>
+ </SubComponents>
+ </Container>
+ </SubComponents>
+ </Container>
+ </SubComponents>
+</Form>
Added: trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,157 @@
+/*
+ * ChannelPane.java
+ *
+ * Created on May 24, 2005, 9:31 PM
+ */
+
+package org.haverdev.javer2;
+import org.haverdev.haver.*;
+import java.util.*;
+import javax.swing.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class ChannelPane extends javax.swing.JPanel implements Pane {
+
+ Client client;
+ String channel;
+ Listener l = new Listener();
+ TreeSet users = new TreeSet();
+
+ class Listener extends Callback {
+ // TODO: part self
+
+ public void onQuit(Client source, String who, String type, String
detail) throws Throwable {
+ synchronized (users) {
+ if (users.contains(who)) {
+ users.remove(who);
+ putLine("--- " + who + " has left the channel: " + type +
" " + detail);
+ refreshList();
+ }
+ }
+ }
+
+ public void onPart(Client source, String chan, String who) throws
Throwable {
+ if (!channel.equals(chan))
+ return;
+ synchronized (users) {
+ users.remove(who);
+ }
+ putLine("--- " + who + " has left the channel.");
+ refreshList();
+ }
+
+ public void onJoin(Client source, String chan, String who) throws
Throwable {
+ if (!channel.equals(chan))
+ return;
+ synchronized (users) {
+ users.add(who);
+ }
+ putLine("--- " + who + " has joined the channel.");
+ refreshList();
+ }
+
+ public void onReceivedList(Client source, String chan, String
namespace, String[] list) throws Throwable {
+ if (!channel.equals(chan))
+ return;
+ synchronized (users) {
+ TreeSet nu = new TreeSet();
+ for (int i = 0; i < list.length; i++)
+ nu.add(list[i]);
+ users = nu;
+ }
+ refreshList();
+ }
+
+ public void onPublicMessage(Client source, String chan, String from,
String type, String[] args) throws Throwable {
+ if (!channel.equals(chan))
+ return;
+ if (type.equals("say"))
+ putLine("<" + from + "> " + args[0]);
+ else if (type.equals("act"))
+ putLine("* " + from + " " + args[0]);
+ }
+ }
+
+ /** Creates new form ChannelPane */
+ public ChannelPane(Client cli, String channel) {
+ initComponents();
+ client = cli;
+ this.channel = channel;
+ client.addNotify(l);
+ client.sendJoin(channel);
+ client.requestList(channel, "user");
+ }
+
+ public void speak(String line) {
+ client.sendPublicMessage(channel, "say", line);
+ }
+
+ public void putLine(final String line) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ String txt = jTextArea1.getText();
+ jTextArea1.setText(txt + "\n" + line);
+ }
+ });
+ }
+
+ public void act(String line) {
+ client.sendPublicMessage(channel, "act", line);
+ }
+
+ public String getCaption() {
+ return "Channel " + channel;
+ }
+
+ public void refreshList() {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ synchronized (users) {
+ userList.setListData(users.toArray());
+ }
+ }
+ });
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ private void initComponents() {//GEN-BEGIN:initComponents
+ jSplitPane1 = new javax.swing.JSplitPane();
+ jScrollPane1 = new javax.swing.JScrollPane();
+ jTextArea1 = new javax.swing.JTextArea();
+ jScrollPane2 = new javax.swing.JScrollPane();
+ userList = new javax.swing.JList();
+
+ setLayout(new java.awt.BorderLayout());
+
+ jTextArea1.setEditable(false);
+ jTextArea1.setLineWrap(true);
+ jTextArea1.setWrapStyleWord(true);
+ jScrollPane1.setViewportView(jTextArea1);
+
+ jSplitPane1.setLeftComponent(jScrollPane1);
+
+ jScrollPane2.setViewportView(userList);
+
+ jSplitPane1.setRightComponent(jScrollPane2);
+
+ add(jSplitPane1, java.awt.BorderLayout.CENTER);
+
+ }//GEN-END:initComponents
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JScrollPane jScrollPane2;
+ private javax.swing.JSplitPane jSplitPane1;
+ private javax.swing.JTextArea jTextArea1;
+ private javax.swing.JList userList;
+ // End of variables declaration//GEN-END:variables
+
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.form
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.form 2005-05-24
21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.form 2005-05-25
02:59:42 UTC (rev 731)
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.0" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+ <SubComponents>
+ <Container class="javax.swing.JTabbedPane" name="jTabbedPane1">
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="Center"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
+ </Container>
+ <Container class="javax.swing.JPanel" name="jPanel1">
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="South"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+ <SubComponents>
+ <Component class="javax.swing.JTextField" name="inputBox">
+ <Events>
+ <EventHandler event="keyTyped"
listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent"
handler="inputBoxKeyTyped"/>
+ </Events>
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="Center"/>
+ </Constraint>
+ </Constraints>
+ </Component>
+ <Component class="javax.swing.JButton" name="jButton1">
+ <Properties>
+ <Property name="text" type="java.lang.String" value="Send"/>
+ <Property name="actionCommand" type="java.lang.String"
value="Send"/>
+ </Properties>
+ <Events>
+ <EventHandler event="actionPerformed"
listener="java.awt.event.ActionListener"
parameters="java.awt.event.ActionEvent" handler="sendLine"/>
+ </Events>
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="East"/>
+ </Constraint>
+ </Constraints>
+ </Component>
+ </SubComponents>
+ </Container>
+ </SubComponents>
+</Form>
Added: trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.java 2005-05-24
21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.java 2005-05-25
02:59:42 UTC (rev 731)
@@ -0,0 +1,258 @@
+/*
+ * JaverForm.java
+ *
+ * Created on May 24, 2005, 8:09 PM
+ */
+
+package org.haverdev.javer2;
+import javax.swing.*;
+import java.util.*;
+import org.haverdev.haver.*;
+import java.lang.reflect.*;
+import java.io.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class JaverForm extends javax.swing.JPanel {
+
+ Thread connectThread = null;
+ Client cli = null;
+ Watcher watch = null;
+
+ class Watcher extends Callback {
+ public void onPrivateMessage(Client source, final String from, final
String type, final String[] args) throws Throwable {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ QueryPane q = findPrivateQuery(from);
+ q.onIncomingMessage(type, args[0]);
+ }
+ });
+ }
+
+ }
+
+ void doConnect(String nick) {
+ cli = new Client();
+ watch = new Watcher();
+ cli.addNotify(watch);
+ try {
+ cli.syncConnect("localhost", 7070, nick);
+ serverpane.putLine("Connected!");
+ } catch (final Throwable t) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ connectThread = null;
+ cli = null;
+ watch = null;
+ serverpane.putLine("Connection failed: " + t.toString());
+ }
+ });
+ }
+ }
+
+ public final static void main(String[] args) {
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ JFrame f = new JFrame("test");
+ JaverForm form = new JaverForm();
+ f.getContentPane().add(form);
+ f.pack();
+ f.setVisible(true);
+ f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ }
+ });
+ }
+
+ ServerPane serverpane;
+
+ /** Creates new form JaverForm */
+ public JaverForm() {
+ initComponents();
+ serverpane = new ServerPane();
+ addPane(serverpane);
+ serverpane.putLine("Welcome to haver!");
+ }
+
+ HashMap panes = new HashMap();
+
+ void addPane(Object c) {
+ int paneCount = panes.size();
+ jTabbedPane1.addTab(((Pane)c).getCaption(), (JComponent)c);
+ panes.put(c, new Integer(paneCount));
+ }
+
+ void removePane(JComponent c) {
+ Integer paneid_o = (Integer)panes.get(c);
+ if (paneid_o == null)
+ return;
+ int paneid = paneid_o.intValue();
+ panes.remove(c);
+ jTabbedPane1.remove(c);
+ Iterator i = panes.keySet().iterator();
+ while (i.hasNext()) {
+ Object o = i.next();
+ Integer v = (Integer)panes.get(o);
+ if (v.intValue() > paneid)
+ panes.put(o, new Integer(v.intValue() - 1));
+ }
+ }
+
+ Pane currentPane() {
+ return (Pane)jTabbedPane1.getSelectedComponent();
+ }
+
+ HashMap channelQueries = new HashMap();
+
+ Pane findChannelPane(String channel) {
+ channel = channel.toLowerCase();
+ if (channelQueries.containsKey(channel))
+ return (Pane)channelQueries.get(channel);
+ Pane chan = new ChannelPane(cli, channel);
+ addPane(chan);
+ channelQueries.put(channel, chan);
+ return chan;
+ }
+
+ HashMap privateQueries = new HashMap();
+
+ QueryPane findPrivateQuery(String name) {
+ name = name.toLowerCase();
+ if (privateQueries.containsKey(name))
+ return (QueryPane)privateQueries.get(name);
+ QueryPane p = new QueryPane(cli, name);
+ addPane(p);
+ privateQueries.put(name, p);
+ return p;
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ private void initComponents() {//GEN-BEGIN:initComponents
+ jTabbedPane1 = new javax.swing.JTabbedPane();
+ jPanel1 = new javax.swing.JPanel();
+ inputBox = new javax.swing.JTextField();
+ jButton1 = new javax.swing.JButton();
+
+ setLayout(new java.awt.BorderLayout());
+
+ add(jTabbedPane1, java.awt.BorderLayout.CENTER);
+
+ jPanel1.setLayout(new java.awt.BorderLayout());
+
+ inputBox.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyTyped(java.awt.event.KeyEvent evt) {
+ inputBoxKeyTyped(evt);
+ }
+ });
+
+ jPanel1.add(inputBox, java.awt.BorderLayout.CENTER);
+
+ jButton1.setText("Send");
+ jButton1.setActionCommand("Send");
+ jButton1.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ sendLine(evt);
+ }
+ });
+
+ jPanel1.add(jButton1, java.awt.BorderLayout.EAST);
+
+ add(jPanel1, java.awt.BorderLayout.SOUTH);
+
+ }//GEN-END:initComponents
+
+ private void inputBoxKeyTyped(java.awt.event.KeyEvent evt)
{//GEN-FIRST:event_inputBoxKeyTyped
+ if (evt.getKeyChar() == '\n')
+ sendLine(null);
+ }//GEN-LAST:event_inputBoxKeyTyped
+
+ private void sendLine(java.awt.event.ActionEvent evt)
{//GEN-FIRST:event_sendLine
+ if (connectThread != null) {
+ serverpane.putLine("Still connecting, please wait...");
+ return;
+ }
+ String text = inputBox.getText();
+ inputBox.setText("");
+ if (cli == null) {
+ final String nick = text;
+ serverpane.putLine("Trying to connect with nick " + nick);
+ new Thread(new Runnable() {
+ public void run() {
+ doConnect(nick);
+ }
+ }).start();
+ return;
+ }
+
+ if (text.charAt(0) == '/') {
+ if (text.charAt(1) == ' ') {
+ text = text.substring(2);
+ } else {
+ String cmd, arg;
+ int split = text.indexOf(' ');
+ if (split == -1) {
+ cmd = text.substring(1);
+ arg = "";
+ } else {
+ cmd = text.substring(1, split);
+ arg = text.substring(split + 1);
+ }
+ // XXX: is this ok in applets?
+
+ Class[] proto = {text.getClass()};
+ Object[] args = {arg};
+ try {
+ Class cls = getClass();
+ Method m = cls.getDeclaredMethod("slash_" +
cmd.toUpperCase(), proto);
+ m.invoke(this, args);
+ } catch (Throwable t) {
+ ((Pane)currentPane()).putLine("Error: " + t.toString());
+ }
+ return;
+ }
+ }
+ Pane current = (Pane)currentPane();
+ current.speak(text);
+ }//GEN-LAST:event_sendLine
+
+ void putLine(String line) {
+ ((Pane)currentPane()).putLine(line);
+ }
+
+ void slash_XYZZY(String arg) {
+ ((Pane)currentPane()).putLine("Nothing happens.");
+ }
+
+ void slash_MSG(String arg) throws IOException {
+ int split = arg.indexOf(' ');
+ if (split == -1) {
+ putLine("Usage: /msg <user> <message>");
+ return;
+ }
+ String to = arg.substring(0, split);
+ String msg = arg.substring(split + 1);
+
+ findPrivateQuery(to).speak(msg);
+ }
+
+ void slash_JOIN(String arg) throws IOException {
+ findChannelPane(arg);
+ }
+
+ void slash_ME(String arg) {
+ currentPane().act(arg);
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JTextField inputBox;
+ private javax.swing.JButton jButton1;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JTabbedPane jTabbedPane1;
+ // End of variables declaration//GEN-END:variables
+
+}
Property changes on: trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/Javer2/src/org/haverdev/javer2/Pane.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/Pane.java 2005-05-24
21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/Pane.java 2005-05-25
02:59:42 UTC (rev 731)
@@ -0,0 +1,19 @@
+/*
+ * Pane.java
+ *
+ * Created on May 24, 2005, 8:19 PM
+ */
+
+package org.haverdev.javer2;
+
+/**
+ *
+ * @author bdonlan
+ */
+public interface Pane {
+ public String getCaption();
+ public void putLine(String line);
+ public void speak(String line);
+
+ public void act(String line);
+}
Property changes on: trunk/clients/Javer2/src/org/haverdev/javer2/Pane.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/Javer2/src/org/haverdev/javer2/QueryPane.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/QueryPane.java 2005-05-24
21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/QueryPane.java 2005-05-25
02:59:42 UTC (rev 731)
@@ -0,0 +1,58 @@
+/*
+ * QueryPane.java
+ *
+ * Created on May 24, 2005, 10:11 PM
+ */
+
+package org.haverdev.javer2;
+import org.haverdev.haver.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class QueryPane extends TextPane {
+
+ Client client;
+ String name;
+ Listener listener;
+
+ class Listener extends Callback {
+ public void onQuit(String who, String reason, String detail) {
+ if (who.equals(name))
+ putLine("--- " + who + " quit: " + reason + " " + detail);
+ }
+ }
+
+ /** Creates a new instance of QueryPane */
+ public QueryPane(Client client, String name) {
+ this.client = client;
+ this.name = name;
+ // XXX: this reference never dies. fixit
+ client.addNotify(listener = new Listener());
+ }
+
+ public void onIncomingMessage(String type, String arg) {
+ // This is not in a client listener because we need to hook the first
+ // message in the root frame anyway
+ if (type.equals("say"))
+ putLine("<" + name + "> " + arg);
+ else if (type.equals("act"))
+ putLine("* " + name + " " + arg);
+ }
+
+ public void speak(String line) {
+ putLine("<" + client.getName() + "> " + line);
+ client.sendPrivateMessage(name, "say", line);
+ }
+
+ public void act(String line) {
+ putLine("* " + client.getName() + " " + line);
+ client.sendPrivateMessage(name, "act", line);
+ }
+
+ public String getCaption() {
+ return "Private query: " + name;
+ }
+
+}
Property changes on: trunk/clients/Javer2/src/org/haverdev/javer2/QueryPane.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/Javer2/src/org/haverdev/javer2/ServerPane.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/ServerPane.java
2005-05-24 21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/ServerPane.java
2005-05-25 02:59:42 UTC (rev 731)
@@ -0,0 +1,30 @@
+/*
+ * ServerPane.java
+ *
+ * Created on May 24, 2005, 8:21 PM
+ */
+
+package org.haverdev.javer2;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class ServerPane extends TextPane {
+
+ /** Creates a new instance of ServerPane */
+ public ServerPane() {
+ }
+
+ public void speak(String line) {
+ putLine("Error: Can't type to this window");
+ }
+
+ public void act(String line) {
+ putLine("Error: Can't act in this window");
+ }
+
+ public String getCaption() {
+ return "Server";
+ }
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/javer2/ServerPane.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/Javer2/src/org/haverdev/javer2/TextPane.form
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/TextPane.form 2005-05-24
21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/TextPane.form 2005-05-25
02:59:42 UTC (rev 731)
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.0" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+ <SubComponents>
+ <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+ <Properties>
+ <Property name="autoscrolls" type="boolean" value="true"/>
+ </Properties>
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="Center"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+ <SubComponents>
+ <Component class="javax.swing.JTextArea" name="textPane">
+ <Properties>
+ <Property name="editable" type="boolean" value="false"/>
+ <Property name="lineWrap" type="boolean" value="true"/>
+ <Property name="wrapStyleWord" type="boolean" value="true"/>
+ </Properties>
+ <AuxValues>
+ <AuxValue name="JavaCodeGenerator_VariableModifier"
type="java.lang.Integer" value="4"/>
+ </AuxValues>
+ </Component>
+ </SubComponents>
+ </Container>
+ </SubComponents>
+</Form>
Added: trunk/clients/Javer2/src/org/haverdev/javer2/TextPane.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/TextPane.java 2005-05-24
21:42:18 UTC (rev 730)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/TextPane.java 2005-05-25
02:59:42 UTC (rev 731)
@@ -0,0 +1,58 @@
+/*
+ * TextPane.java
+ *
+ * Created on May 24, 2005, 8:14 PM
+ */
+
+package org.haverdev.javer2;
+
+/**
+ *
+ * @author bdonlan
+ */
+public abstract class TextPane extends javax.swing.JPanel implements Pane {
+
+ /** Creates new form TextPane */
+ public TextPane() {
+ initComponents();
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ private void initComponents() {//GEN-BEGIN:initComponents
+ jScrollPane1 = new javax.swing.JScrollPane();
+ textPane = new javax.swing.JTextArea();
+
+ setLayout(new java.awt.BorderLayout());
+
+ jScrollPane1.setAutoscrolls(true);
+ textPane.setEditable(false);
+ textPane.setLineWrap(true);
+ textPane.setWrapStyleWord(true);
+ jScrollPane1.setViewportView(textPane);
+
+ add(jScrollPane1, java.awt.BorderLayout.CENTER);
+
+ }//GEN-END:initComponents
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JScrollPane jScrollPane1;
+ protected javax.swing.JTextArea textPane;
+ // End of variables declaration//GEN-END:variables
+
+ public synchronized void putLine(final String line) {
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ String text = textPane.getText();
+ String newtext = text + "\n" + line;
+ textPane.setText(newtext);
+ }
+ });
+ }
+
+
+}
Property changes on: trunk/clients/Javer2/src/org/haverdev/javer2/TextPane.java
___________________________________________________________________
Name: svn:eol-style
+ native