Author: adrianc
Date: Fri Mar 9 20:41:18 2012 New Revision: 1299040 URL: http://svn.apache.org/viewvc?rev=1299040&view=rev Log: More JSR-223 work - added the ability to protect the bindings, plus some minor code formatting changes. Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ScriptUtil.java ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/FlexibleStringExpander.java ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/ScriptEngine.java Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ScriptUtil.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ScriptUtil.java?rev=1299040&r1=1299039&r2=1299040&view=diff ============================================================================== --- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ScriptUtil.java (original) +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ScriptUtil.java Fri Mar 9 20:41:18 2012 @@ -23,8 +23,10 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.net.MalformedURLException; import java.net.URL; +import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; import javax.script.Bindings; import javax.script.Compilable; @@ -35,6 +37,7 @@ import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import javax.script.ScriptEngineManager; import javax.script.ScriptException; +import javax.script.SimpleBindings; import javax.script.SimpleScriptContext; import org.codehaus.groovy.runtime.InvokerHelper; @@ -43,6 +46,10 @@ import org.ofbiz.base.util.cache.UtilCac /** * Scripting utility methods. This is a facade class that is used to connect OFBiz to JSR-223 scripting engines. + * <p><b>Important:</b> To avoid a lot of <code>Map</code> copying, all methods that accept a context + * <code>Map</code> argument will pass that <code>Map</code> directly to the scripting engine. Any variables that + * are declared or modified in the script will affect the original <code>Map</code>. Client code that wishes to preserve + * the state of the <code>Map</code> argument should pass a copy of the <code>Map</code>.</p> * */ public final class ScriptUtil { @@ -167,11 +174,31 @@ public final class ScriptUtil { * @param context * @return */ - public static ScriptContext createScriptContext(Map<String, ? extends Object> context) { + public static ScriptContext createScriptContext(Map<String, Object> context) { + Assert.notNull("context", context); + context.put("context", context); ScriptContext scriptContext = new SimpleScriptContext(); - Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE); - bindings.putAll(context); - bindings.put("context", context); + Bindings bindings = new SimpleBindings(context); + scriptContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE); + return scriptContext; + } + + /** + * Returns a <code>ScriptContext</code> that contains the members of <code>context</code>. + * <p>If a <code>CompiledScript</code> instance is to be shared by multiple threads, then + * each thread must create its own <code>ScriptContext</code> and pass it to the + * <code>CompiledScript</code> eval method.</p> + * + * @param context + * @param protectedKeys + * @return + */ + public static ScriptContext createScriptContext(Map<String, Object> context, Set<String> protectedKeys) { + Assert.notNull("context", context, "protectedKeys", protectedKeys); + context.put("context", context); + ScriptContext scriptContext = new SimpleScriptContext(); + Bindings bindings = new ProtectedBindings(context, protectedKeys); + scriptContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE); return scriptContext; } @@ -181,19 +208,19 @@ public final class ScriptUtil { * @param language * @param script * @param scriptClass - * @param inputMap + * @param context * @return The script result. * @throws Exception */ - public static Object evaluate(String language, String script, Class<?> scriptClass, Map<String, ? extends Object> inputMap) throws Exception { - Assert.notNull("inputMap", inputMap); + public static Object evaluate(String language, String script, Class<?> scriptClass, Map<String, Object> context) throws Exception { + Assert.notNull("context", context); if (scriptClass != null) { - return InvokerHelper.createScript(scriptClass, GroovyUtil.getBinding(inputMap)).run(); + return InvokerHelper.createScript(scriptClass, GroovyUtil.getBinding(context)).run(); } try { CompiledScript compiledScript = compileScriptString(language, script); if (compiledScript != null) { - return executeScript(compiledScript, null, createScriptContext(inputMap), null); + return executeScript(compiledScript, null, createScriptContext(context), null); } ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName(language); @@ -203,7 +230,7 @@ public final class ScriptUtil { if (Debug.verboseOn()) { Debug.logVerbose("Begin processing script [" + script + "] using engine " + engine.getClass().getName(), module); } - ScriptContext scriptContext = createScriptContext(inputMap); + ScriptContext scriptContext = createScriptContext(context); return engine.eval(script, scriptContext); } catch (Exception e) { String errMsg = "Error running " + language + " script [" + script + "]: " + e.toString(); @@ -248,7 +275,7 @@ public final class ScriptUtil { * @return The script result. * @throws IllegalArgumentException */ - public static Object executeScript(String filePath, String functionName, Map<String, ? extends Object> context) { + public static Object executeScript(String filePath, String functionName, Map<String, Object> context) { return executeScript(filePath, functionName, context, EMPTY_ARGS); } @@ -257,6 +284,27 @@ public final class ScriptUtil { * * @param filePath Script path and file name. * @param functionName Optional function or method to invoke. + * @param context Script execution context. + * @param args Function/method arguments. + * @return The script result. + * @throws IllegalArgumentException + */ + public static Object executeScript(String filePath, String functionName, Map<String, Object> context, Object[] args) { + Assert.notNull("filePath", filePath, "context", context); + try { + return executeScript(filePath, functionName, createScriptContext(context), args); + } catch (Exception e) { + String errMsg = "Error running script at location [" + filePath + "]: " + e.toString(); + Debug.logWarning(e, errMsg, module); + throw new IllegalArgumentException(errMsg); + } + } + + /** + * Executes the script at the specified location and returns the result. + * + * @param filePath Script path and file name. + * @param functionName Optional function or method to invoke. * @param scriptContext Script execution context. * @param args Function/method arguments. * @return The script result. @@ -294,27 +342,6 @@ public final class ScriptUtil { return result; } - /** - * Executes the script at the specified location and returns the result. - * - * @param filePath Script path and file name. - * @param functionName Optional function or method to invoke. - * @param context Script execution context. - * @param args Function/method arguments. - * @return The script result. - * @throws IllegalArgumentException - */ - public static Object executeScript(String filePath, String functionName, Map<String, ? extends Object> context, Object[] args) { - Assert.notNull("filePath", filePath, "context", context); - try { - return executeScript(filePath, functionName, createScriptContext(context), args); - } catch (Exception e) { - String errMsg = "Error running script at location [" + filePath + "]: " + e.toString(); - Debug.logWarning(e, errMsg, module); - throw new IllegalArgumentException(errMsg); - } - } - private static String getFileExtension(String filePath) { int pos = filePath.lastIndexOf("."); if (pos == -1) { @@ -332,4 +359,71 @@ public final class ScriptUtil { } private ScriptUtil() {} + + private static final class ProtectedBindings implements Bindings { + private final Map<String, Object> bindings; + private final Set<String> protectedKeys; + private ProtectedBindings(Map<String, Object> bindings, Set<String> protectedKeys) { + this.bindings = bindings; + this.protectedKeys = protectedKeys; + } + public void clear() { + for (String key : bindings.keySet()) { + if (!protectedKeys.contains(key)) { + bindings.remove(key); + } + } + } + public boolean containsKey(Object key) { + return bindings.containsKey(key); + } + public boolean containsValue(Object value) { + return bindings.containsValue(value); + } + public Set<java.util.Map.Entry<String, Object>> entrySet() { + return bindings.entrySet(); + } + public boolean equals(Object o) { + return bindings.equals(o); + } + public Object get(Object key) { + return bindings.get(key); + } + public int hashCode() { + return bindings.hashCode(); + } + public boolean isEmpty() { + return bindings.isEmpty(); + } + public Set<String> keySet() { + return bindings.keySet(); + } + public Object put(String key, Object value) { + Assert.notNull("key", key); + if (protectedKeys.contains(key)) { + throw new UnsupportedOperationException(); + } + return bindings.put(key, value); + } + public void putAll(Map<? extends String, ? extends Object> map) { + for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) { + Assert.notNull("key", entry.getKey()); + if (!protectedKeys.contains(entry.getKey())) { + bindings.put(entry.getKey(), entry.getValue()); + } + } + } + public Object remove(Object key) { + if (protectedKeys.contains(key)) { + throw new UnsupportedOperationException(); + } + return bindings.remove(key); + } + public int size() { + return bindings.size(); + } + public Collection<Object> values() { + return bindings.values(); + } + } } Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/FlexibleStringExpander.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/FlexibleStringExpander.java?rev=1299040&r1=1299039&r2=1299040&view=diff ============================================================================== --- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/FlexibleStringExpander.java (original) +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/FlexibleStringExpander.java Fri Mar 9 20:41:18 2012 @@ -21,6 +21,7 @@ package org.ofbiz.base.util.string; import java.io.Serializable; import java.math.BigDecimal; import java.util.ArrayList; +import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.TimeZone; @@ -593,7 +594,8 @@ public abstract class FlexibleStringExpa @Override protected Object get(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) { try { - Object obj = ScriptUtil.evaluate(this.language, this.script, this.parsedScript, context); + Map <String, Object> contextCopy = new HashMap<String, Object>(context); + Object obj = ScriptUtil.evaluate(this.language, this.script, this.parsedScript, contextCopy); if (obj != null) { return obj; } else { Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/ScriptEngine.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/ScriptEngine.java?rev=1299040&r1=1299039&r2=1299040&view=diff ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/ScriptEngine.java (original) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/ScriptEngine.java Fri Mar 9 20:41:18 2012 @@ -20,7 +20,10 @@ package org.ofbiz.service.engine; import static org.ofbiz.base.util.UtilGenerics.cast; +import java.util.Collections; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import javax.script.ScriptContext; @@ -50,14 +53,19 @@ import org.ofbiz.service.ServiceUtil; public final class ScriptEngine extends GenericAsyncEngine { public static final String module = ScriptEngine.class.getName(); + private static final Set<String> protectedKeys = createProtectedKeys(); - public ScriptEngine(ServiceDispatcher dispatcher) { - super(dispatcher); + private static Set<String> createProtectedKeys() { + Set<String> newSet = new HashSet<String>(); + newSet.add("parameters"); + newSet.add("dctx"); + newSet.add("dispatcher"); + newSet.add("delegator"); + return Collections.unmodifiableSet(newSet); } - @Override - public void runSyncIgnore(String localName, ModelService modelService, Map<String, Object> context) throws GenericServiceException { - runSync(localName, modelService, context); + public ScriptEngine(ServiceDispatcher dispatcher) { + super(dispatcher); } @Override @@ -71,7 +79,7 @@ public final class ScriptEngine extends context.put("dispatcher", dctx.getDispatcher()); context.put("delegator", dispatcher.getDelegator()); try { - ScriptContext scriptContext = ScriptUtil.createScriptContext(context); + ScriptContext scriptContext = ScriptUtil.createScriptContext(context, protectedKeys); Object resultObj = ScriptUtil.executeScript(getLocation(modelService), modelService.invoke, scriptContext, new Object[] { context }); if (resultObj == null) { resultObj = scriptContext.getAttribute("result"); @@ -88,4 +96,8 @@ public final class ScriptEngine extends } } + @Override + public void runSyncIgnore(String localName, ModelService modelService, Map<String, Object> context) throws GenericServiceException { + runSync(localName, modelService, context); + } } |
Free forum by Nabble | Edit this page |