001package com.hammurapi.common; 002 003import java.io.InputStream; 004import java.io.InputStreamReader; 005import java.util.Locale; 006import java.util.Map; 007 008import javax.script.ScriptEngine; 009import javax.script.ScriptEngineFactory; 010import javax.script.ScriptEngineManager; 011import javax.script.ScriptException; 012import javax.script.SimpleBindings; 013 014/** 015 * This class resolves and evaluates scripts for a class. 016 * Scripts and properties for script parameterization are resolved traversing class hierarchy. 017 * A special resource with .binder extension is used to create custom bindings for 018 * script evaluation. This resource shall contain a fragment of java code. This code shall reference a 019 * single parameter 'bindings' to access existing bindings and create new ones. 020 * 021 * The primary purpose of this class is to be a facility for flexible rendering/code generation. 022 * @author Pavel Vlasov 023 * 024 */ 025public class ScriptProcessor { 026 027 private ResourceLoader rl; 028 private ScriptEngineManager scriptEngineManager; 029 030 public ScriptProcessor(ResourceLoader resourceLoader, ClassLoader scriptEnginesClassLoader) { 031 this.rl = resourceLoader; 032 this.scriptEngineManager = scriptEnginesClassLoader==null ? new ScriptEngineManager() : new ScriptEngineManager(scriptEnginesClassLoader); 033 } 034 035 public Object eval(String scriptName, Map<String, Object> bindings, Locale locale) throws ScriptException { 036 for (ScriptEngineFactory sef: scriptEngineManager.getEngineFactories()) { 037 for (String extension: sef.getExtensions()) { 038 InputStream scriptStream = rl.getResourceStream(scriptName, locale, extension); 039 if (scriptStream!=null) { 040 SimpleBindings sBindings = new SimpleBindings(); 041 Map<String, Object> props = rl.getProperties(scriptName, locale, "properties"); 042 sBindings.putAll(props); 043 if (bindings!=null) { 044 sBindings.putAll(bindings); 045 } 046 InputStream binderStream = rl.getResourceStream(scriptName, locale, "binder"); 047 if (binderStream!=null) { 048 ScriptEngine be = scriptEngineManager.getEngineByExtension("java"); 049 if (be==null) { 050 throw new ScriptException("Cannot evaluate binder - java script engine not found"); 051 } 052 SimpleBindings bb = new SimpleBindings(); 053 bb.put("bindings", sBindings); 054 be.eval(new InputStreamReader(binderStream), bb); 055 } 056 return sef.getScriptEngine().eval(new InputStreamReader(scriptStream), sBindings); 057 } 058 } 059 } 060 throw new ScriptException("Script resource not found: "+scriptName+" in "+rl); 061 } 062 063}