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

Reply via email to