details: https://code.openbravo.com/erp/devel/pi/rev/120a6a75f9b7 changeset: 33188:120a6a75f9b7 user: Augusto Mauch <augusto.mauch <at> openbravo.com> date: Tue Jan 16 17:16:51 2018 +0100 summary: Fixes issue 37643: OBScriptEngine can be used to evaluate javascript scripts
There were four classes that were creating a new instance of ScriptEngine each time they needed to evaluate a javascript script. This was not the better way to do it, since creating a ScriptEngine instance can be expensive, and that class is thread safety if properly used (i.e. by setting the bindings to each evaluation instead of to the script engine itself). A new singleton class has been added, OBScriptEngine, that is now used by all the classes that need to evaluate javascript scripts. diffstat: modules/org.openbravo.client.application/src/org/openbravo/client/application/ParameterUtils.java | 15 +- modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewFieldHandler.java | 9 +- modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/SelectorDefaultFilterActionHandler.java | 17 +- src/org/openbravo/base/expression/Evaluator.java | 19 +- src/org/openbravo/base/expression/OBScriptEngine.java | 69 ++++++++++ 5 files changed, 97 insertions(+), 32 deletions(-) diffs (292 lines): diff -r 8e83421e15ba -r 120a6a75f9b7 modules/org.openbravo.client.application/src/org/openbravo/client/application/ParameterUtils.java --- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/ParameterUtils.java Mon Jan 15 12:28:10 2018 -0500 +++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/ParameterUtils.java Tue Jan 16 17:16:51 2018 +0100 @@ -11,7 +11,7 @@ * under the License. * The Original Code is Openbravo ERP. * The Initial Developer of the Original Code is Openbravo SLU - * All portions are Copyright (C) 2010-2015 Openbravo SLU + * All portions are Copyright (C) 2010-2018 Openbravo SLU * All Rights Reserved. * Contributor(s): ______________________________________. ************************************************************************ @@ -24,8 +24,6 @@ import java.util.HashMap; import java.util.Map; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @@ -34,6 +32,7 @@ import org.apache.log4j.Logger; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; +import org.openbravo.base.expression.OBScriptEngine; import org.openbravo.base.model.Entity; import org.openbravo.base.model.ModelProvider; import org.openbravo.base.model.domaintype.BasePrimitiveDomainType; @@ -59,6 +58,7 @@ * @author iperdomo */ public class ParameterUtils { + private static Logger log = Logger.getLogger(ParameterUtils.class); public static void setParameterValue(ParameterValue parameterValue, JSONObject requestValue) { @@ -269,16 +269,15 @@ @SuppressWarnings("rawtypes") public static Object getJSExpressionResult(Map<String, String> parameters, HttpSession session, String expression) throws ScriptException { - final ScriptEngineManager manager = new ScriptEngineManager(); - final ScriptEngine engine = manager.getEngineByName("js"); + Map<String, Object> bindings = new HashMap<>(); if (session != null) { - engine.put("OB", new OBBindings(OBContext.getOBContext(), parameters, session)); + bindings.put("OB", new OBBindings(OBContext.getOBContext(), parameters, session)); } else { - engine.put("OB", new OBBindings(OBContext.getOBContext(), parameters)); + bindings.put("OB", new OBBindings(OBContext.getOBContext(), parameters)); } - Object result = engine.eval(expression); + Object result = OBScriptEngine.getInstance().eval(expression, bindings); if (result instanceof Map) { // complex js object, convert it into a JSON result = new JSONObject((Map) result); diff -r 8e83421e15ba -r 120a6a75f9b7 modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewFieldHandler.java --- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewFieldHandler.java Mon Jan 15 12:28:10 2018 -0500 +++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewFieldHandler.java Tue Jan 16 17:16:51 2018 +0100 @@ -11,7 +11,7 @@ * under the License. * The Original Code is Openbravo ERP. * The Initial Developer of the Original Code is Openbravo SLU - * All portions are Copyright (C) 2011-2017 Openbravo SLU + * All portions are Copyright (C) 2011-2018 Openbravo SLU * All Rights Reserved. * Contributor(s): ______________________________________. ************************************************************************ @@ -28,14 +28,13 @@ import java.util.Map; import java.util.Set; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; import javax.script.ScriptException; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; +import org.openbravo.base.expression.OBScriptEngine; import org.openbravo.base.model.Entity; import org.openbravo.base.model.ModelProvider; import org.openbravo.base.model.Property; @@ -1575,14 +1574,12 @@ String translatedDisplayLogic = DynamicExpressionParser .replaceSystemPreferencesInDisplayLogic(displayLogicEvaluatedInTheServer); - final ScriptEngineManager manager = new ScriptEngineManager(); - final ScriptEngine engine = manager.getEngineByName("js"); boolean result; DynamicExpressionParser parser = new DynamicExpressionParser(translatedDisplayLogic, tab); try { - result = (Boolean) engine.eval(parser.getJSExpression()); + result = (Boolean) OBScriptEngine.getInstance().eval(parser.getJSExpression()); } catch (ScriptException e) { log.error( "Error while evaluating the Display Logic at Server Level. Error in field with id: " diff -r 8e83421e15ba -r 120a6a75f9b7 modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/SelectorDefaultFilterActionHandler.java --- a/modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/SelectorDefaultFilterActionHandler.java Mon Jan 15 12:28:10 2018 -0500 +++ b/modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/SelectorDefaultFilterActionHandler.java Tue Jan 16 17:16:51 2018 +0100 @@ -11,7 +11,7 @@ * under the License. * The Original Code is Openbravo ERP. * The Initial Developer of the Original Code is Openbravo SLU - * All portions are Copyright (C) 2010-2016 Openbravo SLU + * All portions are Copyright (C) 2010-2018 Openbravo SLU * All Rights Reserved. * Contributor(s): ______________________________________. ************************************************************************ @@ -23,8 +23,6 @@ import java.util.Map; import javax.enterprise.context.ApplicationScoped; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; @@ -32,6 +30,7 @@ import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.hibernate.criterion.Restrictions; +import org.openbravo.base.expression.OBScriptEngine; import org.openbravo.base.model.Entity; import org.openbravo.base.model.ModelProvider; import org.openbravo.base.model.Property; @@ -93,9 +92,9 @@ return result; } - final ScriptEngineManager manager = new ScriptEngineManager(); - final ScriptEngine engine = manager.getEngineByName(SelectorConstants.JS); - engine.put( + Map<String, Object> bindings = new HashMap<>(); + + bindings.put( "OB", new OBBindings(OBContext.getOBContext(), params, (HttpSession) parameters .get(KernelConstants.HTTP_SESSION))); @@ -107,7 +106,7 @@ JSONArray idFilters = new JSONArray(); for (SelectorField f : selFields) { try { - exprResult = engine.eval(f.getDefaultExpression()); + exprResult = OBScriptEngine.getInstance().eval(f.getDefaultExpression(), bindings); Object bobId = null; if (exprResult != null && !exprResult.equals("") && !exprResult.equals("''")) { @@ -146,12 +145,12 @@ if (idFilters.length() > 0) { result.put(SelectorConstants.PARAM_ID_FILTERS, idFilters); } - // Obtaining the filter Expression from Selector. Refer issue // https://issues.openbravo.com/view.php?id=21541 Object dynamicFilterExpression = null; if (sel.getFilterExpression() != null) { - dynamicFilterExpression = engine.eval(sel.getFilterExpression()); + dynamicFilterExpression = OBScriptEngine.getInstance().eval(sel.getFilterExpression(), + bindings); result.put(SelectorConstants.PARAM_FILTER_EXPRESSION, dynamicFilterExpression.toString()); } diff -r 8e83421e15ba -r 120a6a75f9b7 src/org/openbravo/base/expression/Evaluator.java --- a/src/org/openbravo/base/expression/Evaluator.java Mon Jan 15 12:28:10 2018 -0500 +++ b/src/org/openbravo/base/expression/Evaluator.java Tue Jan 16 17:16:51 2018 +0100 @@ -8,14 +8,15 @@ * either express or implied. See the License for the specific language * governing rights and limitations under the License. The Original Code is * Openbravo ERP. The Initial Developer of the Original Code is Openbravo SLU All - * portions are Copyright (C) 2008-2010 Openbravo SLU All Rights Reserved. + * portions are Copyright (C) 2008-2018 Openbravo SLU All Rights Reserved. * Contributor(s): ______________________________________. */ package org.openbravo.base.expression; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; +import java.util.HashMap; +import java.util.Map; + import javax.script.ScriptException; import org.apache.log4j.Logger; @@ -66,22 +67,22 @@ log.debug("Evaluating script for " + contextBob + " script: " + script); + OBScriptEngine engine = OBScriptEngine.getInstance(); + try { - // note that the name of a engine can differ: Mozilla Rhino - // but js seems to work fine - final ScriptEngineManager manager = new ScriptEngineManager(); - final ScriptEngine engine = manager.getEngineByName("js"); Check .isNotNull( engine, "Scripting engine not found using name js, check for other scripting language names such as Mozilla Rhino"); final Entity e = contextBob.getEntity(); + + Map<String, Object> bindings = new HashMap<>(); for (final Property p : e.getProperties()) { - engine.put(p.getName(), contextBob.get(p.getName())); + bindings.put(p.getName(), contextBob.get(p.getName())); } - final Object result = engine.eval(script); + final Object result = engine.eval(script, bindings); Check.isInstanceOf(result, Boolean.class); return (Boolean) result; } catch (final ScriptException e) { diff -r 8e83421e15ba -r 120a6a75f9b7 src/org/openbravo/base/expression/OBScriptEngine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/openbravo/base/expression/OBScriptEngine.java Tue Jan 16 17:16:51 2018 +0100 @@ -0,0 +1,69 @@ +/* + ************************************************************************* + * The contents of this file are subject to the Openbravo Public License + * Version 1.1 (the "License"), being the Mozilla Public License + * Version 1.1 with a permitted attribution clause; you may not use this + * file except in compliance with the License. You may obtain a copy of + * the License at http://www.openbravo.com/legal/license.html + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * The Original Code is Openbravo ERP. + * The Initial Developer of the Original Code is Openbravo SLU + * All portions are Copyright (C) 2018 Openbravo SLU + * All Rights Reserved. + * Contributor(s): ______________________________________. + ************************************************************************ + */ +package org.openbravo.base.expression; + +import java.util.Map; +import java.util.Map.Entry; + +import javax.script.Bindings; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; + +/** + * Class that wraps a ScriptEngine and that should be used to evaluate javascript scripts + * + * It is a singleton, and it takes advantage of the thread safety of ScriptEngine + * + */ +public class OBScriptEngine { + + private final ScriptEngine engine; + + private static OBScriptEngine instance; + + public static synchronized OBScriptEngine getInstance() { + if (instance == null) { + instance = new OBScriptEngine(); + } + return instance; + } + + private OBScriptEngine() { + ScriptEngineManager manager = new ScriptEngineManager(); + engine = manager.getEngineByName("js"); + } + + public Object eval(String script) throws ScriptException { + return engine.eval(script); + } + + public Object eval(String script, Map<String, Object> properties) throws ScriptException { + Bindings bindings = engine.createBindings(); + copyPropertiesToBindings(properties, bindings); + return engine.eval(script, bindings); + } + + private void copyPropertiesToBindings(Map<String, Object> properties, Bindings bindings) { + for (Entry<String, Object> entry : properties.entrySet()) { + bindings.put(entry.getKey(), entry.getValue()); + } + } + +} ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Openbravo-commits mailing list Openbravo-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openbravo-commits