+// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
+package org.ibex.mail;
+import org.ibex.js.*;
+
+public class Script {
+
+ public static final JS root =
+ new Script(System.getProperty("ibex.mail.conf", File.separatorChar + "etc" + File.separatorChar + "org.ibex.mail.conf"));
+
+ final JS js;
+ public Script(String filePath) { js = JS.fromReader(CONF, 0, new InputStreamReader(new FileInputStream(CONF))); }
+
+ public void accept(Message m) throws IOException {
+ // currently, we write all inbound messages to the transcript
+ MessageStore.transcript.add(m);
+ Object ret = js.call(m);
+ if (ret instanceof Target) {
+ ((Target)ret).accept(m);
+ } else if (ret instanceof Filter) {
+ ((Filter)f).accept
+ } else {
+ throw new IOException("configuration script returned a " + ret.getClass().getName());
+ }
+ }
+
+ // FIXME: this should extend org.ibex.core.Ibex
+ public static class ScriptEnvironment extends JS {
+
+ // FIXME: duplicated code with org.ibex.core.Ibex; lift?
+ /** lets us put multi-level get/put/call keys all in the same method */
+ private class Sub extends JS {
+ String key;
+ Sub(String key) { this.key = key; }
+ public void put(Object key, Object val) throws JSExn { ScriptEnv.this.put(this.key + "." + key, val); }
+ public Object get(Object key) throws JSExn { return ScriptEnv.this.get(this.key + "." + key); }
+ public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
+ return ScriptEnv.this.callMethod(this.key, a0, a1, a2, rest, nargs);
+ }
+ public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
+ return ScriptEnv.this.callMethod(this.key + "." + method, a0, a1, a2, rest, nargs);
+ }
+ }
+ private Cache subCache = new Cache(20);
+ private Sub getSub(String s) {
+ Sub ret = (Sub)subCache.get(s);
+ if (ret == null) subCache.put(s, ret = new Sub(s));
+ return ret;
+ }
+
+ public Object get(Object name) throws JSExn {
+ if (name instanceof String && ((String)name).length() == 0) return rr;
+ //#switch(name)
+ case "math": return ibexMath;
+ case "string": return ibexString;
+ case "date": return METHOD;
+ case "regexp": return METHOD;
+ case "log": return getSub("log");
+ case "log.debug": return METHOD;
+ case "log.info": return METHOD;
+ case "log.warn": return METHOD;
+ case "log.error": return METHOD;
+ //#end
+ return super.get(name);
+ }
+
+ public Object callMethod(Object name, Object a, Object b, Object c, Object[] rest, int nargs) throws JSExn {
+ try {
+ //#switch(name)
+ case "date": return new JSDate(a, b, c, rest, nargs);
+ case "log.debug": JS.debug(a== null ? "**null**" : a.toString()); return null;
+ case "log.info": JS.info(a== null ? "**null**" : a.toString()); return null;
+ case "log.warn": JS.warn(a== null ? "**null**" : a.toString()); return null;
+ case "log.error": JS.error(a== null ? "**null**" : a.toString()); return null;
+ //#end
+ switch (nargs) {
+ case 1:
+ //#switch(name)
+ case "regexp": return new JSRegexp(a, null);
+ //#end
+ break;
+ case 2:
+ //#switch(name)
+ case "regexp": return new JSRegexp(a, b);
+ //#end
+ }
+ } catch (RuntimeException e) {
+ // FIXME: maybe JSExn should take a second argument, Exception
+ Log.warn(this, "ibex."+name+"() threw: " + e);
+ throw new JSExn("invalid argument for ibex object method "+name+"()");
+ }
+ throw new JSExn("invalid number of arguments ("+nargs+") for ibex object method "+name+"()");
+ }
+
+ public static final JSMath ibexMath = new JSMath() {
+ private JS gs = new JSScope.Global();
+ public Object get(Object key) throws JSExn {
+ //#switch(key)
+ case "isNaN": return gs.get("isNaN");
+ case "isFinite": return gs.get("isFinite");
+ case "NaN": return gs.get("NaN");
+ case "Infinity": return gs.get("Infinity");
+ //#end
+ return super.get(key);
+ }
+ };
+
+ public static final JS ibexString = new JS() {
+ private JS gs = new JSScope.Global();
+ public void put(Object key, Object val) { }
+ public Object get(Object key) throws JSExn {
+ //#switch(key)
+ case "parseInt": return gs.get("parseInt");
+ case "parseFloat": return gs.get("parseFloat");
+ case "decodeURI": return gs.get("decodeURI");
+ case "decodeURIComponent": return gs.get("decodeURIComponent");
+ case "encodeURI": return gs.get("encodeURI");
+ case "encodeURIComponent": return gs.get("encodeURIComponent");
+ case "escape": return gs.get("escape");
+ case "unescape": return gs.get("unescape");
+ case "fromCharCode": return gs.get("stringFromCharCode");
+ //#end
+ return null;
+ }
+ };
+ }
+}