Added a simple session manager for responders and used it in the bsh sample.
[jsvc.git] / src / dolda / jsvc / util / PerSession.java
diff --git a/src/dolda/jsvc/util/PerSession.java b/src/dolda/jsvc/util/PerSession.java
new file mode 100644 (file)
index 0000000..7973e0a
--- /dev/null
@@ -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);
+    }
+}