From d5dd6a2dada08df30133b739d0ce1fa8f2a0d2e9 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Mon, 26 Oct 2009 16:56:15 +0100 Subject: [PATCH] Added basic session support. --- samples/bsh/build.xml | 2 +- src/dolda/jsvc/util/Cookie.java | 12 ++++ src/dolda/jsvc/util/Session.java | 130 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 src/dolda/jsvc/util/Session.java diff --git a/samples/bsh/build.xml b/samples/bsh/build.xml index fd6d4df..19384b3 100644 --- a/samples/bsh/build.xml +++ b/samples/bsh/build.xml @@ -24,7 +24,7 @@ - + diff --git a/src/dolda/jsvc/util/Cookie.java b/src/dolda/jsvc/util/Cookie.java index 8783427..591289d 100644 --- a/src/dolda/jsvc/util/Cookie.java +++ b/src/dolda/jsvc/util/Cookie.java @@ -6,6 +6,7 @@ import java.text.*; import java.io.*; public class Cookie { + private final static Map> cache = new WeakHashMap>(); public final static DateFormat datefmt; static { datefmt = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z", Locale.ENGLISH); @@ -88,6 +89,17 @@ public class Cookie { return(ret); } + public static MultiMap get(Request req) { + synchronized(cache) { + MultiMap ret = cache.get(req); + if(ret == null) { + ret = parse(req); + cache.put(req, ret); + } + return(ret); + } + } + public String toString() { StringBuilder buf = new StringBuilder(); buf.append("Cookie("); diff --git a/src/dolda/jsvc/util/Session.java b/src/dolda/jsvc/util/Session.java new file mode 100644 index 0000000..31b65a7 --- /dev/null +++ b/src/dolda/jsvc/util/Session.java @@ -0,0 +1,130 @@ +package dolda.jsvc.util; + +import dolda.jsvc.*; +import java.util.*; +import java.security.SecureRandom; + +public class Session implements java.io.Serializable { + private static final Map sessions = new HashMap(); + private static final SecureRandom prng; + private static long lastclean = 0; + private final Map props = new HashMap(); + private long ctime = System.currentTimeMillis(), atime = ctime, etime = 86400 * 1000; + private Collection ll = new HashSet(); + + static { + try { + prng = SecureRandom.getInstance("SHA1PRNG"); + } catch(java.security.NoSuchAlgorithmException e) { + throw(new Error(e)); + } + } + + public static interface Listener { + public void expire(Session sess); + } + + public void listen(Listener l) { + synchronized(ll) { + ll.add(l); + } + } + + public Object get(Object key, Object def) { + synchronized(props) { + if(props.containsKey(key)) + return(props.get(key)); + else + return(def); + } + } + + public Object put(Object key, Object val) { + synchronized(props) { + return(props.put(key, val)); + } + } + + private void expire() { + synchronized(ll) { + for(Listener l : ll) + l.expire(this); + } + } + + public static int num() { + synchronized(sessions) { + return(sessions.size()); + } + } + + private static String newid() { + byte[] rawid = new byte[16]; + prng.nextBytes(rawid); + StringBuilder buf = new StringBuilder(); + for(byte b : rawid) { + buf.append(Misc.int2hex((b & 0xf0) >> 4, false)); + buf.append(Misc.int2hex(b & 0x0f, false)); + } + return(buf.toString()); + } + + private static Session create(Request req) { + Session sess = new Session(); + long etime = 0; + int ct; + ct = Integer.parseInt(req.ctx().libconfig("jsvc.session.expire", "0")); + if(ct > 0) + sess.etime = ct; + ct = Integer.parseInt(req.ctx().sysconfig("jsvc.session.expire", "0")); + if(ct > 0) + sess.etime = ct; + return(sess); + } + + private static void clean() { + long now = System.currentTimeMillis(); + synchronized(sessions) { + for(Iterator i = sessions.values().iterator(); i.hasNext();) { + Session sess = i.next(); + if(now > sess.atime + sess.etime) { + i.remove(); + sess.expire(); + } + } + } + } + + public static Session get(Request req) { + long now = System.currentTimeMillis(); + if(now - lastclean > 3600 * 1000) { + clean(); + lastclean = now; + } + + MultiMap cookies = Cookie.get(req); + Cookie sc = cookies.get("jsvc-session"); + Session sess = null; + synchronized(sessions) { + if(sc != null) + sess = sessions.get(sc.value); + if(sess == null) { + String id = newid(); + sess = create(req); + sessions.put(id, sess); + sc = new Cookie("jsvc-session", id); + sc.expires = new Date(System.currentTimeMillis() + (86400L * 365L * 1000L)); + sc.path = req.ctx().sysconfig("jsvc.session.path", req.rooturl().getPath()); + String pd = req.ctx().sysconfig("jsvc.session.domain", null); + if(pd != null) + sc.domain = pd; + sc.addto(req); + } + } + return(sess); + } + + public static Session get() { + return(get(RequestThread.request())); + } +} -- 2.11.0