From e3a151ba478f9d0496a50f49a0b1cca0eb1cf9fd Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Sat, 26 Jan 2019 17:43:29 +0100 Subject: [PATCH] IDEMPIERE-3879 Error executing Rule / revert IDEMPIERE-3243 and implement different approach --- .../src/org/adempiere/base/Core.java | 30 ++- .../adempiere/base/osgi/OSGiScriptEngine.java | 85 ------- .../base/osgi/OSGiScriptEngineFactory.java | 89 -------- .../base/osgi/OSGiScriptEngineManager.java | 216 ------------------ .../src/org/adempiere/util/ProcessUtil.java | 4 + .../src/org/compiere/model/GridTab.java | 5 + .../src/org/compiere/model/MMeasure.java | 4 + .../src/org/compiere/model/MRule.java | 7 +- .../compiere/model/ModelValidationEngine.java | 10 + 9 files changed, 45 insertions(+), 405 deletions(-) delete mode 100644 org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngine.java delete mode 100644 org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngineFactory.java delete mode 100644 org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngineManager.java diff --git a/org.adempiere.base/src/org/adempiere/base/Core.java b/org.adempiere.base/src/org/adempiere/base/Core.java index 83ed39cdff..fd8c74cc8e 100644 --- a/org.adempiere.base/src/org/adempiere/base/Core.java +++ b/org.adempiere.base/src/org/adempiere/base/Core.java @@ -26,8 +26,9 @@ import java.util.List; import java.util.logging.Level; import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptEngineManager; -import org.adempiere.base.osgi.OSGiScriptEngineManager; import org.adempiere.model.IAddressValidation; import org.adempiere.model.IShipmentProcessor; import org.adempiere.model.ITaxProvider; @@ -47,7 +48,6 @@ import org.compiere.process.ProcessCall; import org.compiere.util.CLogger; import org.compiere.util.PaymentExport; import org.compiere.util.ReplenishInterface; -import org.osgi.framework.FrameworkUtil; /** * This is a facade class for the Service Locator. @@ -55,8 +55,6 @@ import org.osgi.framework.FrameworkUtil; * * @author viola * @author hengsin - * @author Silvano Trinchero, www.freepath.it - *
  • IDEMPIERE-3243 added getScriptEngine to manage both registered engines and engines provided by osgi bundles */ public class Core { @@ -437,17 +435,31 @@ public class Core { } - /** Get script engine, checking classpath first, and then osgi plugins + /** Get script engine * * @param engineName * @return ScriptEngine found, or null */ public static ScriptEngine getScriptEngine(String engineName) { - OSGiScriptEngineManager osgiFactory = new OSGiScriptEngineManager( FrameworkUtil.getBundle(Core.class).getBundleContext()); - ScriptEngine engine = osgiFactory.getEngineByName(engineName); - - return engine; + ScriptEngineManager manager = new ScriptEngineManager(Core.class.getClassLoader()); + ScriptEngine engine = manager.getEngineByName(engineName); + if (engine != null) + return engine; + + List factoryList = + Service.locator().list(ScriptEngineFactory.class).getServices(); + if (factoryList != null) { + for(ScriptEngineFactory factory : factoryList) { + for (String name : factory.getNames()) { + if (engineName.equals(name)) { + return factory.getScriptEngine(); + } + } + } + } + + return null; } /** diff --git a/org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngine.java b/org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngine.java deleted file mode 100644 index 31619a0428..0000000000 --- a/org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngine.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2005 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.adempiere.base.osgi; - -import java.io.Reader; - -import javax.script.Bindings; -import javax.script.ScriptContext; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineFactory; -import javax.script.ScriptException; - -/** - * Imported from Apache Felix project. - * Original file: - * http://svn.apache.org/repos/asf/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngine.java - * - */ - - -public class OSGiScriptEngine implements ScriptEngine{ - private ScriptEngine engine; - private OSGiScriptEngineFactory factory; - public OSGiScriptEngine(ScriptEngine engine, OSGiScriptEngineFactory factory){ - this.engine=engine; - this.factory=factory; - } - public Bindings createBindings() { - return engine.createBindings(); - } - public Object eval(Reader reader, Bindings n) throws ScriptException { - return engine.eval(reader, n); - } - public Object eval(Reader reader, ScriptContext context) throws ScriptException { - return engine.eval(reader, context); - } - public Object eval(Reader reader) throws ScriptException { - return engine.eval(reader); - } - public Object eval(String script, Bindings n) throws ScriptException { - return engine.eval(script, n); - } - public Object eval(String script, ScriptContext context) throws ScriptException { - return engine.eval(script, context); - } - public Object eval(String script) throws ScriptException { - return engine.eval(script); - } - public Object get(String key) { - return engine.get(key); - } - public Bindings getBindings(int scope) { - return engine.getBindings(scope); - } - public ScriptContext getContext() { - return engine.getContext(); - } - public ScriptEngineFactory getFactory() { - return factory; - } - public void put(String key, Object value) { - engine.put(key, value); - } - public void setBindings(Bindings bindings, int scope) { - engine.setBindings(bindings, scope); - } - public void setContext(ScriptContext context) { - engine.setContext(context); - } - -} diff --git a/org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngineFactory.java b/org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngineFactory.java deleted file mode 100644 index e071878fc7..0000000000 --- a/org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngineFactory.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2005 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.adempiere.base.osgi; - -import java.util.List; - -import javax.script.ScriptEngine; -import javax.script.ScriptEngineFactory; - -/** - * This is a wrapper class for the ScriptEngineFactory class that deals with context class loader issues - * It is necessary because engines (at least ruby) use the context classloader to find their resources (i.e., their "native" classes) - * - */ - -/** - * Imported from Apache Felix project. - * Original file: - * http://svn.apache.org/repos/asf/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineFactory.java - * - */ -public class OSGiScriptEngineFactory implements ScriptEngineFactory{ - private ScriptEngineFactory factory; - private ClassLoader contextClassLoader; - public OSGiScriptEngineFactory (ScriptEngineFactory factory, ClassLoader contextClassLoader){ - this.factory=factory; - this.contextClassLoader=contextClassLoader; - } - public String getEngineName() { - return factory.getEngineName(); - } - public String getEngineVersion() { - return factory.getEngineVersion(); - } - public List getExtensions() { - return factory.getExtensions(); - } - public String getLanguageName() { - return factory.getLanguageName(); - } - public String getLanguageVersion() { - return factory.getLanguageVersion(); - } - public String getMethodCallSyntax(String obj, String m, String... args) { - return factory.getMethodCallSyntax(obj, m, args); - } - public List getMimeTypes() { - return factory.getMimeTypes(); - } - public List getNames() { - return factory.getNames(); - } - public String getOutputStatement(String toDisplay) { - return factory.getOutputStatement(toDisplay); - } - public Object getParameter(String key) { - return factory.getParameter(key); - } - public String getProgram(String... statements) { - return factory.getProgram(statements); - } - public ScriptEngine getScriptEngine() { - ScriptEngine engine=null; - if(contextClassLoader!=null){ - ClassLoader old=Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(contextClassLoader); - engine=factory.getScriptEngine(); - Thread.currentThread().setContextClassLoader(old); - } - else engine=factory.getScriptEngine(); - return engine; - } - - -} diff --git a/org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngineManager.java b/org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngineManager.java deleted file mode 100644 index a020533875..0000000000 --- a/org.adempiere.base/src/org/adempiere/base/osgi/OSGiScriptEngineManager.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2005 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.adempiere.base.osgi; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.script.Bindings; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineFactory; -import javax.script.ScriptEngineManager; -import javax.script.SimpleBindings; - -import org.adempiere.base.Service; -import org.osgi.framework.BundleContext; - -/** - * This class acts as a delegate for all the available ScriptEngineManagers. Unluckily, the standard did not - * define it as an interface, so we need to extend it to allow polymorphism. However, no calls to super are used. - * It wraps all available ScriptEngineManagers in the OSGi ServicePlatform into a merged ScriptEngineManager. - * - * Internally, what this class does is creating ScriptEngineManagers for each bundle - * that contains a ScriptEngineFactory and includes a META-INF/services/javax.script.ScriptEngineFactory file. - * It assumes that the file contains a list of @link ScriptEngineFactory classes. For each bundle, it creates a - * ScriptEngineManager, then merges them. @link ScriptEngineFactory objects are wrapped - * into @link OSGiScriptEngineFactory objects to deal with problems of context class loader: - * Those scripting engines that rely on the ContextClassloader for finding resources need to use this wrapper - * and the @link OSGiScriptFactory. Mainly, jruby does. - * - * Note that even if no context classloader issues arose, it would still be needed to search manually for the - * factories and either use them directly (losing the mimeType/extension/shortName mechanisms for finding engines - * or manually registering them) or still use this class, which would be smarter. In the latter case, - * it would only be needed to remove the hack that temporarily sets the context classloader to the appropriate, - * bundle-related, class loader. - * - * Caveats: - *
    • - * All factories are wrapped with an {@link OSGiScriptEngineFactory}. As Engines are not wrapped, - * calls like - * - * ScriptEngineManager osgiManager=new OSGiScriptEngineManager(context);
      - * ScriptEngine engine=osgiManager.getEngineByName("ruby"); - * ScriptEngineFactory factory=engine.getFactory() //this does not return the OSGiFactory wrapper - * factory.getScriptEngine(); //this might fail, as it does not use OSGiScriptEngineFactory wrapper - *
      - * might result in unexpected errors. Future versions may wrap the ScriptEngine with a OSGiScriptEngine to solve this - * issue, but for the moment it is not needed. - *
    • - * - */ - -/** - * Imported from Apache Felix project. - * Original file: - * http://svn.apache.org/repos/asf/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineManager.java - * - * @author Silvano Trinchero, www.freepath.it - *
    • IDEMPIERE-3243 fixed class discovery to avoid comment lines - * - */ - -public class OSGiScriptEngineManager extends ScriptEngineManager{ - private Bindings bindings; - private Map classLoaders; - private BundleContext context; - - public OSGiScriptEngineManager(BundleContext context){ - this.context=context; - bindings=new SimpleBindings(); - this.classLoaders=findManagers(context); - } - /** - * This method is the only one that is visible and not part of the ScriptEngineManager class. - * Its purpose is to find new managers that weren't available before, but keeping the globalScope bindings - * set. - * If you want to clean the bindings you can either get a fresh instance of OSGiScriptManager or - * setting up a new bindings object. - * This can be done with: - * - * ScriptEngineManager manager=new OSGiScriptEngineManager(context); - * (...)//do stuff - * osgiManager=(OSGiScriptEngineManager)manager;//cast to ease reading - * osgiManager.reloadManagers(); - * - * manager.setBindings(new OSGiBindings());//or you can use your own bindings implementation - * - * - * - */ - public void reloadManagers(){ - this.classLoaders=findManagers(context); - } - - public Object get(String key) { - return bindings.get(key); - } - - public Bindings getBindings() { - return bindings; - } - - public ScriptEngine getEngineByExtension(String extension) { - //TODO this is a hack to deal with context class loader issues - ScriptEngine engine=null; - for(ScriptEngineManager manager: classLoaders.keySet()){ - ClassLoader old=Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(classLoaders.get(manager)); - engine=manager.getEngineByExtension(extension); - Thread.currentThread().setContextClassLoader(old); - if (engine!=null) break; - } - return engine; - } - - public ScriptEngine getEngineByMimeType(String mimeType) { - //TODO this is a hack to deal with context class loader issues - ScriptEngine engine=null; - for(ScriptEngineManager manager: classLoaders.keySet()){ - ClassLoader old=Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(classLoaders.get(manager)); - engine=manager.getEngineByMimeType(mimeType); - Thread.currentThread().setContextClassLoader(old); - if (engine!=null) break; - } - return engine; - } - - public ScriptEngine getEngineByName(String shortName) { - //TODO this is a hack to deal with context class loader issues - for(ScriptEngineManager manager: classLoaders.keySet()){ - ClassLoader old=Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(classLoaders.get(manager)); - ScriptEngine engine=manager.getEngineByName(shortName); - Thread.currentThread().setContextClassLoader(old); - if (engine!=null){ - return new OSGiScriptEngine(engine, new OSGiScriptEngineFactory(engine.getFactory(), classLoaders.get(manager))); - } - } - return null; - } - public List getEngineFactories() { - List osgiFactories=new ArrayList(); - for(ScriptEngineManager engineManager: classLoaders.keySet()){ - for (ScriptEngineFactory factory : engineManager.getEngineFactories()){ - osgiFactories.add(new OSGiScriptEngineFactory(factory, classLoaders.get(engineManager))); - } - } - return osgiFactories; - } - - public void put(String key, Object value) { - bindings.put(key, value); - } - - public void registerEngineExtension(String extension, ScriptEngineFactory factory) { - for(ScriptEngineManager engineManager: classLoaders.keySet()) - engineManager.registerEngineExtension(extension, factory); - } - - public void registerEngineMimeType(String type, ScriptEngineFactory factory) { - for(ScriptEngineManager engineManager: classLoaders.keySet()) - engineManager.registerEngineMimeType(type, factory); - } - - public void registerEngineName(String name, ScriptEngineFactory factory) { - for(ScriptEngineManager engineManager: classLoaders.keySet()) - engineManager.registerEngineName(name, factory); - } - /** - * Follows the same behavior of @link javax.script.ScriptEngineManager#setBindings(Bindings) - * This means that the same bindings are applied to all the underlying managers. - * @param bindings - */ - public void setBindings(Bindings bindings) { - this.bindings=bindings; - for(ScriptEngineManager manager: classLoaders.keySet()){ - manager.setBindings(bindings); - } - - } - - private Map findManagers(BundleContext context) { - - Map managers=new HashMap(); - - List seFactoryList = - Service.locator().list(ScriptEngineFactory.class).getServices(); - if (seFactoryList != null) { - for(ScriptEngineFactory seFactory : seFactoryList) { - ClassLoader factoryLoader = seFactory.getClass().getClassLoader(); - ScriptEngineManager manager=new ScriptEngineManager(factoryLoader); - manager.setBindings(bindings); - managers.put(manager, factoryLoader); - } - } - - return managers; - } - -} diff --git a/org.adempiere.base/src/org/adempiere/util/ProcessUtil.java b/org.adempiere.base/src/org/adempiere/util/ProcessUtil.java index e3f9974785..cda6c560f9 100644 --- a/org.adempiere.base/src/org/adempiere/util/ProcessUtil.java +++ b/org.adempiere.base/src/org/adempiere/util/ProcessUtil.java @@ -29,6 +29,7 @@ import java.util.logging.Level; import javax.script.ScriptEngine; import org.adempiere.base.Core; +import org.adempiere.exceptions.AdempiereException; import org.compiere.model.MProcess; import org.compiere.model.MRule; import org.compiere.process.ProcessCall; @@ -217,6 +218,9 @@ public final class ProcessUtil { } ScriptEngine engine = rule.getScriptEngine(); + if (engine == null) { + throw new AdempiereException("Engine not found: " + rule.getEngineName()); + } // Window context are W_ // Login context are G_ diff --git a/org.adempiere.base/src/org/compiere/model/GridTab.java b/org.adempiere.base/src/org/compiere/model/GridTab.java index af44023cb2..83826a7c9b 100644 --- a/org.adempiere.base/src/org/compiere/model/GridTab.java +++ b/org.adempiere.base/src/org/compiere/model/GridTab.java @@ -2880,6 +2880,11 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable } ScriptEngine engine = rule.getScriptEngine(); + if (engine == null) { + retValue = "Callout Invalid, engine not found: " + rule.getEngineName(); + log.log(Level.SEVERE, retValue); + return retValue; + } // Window context are W_ // Login context are G_ diff --git a/org.adempiere.base/src/org/compiere/model/MMeasure.java b/org.adempiere.base/src/org/compiere/model/MMeasure.java index 238bc1a72b..f81cc7b5fa 100644 --- a/org.adempiere.base/src/org/compiere/model/MMeasure.java +++ b/org.adempiere.base/src/org/compiere/model/MMeasure.java @@ -28,6 +28,7 @@ import java.util.logging.Level; import javax.script.ScriptEngine; import org.adempiere.apps.graph.GraphColumn; +import org.adempiere.exceptions.AdempiereException; import org.adempiere.util.MeasureInterface; import org.compiere.util.CCache; import org.compiere.util.DB; @@ -613,6 +614,9 @@ public class MMeasure extends X_PA_Measure break; } ScriptEngine engine = rule.getScriptEngine(); + if (engine == null) { + throw new AdempiereException("Engine not found: " + rule.getEngineName()); + } MRule.setContext(engine, po.getCtx(), 0); engine.put(MRule.ARGUMENTS_PREFIX + "Ctx", po.getCtx()); engine.put(MRule.ARGUMENTS_PREFIX + "PO", po); diff --git a/org.adempiere.base/src/org/compiere/model/MRule.java b/org.adempiere.base/src/org/compiere/model/MRule.java index a2489408dc..47d68c91f1 100644 --- a/org.adempiere.base/src/org/compiere/model/MRule.java +++ b/org.adempiere.base/src/org/compiere/model/MRule.java @@ -34,8 +34,6 @@ import org.compiere.util.Util; /** * Persistent Rule Model * @author Carlos Ruiz - * @author Silvano Trinchero, www.freepath.it - *
    • IDEMPIERE-3243 refactored getScriptEngine to use Core.getScriptEngine * @version $Id: MRule.java * */ @@ -196,12 +194,9 @@ public class MRule extends X_AD_Rule * @return ScriptEngine */ public ScriptEngine getScriptEngine() { - String engineName = getEngineName(); - - if(engineName != null) + if (engineName != null) engine = Core.getScriptEngine(engineName); - return engine; } diff --git a/org.adempiere.base/src/org/compiere/model/ModelValidationEngine.java b/org.adempiere.base/src/org/compiere/model/ModelValidationEngine.java index 8c22fb0bcd..de3c1e7385 100644 --- a/org.adempiere.base/src/org/compiere/model/ModelValidationEngine.java +++ b/org.adempiere.base/src/org/compiere/model/ModelValidationEngine.java @@ -35,6 +35,7 @@ import org.adempiere.base.event.IEventManager; import org.adempiere.base.event.IEventTopics; import org.adempiere.base.event.ImportEventData; import org.adempiere.base.event.LoginEventData; +import org.adempiere.exceptions.AdempiereException; import org.adempiere.model.ImportValidator; import org.adempiere.process.ImportProcess; import org.compiere.acct.Fact; @@ -241,6 +242,9 @@ public class ModelValidationEngine String error; try { ScriptEngine engine = loginRule.getScriptEngine(); + if (engine == null) { + throw new AdempiereException("Engine not found: " + loginRule.getEngineName()); + } MRule.setContext(engine, Env.getCtx(), 0); // no window // now add the method arguments to the engine @@ -378,6 +382,9 @@ public class ModelValidationEngine String error; try { ScriptEngine engine = rule.getScriptEngine(); + if (engine == null) { + throw new AdempiereException("Engine not found: " + rule.getEngineName()); + } MRule.setContext(engine, po.getCtx(), 0); // no window // now add the method arguments to the engine @@ -542,6 +549,9 @@ public class ModelValidationEngine String error; try { ScriptEngine engine = rule.getScriptEngine(); + if (engine == null) { + throw new AdempiereException("Engine not found: " + rule.getEngineName()); + } MRule.setContext(engine, po.getCtx(), 0); // no window // now add the method arguments to the engine