From c04f28ae77d5a372eb4afd0296c12014fdbcf96e Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Mon, 26 Oct 2009 17:32:54 +0100 Subject: [PATCH] Added a simple session manager for responders and used it in the bsh sample. --- samples/bsh/src/dolda/bsvc/Main.java | 2 +- samples/bsh/src/dolda/bsvc/ShellPage.java | 85 +++++++++++++++++++------ src/dolda/jsvc/util/PerSession.java | 100 ++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 20 deletions(-) create mode 100644 src/dolda/jsvc/util/PerSession.java diff --git a/samples/bsh/src/dolda/bsvc/Main.java b/samples/bsh/src/dolda/bsvc/Main.java index a1687af..d6a83d2 100644 --- a/samples/bsh/src/dolda/bsvc/Main.java +++ b/samples/bsh/src/dolda/bsvc/Main.java @@ -6,7 +6,7 @@ import dolda.jsvc.util.*; public class Main { public static Responder responder() { Multiplexer root = new Multiplexer(); - root.file("sh", new ShellPage()); + root.file("sh", new PerSession(ShellPage.class)); root.file("css", new StaticContent(Main.class, "static/base.css", false, "text/css")); return(Misc.stdroot(root)); } diff --git a/samples/bsh/src/dolda/bsvc/ShellPage.java b/samples/bsh/src/dolda/bsvc/ShellPage.java index 29d0d3d..e7412ad 100644 --- a/samples/bsh/src/dolda/bsvc/ShellPage.java +++ b/samples/bsh/src/dolda/bsvc/ShellPage.java @@ -6,6 +6,47 @@ import java.io.*; import bsh.Interpreter; public class ShellPage extends SimpleWriter { + private RConsole cons = new RConsole(); + private Interpreter ip = new Interpreter(cons); + + private static class RConsole implements bsh.ConsoleInterface { + public Console back; + Reader in = new StringReader(""); + + public void error(Object msg) { + if(back != null) + back.error(msg); + } + + public void print(Object msg) { + if(back != null) + back.print(msg); + } + + public void println(Object msg) { + if(back != null) + back.println(msg); + } + + public PrintStream getOut() { + if(back == null) + return(null); + return(back.getOut()); + } + + public PrintStream getErr() { + if(back == null) + return(null); + return(back.getErr()); + } + + public Reader getIn() { + if(back == null) + return(null); + return(in); + } + } + private static class Console implements bsh.ConsoleInterface { ByteArrayOutputStream obuf = new ByteArrayOutputStream(); ByteArrayOutputStream ebuf = new ByteArrayOutputStream(); @@ -61,25 +102,31 @@ public class ShellPage extends SimpleWriter { out.println("

Shell

"); if((req.method() == "POST") && (cmd != null)) { Console cons = new Console(); - Interpreter ip = new Interpreter(cons); - Object resp; - try { - ip.set("req", req); - resp = ip.eval(cmd); - out.println("
");
-		out.println(Misc.htmlq((resp == null)?"(null)":(resp.toString())));
-		out.println("
"); - } catch(bsh.EvalError exc) { - out.println("

Evaluation error

"); - out.println("
");
-		out.print(exc.toString());
-		out.println("
"); - if(exc instanceof bsh.TargetError) { - bsh.TargetError te = (bsh.TargetError)exc; - out.println("

Target error

"); - out.println("
");
-		    te.getTarget().printStackTrace(out);
-		    out.println("
"); + synchronized(ip) { + this.cons.back = cons; + try { + Object resp; + try { + ip.set("req", req); + resp = ip.eval(cmd); + out.println("
");
+			out.println(Misc.htmlq((resp == null)?"(null)":(resp.toString())));
+			out.println("
"); + } catch(bsh.EvalError exc) { + out.println("

Evaluation error

"); + out.println("
");
+			out.print(exc.toString());
+			out.println("
"); + if(exc instanceof bsh.TargetError) { + bsh.TargetError te = (bsh.TargetError)exc; + out.println("

Target error

"); + out.println("
");
+			    te.getTarget().printStackTrace(out);
+			    out.println("
"); + } + } + } finally { + this.cons.back = null; } } String eo = new String(cons.obuf.toByteArray(), Misc.utf8); diff --git a/src/dolda/jsvc/util/PerSession.java b/src/dolda/jsvc/util/PerSession.java new file mode 100644 index 0000000..7973e0a --- /dev/null +++ b/src/dolda/jsvc/util/PerSession.java @@ -0,0 +1,100 @@ +package dolda.jsvc.util; + +import dolda.jsvc.*; +import java.lang.reflect.*; + +public class PerSession implements Responder { + private final Class rcl; + private final Class dcl; + + public PerSession(Class rcl, Class dcl) { + this.rcl = rcl; + this.dcl = dcl; + } + + public PerSession(Class rcl) { + this(rcl, null); + } + + private Object makedata(Session sess) { + try { + try { + return(dcl.getConstructor().newInstance()); + } catch(NoSuchMethodException e) { + } + try { + return(dcl.getConstructor(Session.class).newInstance(sess)); + } catch(NoSuchMethodException e) { + } + } catch(InstantiationException e) { + throw(new RuntimeException(e)); + } catch(IllegalAccessException e) { + throw(new RuntimeException(e)); + } catch(InvocationTargetException e) { + throw(new RuntimeException(e)); + } + throw(new RuntimeException("Found no way to create an instance of " + dcl.getName())); + } + + private Object getdata(Session sess) { + Object d = sess.get(dcl, null); + if(d == null) { + d = makedata(sess); + sess.put(dcl, d); + } + return(d); + } + + private Responder create(Session sess) { + try { + if(dcl != null) { + try { + return((Responder)rcl.getMethod("responder", dcl).invoke(null, getdata(sess))); + } catch(NoSuchMethodException e) { + } + } + try { + return((Responder)rcl.getMethod("responder", Session.class).invoke(null, sess)); + } catch(NoSuchMethodException e) { + } + try { + return((Responder)rcl.getMethod("responder").invoke(null)); + } catch(NoSuchMethodException e) { + } + if(dcl != null) { + try { + return((Responder)rcl.getConstructor(dcl).newInstance(getdata(sess))); + } catch(NoSuchMethodException e) { + } + } + try { + return((Responder)rcl.getConstructor(Session.class).newInstance(sess)); + } catch(NoSuchMethodException e) { + } + try { + return((Responder)rcl.getConstructor().newInstance()); + } catch(NoSuchMethodException e) { + } + } catch(InstantiationException e) { + throw(new RuntimeException(e)); + } catch(IllegalAccessException e) { + throw(new RuntimeException(e)); + } catch(InvocationTargetException e) { + throw(new RuntimeException(e)); + } + throw(new RuntimeException("Found no way to create a responder from the class " + rcl.getName())); + } + + public void respond(Request req) { + Session sess = Session.get(req); + Responder resp; + synchronized(sess) { + resp = (Responder)sess.get(rcl, null); + if(resp == null) { + resp = create(sess); + sess.put(rcl, resp); + } + } + resp.respond(req); + } +} -- 2.11.0