reorganise for new collections
[org.ibex.xt-crawshaw.git] / src / java / ibex / xt / Prevalence.java
diff --git a/src/java/ibex/xt/Prevalence.java b/src/java/ibex/xt/Prevalence.java
new file mode 100644 (file)
index 0000000..ce60a19
--- /dev/null
@@ -0,0 +1,111 @@
+package ibex.xt;
+
+import ibex.js.*;
+import ibex.util.*;
+import java.util.*;
+
+import java.io.*;
+import java.net.*;
+import javax.servlet.ServletContext; // FIXME: remove references
+
+import org.prevayler.*;
+import org.prevayler.implementation.snapshot.*;
+//import com.thoughtworks.xstream.*; // FIXME find
+
+public class Prevalence {
+
+    static final Hashtable prevaylers = new Hashtable();
+
+    public static void destroy(ServletContext cx, Prevayler prevayler) { try {
+        prevaylers.remove(cx);
+        prevayler.takeSnapshot();
+        prevayler.close();
+    } catch (Exception e) { e.printStackTrace(); } }
+
+    private static class SnapshotThread extends Thread {
+        ServletContext cx;
+        public SnapshotThread(ServletContext cx) { this.cx = cx; }
+        public void run() {
+            try {
+                Thread.sleep(10000);
+                Prevayler privatePrevayler = (Prevayler)prevaylers.get(cx);
+                if (privatePrevayler == null) return;
+                privatePrevayler.takeSnapshot();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static Prevayler getPrevayler(ServletContext cx) {
+        try {
+            Prevayler prevayler;
+            synchronized(cx) {
+                prevayler = (Prevayler)prevaylers.get(cx);
+                if (prevayler == null) {
+                    PrevaylerFactory pf = new PrevaylerFactory();
+                    String base = cx.getRealPath("/") + "WEB-INF" + File.separatorChar + "prevalent";
+                    System.err.println("prevayling to " + base);
+                    pf.configurePrevalenceBase(base);
+                    /*
+                    XStreamSnapshotManager manager = new XStreamSnapshotManager(new JS(), base, null) {
+                            protected XStream createXStream() {
+                                XStream xstream = new XStream();
+                                xstream.alias("js", JS.class);
+                                xstream.alias("jsdate", JSDate.class);
+                                return xstream;
+                            }
+                        };
+                    System.err.println("configuring with " + manager);
+                    pf.configureSnapshotManager(manager);
+                    */
+                    pf.configureSnapshotManager(new SnapshotManager(new JS(), base));
+                    //pf.configureClassLoader(JSTransaction.class.getClassLoader());
+                    prevayler = pf.create();
+                    prevaylers.put(cx, prevayler);
+                    new SnapshotThread(cx).start();
+                }
+            }
+            return prevayler;
+        } catch (Exception e) { throw new RuntimeException(e); } }
+
+    public static class JSTransaction implements Transaction {
+        public static final long serialVersionUid = 0xfb2aa281;
+        private JS js;
+        JSScope newscope;
+        Vec v;
+        public JSTransaction(JS js) throws JSExn {
+            newscope = new JSScope(null);
+            this.js = JS.cloneWithNewParentScope(js, newscope);
+            v = JS.getFormalArgs(this.js);
+            for(int i=0; i<v.size(); i++) {
+                if ("prevalent".equals(v.elementAt(i))) continue;
+                newscope.put(v.elementAt(i), JS.getParentScope(js).get(v.elementAt(i)));
+            }
+        }
+        public void executeOn(Object o, Date now) {
+            try {
+                newscope.put("prevalent", o);
+                newscope.put("now", new JSDate(now.getTime()));
+                Object a = v.size() <= 0 ? null : newscope.get(v.elementAt(0));
+                Object b = v.size() <= 1 ? null : newscope.get(v.elementAt(1));
+                Object c = v.size() <= 2 ? null : newscope.get(v.elementAt(2));
+                Object[] rest = v.size() <= 3 ? null : new Object[v.size() - 3];
+                for(int i=3; i<v.size(); i++) rest[i-3] = v.elementAt(i);
+                js.call(a, b, c, rest, v.size());
+            } catch (Exception e) { throw new RuntimeException(e); }
+        }
+    }
+
+    public static class JSQuery implements Query {
+        public static final long serialVersionUid = 0xfb2aa282;
+        private JS js;
+        private Object a;
+        public JSQuery(JS js, Object a) { this.js = JS.cloneWithNewParentScope(js, null); this.a = a; }
+        public Object query(Object o, Date now) {
+            try {
+                return js.call(o, a, new JSDate(now.getTime()), null, 3);
+            } catch (Exception e) { throw new RuntimeException(e); }
+        }
+    }
+}