001: package fr.aliacom.util;
002:
003: import java.io.IOException;
004: import java.io.InputStream;
005: import java.util.Iterator;
006:
007: import org.apache.log4j.Logger;
008: import org.python.core.PyObject;
009: import org.python.core.__builtin__;
010: import org.python.util.PythonInterpreter;
011:
012: import fr.aliacom.form.common.FormContext;
013: import fr.aliacom.form.common.FormVariable;
014: import fr.aliacom.form.common.Toolkit;
015: import fr.aliacom.form.common.ToolkitManager;
016:
017: /**
018: * A Jython interpreter wrapper suitable for executing
019: * code on a {@link fr.aliacom.form.common.FormContext}.
020: *
021: * The <code>executeByName</code> methods automatically defines a few
022: * variables :
023: *
024: * <ul>
025: * <li><code>FORM</code>: a reference on the calling form</li>
026: * <li>One python variable for each {@link fr.aliacom.form.common.FormVariable}
027: * in the context.</li>
028: * </ul>
029: *
030: * @author tom
031: *
032: * (c) 2001, 2003 Thomas Cataldo
033: */
034: public final class JythonInterpreter {
035:
036: private PythonInterpreter interp;
037: private LRUCache codeMap;
038: private InterpreterPool pool;
039: private Toolkit tk;
040: private Logger log;
041:
042: JythonInterpreter(InterpreterPool pool) {
043: log = Logger.getLogger(JythonInterpreter.class);
044: this .interp = new PythonInterpreter();
045: this .codeMap = pool.getCodeMap();
046: this .pool = pool;
047: this .tk = ToolkitManager.getToolkit();
048: }
049:
050: /**
051: * Execute a script on a {@link FormContext}.
052: *
053: * This method tries to execute a cached version of the script.
054: * If the script is not cached, it is read using the <code>loadScript</code>
055: * method in the {@link Toolkit} class and added to the cache.
056: *
057: * @param name the script to execute
058: * @param ctx the context holding the variables passed to the script
059: * @throws Exception
060: */
061: public void executeByName(String name, FormContext ctx)
062: throws IOException {
063: PyObject code = (PyObject) codeMap.get(name);
064:
065: if (code == null) {
066: log.debug("script " + name + " not cached");
067: InputStream is = tk.loadScript(name);
068: String stringCode = null;
069: try {
070: stringCode = StringFunctions.read(is);
071: code = __builtin__.compile(stringCode, "<template>",
072: "exec");
073: codeMap.put(name, code);
074: } catch (IOException e) {
075: log.fatal("Error reading script " + name, e);
076: }
077: }
078: Logger logger = Logger.getLogger(name);
079: executeCode(code, ctx, logger);
080: }
081:
082: private void executeCode(PyObject code, FormContext ctx,
083: Logger logger) {
084: Iterator it = ctx.getVariables();
085: while (it.hasNext()) {
086: FormVariable fv = (FormVariable) it.next();
087: log.debug(fv.getName() + " added to python vars (" + fv
088: + ")");
089: interp.set(fv.getName(), fv.getValue());
090: }
091: interp.set("FORM", ctx.getForm());
092: interp.set("LOG", logger);
093:
094: interp.exec(code);
095: }
096:
097: /**
098: * Bring a value from the interpreter environment to the java environment.
099: *
100: * @param name
101: * @param klass
102: * @return the value of a variable in the interpreter environment
103: */
104: public Object get(String name, Class klass) {
105: return interp.get(name, klass);
106: }
107:
108: /**
109: *
110: */
111: public void release() {
112: interp.cleanup();
113: pool.release(this);
114: }
115:
116: }
|