summaryrefslogtreecommitdiffstats
path: root/plugins/plugins-executor/plugins-executor-javascript/src/main
diff options
context:
space:
mode:
authorliamfallon <liam.fallon@est.tech>2020-02-28 16:54:48 +0000
committerliamfallon <liam.fallon@est.tech>2020-03-01 15:37:44 +0000
commit1b43df37f166ce758ad22cef567fe120ad853705 (patch)
tree70adaec671f8257c4342aa6a2abc8deebc9525a3 /plugins/plugins-executor/plugins-executor-javascript/src/main
parentd1a3d4f7fc8f754937f10e320389825316662b2d (diff)
Switch apex to Graal javascript engine
This is the main review to switch out the Nashorn Javascript interpreter and switch in the Graal javascript interpreter for apex Javascript tasks. The Graal Javascript dialect differs slightly from Nashorn in the way it accesses information passed over from the Java world so Javascript tasks need to be converted. Subsequent reviews will convert the JUnit tests marked @Ignore in previous reviews to this one and will convert the Javascript tasks into a format Graal can handle. Subsequent reviews will also convert the examples over to Graal format. Issue-ID: POLICY-2106 Change-Id: Ief582a36539e8a87724c17fb7e56864d5e471c07 Signed-off-by: liamfallon <liam.fallon@est.tech>
Diffstat (limited to 'plugins/plugins-executor/plugins-executor-javascript/src/main')
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java108
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java45
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java51
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java56
4 files changed, 132 insertions, 128 deletions
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java
new file mode 100644
index 000000000..93f6216fc
--- /dev/null
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.plugins.executor.javascript;
+
+import org.graalvm.polyglot.Context;
+import org.graalvm.polyglot.HostAccess;
+import org.graalvm.polyglot.Value;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+
+/**
+ * The Class JavascriptExecutor is the executor for task logic written in Javascript.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class JavascriptExecutor {
+ // The key of the subject that wants to execute Javascript code
+ final AxKey subjectKey;
+
+ // The Javascript context
+ private final Context jsContext;
+
+ /**
+ * Prepares the executor for processing.
+ *
+ * @param subjectKey the key of the subject that is requesting Javascript execution
+ * @throws StateMachineException thrown when instantiation of the executor fails
+ */
+ public JavascriptExecutor(final AxKey subjectKey) throws StateMachineException {
+ this.subjectKey = subjectKey;
+
+ // @formatter:off
+ jsContext =
+ Context.newBuilder("js")
+ .allowHostClassLookup(s -> true)
+ .allowHostAccess(HostAccess.ALL)
+ .build();
+ // @formatter:on
+
+ try {
+ jsContext.getBindings("js");
+ } catch (Exception e) {
+ jsContext.close();
+ throw new StateMachineException(
+ "prepare: javascript engine failed to initialize properly for \"" + subjectKey.getId() + "\"", e);
+ }
+ }
+
+ /**
+ * Executes the the Javascript code.
+ *
+ * @param executionContext the execution context of the subject to be passed to the Javascript context
+ * @param javascriptCode the Javascript code to execute
+ * @return true if the Javascript executed properly
+ * @throws StateMachineException thrown when Javascript execution fails
+ */
+ public boolean execute(final Object executionContext, final String javascriptCode) throws StateMachineException {
+ try {
+ // Set up the Javascript engine context
+ jsContext.getBindings("js").putMember("executor", executionContext);
+ jsContext.eval("js", javascriptCode);
+
+ } catch (final Exception e) {
+ throw new StateMachineException("execute: logic failed to run for \"" + subjectKey.getId() + "\"", e);
+ }
+
+ Value returnValue = jsContext.getBindings("js").getMember("returnValue");
+
+ if (returnValue == null || returnValue.isNull()) {
+ throw new StateMachineException(
+ "execute: logic failed to set a return value for \"" + subjectKey.getId() + "\"");
+ }
+
+ return returnValue.asBoolean();
+ }
+
+ /**
+ * Cleans up the executor after processing.
+ *
+ * @throws StateMachineException thrown when cleanup of the executor fails
+ */
+ public void cleanUp() throws StateMachineException {
+ try {
+ jsContext.close();
+ } catch (final Exception e) {
+ throw new StateMachineException(
+ "cleanUp: executor cleanup failed to close for \"" + subjectKey.getId() + "\"", e);
+ }
+ }
+}
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java
index cd660c807..18a6ef58a 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java
@@ -1,7 +1,7 @@
/*-
* ============LICENSE_START=======================================================
* Copyright (C) 2016-2018 Ericsson. All rights reserved.
- * Modifications Copyright (C) 2019 Nordix Foundation.
+ * Modifications Copyright (C) 2019-2020 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,11 +24,6 @@ package org.onap.policy.apex.plugins.executor.javascript;
import java.util.Map;
import java.util.Properties;
-import javax.script.Compilable;
-import javax.script.CompiledScript;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
import org.onap.policy.apex.context.ContextException;
import org.onap.policy.apex.core.engine.executor.StateFinalizerExecutor;
import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
@@ -45,9 +40,7 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor {
// Logger for this class
private static final XLogger LOGGER = XLoggerFactory.getXLogger(JavascriptStateFinalizerExecutor.class);
- // Javascript engine
- private ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
- private CompiledScript compiled = null;
+ private JavascriptExecutor javascriptExecutor;
/**
* Prepares the state finalizer for processing.
@@ -58,14 +51,8 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor {
public void prepare() throws StateMachineException {
// Call generic prepare logic
super.prepare();
- try {
- compiled = ((Compilable) engine).compile(getSubject().getLogic());
- } catch (final ScriptException e) {
- LOGGER.error("execute: state finalizer logic failed to compile for state finalizer \""
- + getSubject().getKey().getId() + "\"");
- throw new StateMachineException("state finalizer logic failed to compile for state finalizer \""
- + getSubject().getKey().getId() + "\"", e);
- }
+
+ javascriptExecutor = new JavascriptExecutor(getSubject().getKey());
}
/**
@@ -84,25 +71,8 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor {
// Do execution pre work
executePre(executionId, executionProperties, incomingFields);
- // Set up the Javascript engine
- engine.put("executor", getExecutionContext());
-
- // Check and execute the Javascript logic
- try {
- if (compiled == null) {
- engine.eval(getSubject().getLogic());
- } else {
- compiled.eval(engine.getContext());
- }
- } catch (final ScriptException e) {
- LOGGER.error("execute: state finalizer logic failed to run for state finalizer \""
- + getSubject().getKey().getId() + "\"");
- throw new StateMachineException("state finalizer logic failed to run for state finalizer \""
- + getSubject().getKey().getId() + "\"", e);
- }
-
- // Do the execution post work
- executePost((boolean) engine.get("returnValue"));
+ // Execute the Javascript and do post processing
+ executePost(javascriptExecutor.execute(getExecutionContext(), getSubject().getLogic()));
return getOutgoing();
}
@@ -116,6 +86,7 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor {
public void cleanUp() throws StateMachineException {
LOGGER.debug("cleanUp:" + getSubject().getKey().getId() + "," + getSubject().getLogicFlavour() + ","
+ getSubject().getLogic());
- engine = null;
+
+ javascriptExecutor.cleanUp();
}
}
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java
index 9769f42db..29fae193e 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java
@@ -1,7 +1,7 @@
/*-
* ============LICENSE_START=======================================================
* Copyright (C) 2016-2018 Ericsson. All rights reserved.
- * Modifications Copyright (C) 2019 Nordix Foundation.
+ * Modifications Copyright (C) 2019-2020 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,11 +24,6 @@ package org.onap.policy.apex.plugins.executor.javascript;
import java.util.Map;
import java.util.Properties;
-import javax.script.Compilable;
-import javax.script.CompiledScript;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
import org.onap.policy.apex.context.ContextException;
import org.onap.policy.apex.core.engine.executor.TaskExecutor;
import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
@@ -45,9 +40,7 @@ public class JavascriptTaskExecutor extends TaskExecutor {
// Logger for this class
private static final XLogger LOGGER = XLoggerFactory.getXLogger(JavascriptTaskExecutor.class);
- // Javascript engine
- private ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
- private CompiledScript compiled = null;
+ private JavascriptExecutor javascriptExecutor;
/**
* Prepares the task for processing.
@@ -58,13 +51,8 @@ public class JavascriptTaskExecutor extends TaskExecutor {
public void prepare() throws StateMachineException {
// Call generic prepare logic
super.prepare();
- try {
- compiled = ((Compilable) engine).compile(getSubject().getTaskLogic().getLogic());
- } catch (final ScriptException e) {
- LOGGER.error("execute: task logic failed to compile for task \"" + getSubject().getKey().getId() + "\"");
- throw new StateMachineException(
- "task logic failed to compile for task \"" + getSubject().getKey().getId() + "\"", e);
- }
+
+ javascriptExecutor = new JavascriptExecutor(getSubject().getKey());
}
/**
@@ -83,32 +71,8 @@ public class JavascriptTaskExecutor extends TaskExecutor {
// Do execution pre work
executePre(executionId, executionProperties, incomingFields);
- // Set up the Javascript engine
- engine.put("executor", getExecutionContext());
-
- // Check and execute the Javascript logic
- try {
- if (compiled == null) {
- engine.eval(getSubject().getTaskLogic().getLogic());
- } else {
- compiled.eval(engine.getContext());
- }
- } catch (final ScriptException e) {
- LOGGER.error("execute: task logic failed to run for task \"" + getSubject().getKey().getId() + "\"");
- throw new StateMachineException(
- "task logic failed to run for task \"" + getSubject().getKey().getId() + "\"", e);
- }
-
- final Object ret = engine.get("returnValue");
- if (ret == null) {
- LOGGER.error("execute: task logic failed to set a return value for task \"" + getSubject().getKey().getId()
- + "\"");
- throw new StateMachineException("execute: task logic failed to set a return value for task \""
- + getSubject().getKey().getId() + "\"");
- }
-
- // Do the execution post work
- executePost((Boolean) ret);
+ // Execute the Javascript and do post processing
+ executePost(javascriptExecutor.execute(getExecutionContext(), getSubject().getTaskLogic().getLogic()));
return getOutgoing();
}
@@ -122,6 +86,7 @@ public class JavascriptTaskExecutor extends TaskExecutor {
public void cleanUp() throws StateMachineException {
LOGGER.debug("cleanUp:" + getSubject().getKey().getId() + "," + getSubject().getTaskLogic().getLogicFlavour()
+ "," + getSubject().getTaskLogic().getLogic());
- engine = null;
+
+ javascriptExecutor.cleanUp();
}
}
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java
index afc7d0183..41585fbd0 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java
@@ -1,7 +1,7 @@
/*-
* ============LICENSE_START=======================================================
* Copyright (C) 2016-2018 Ericsson. All rights reserved.
- * Modifications Copyright (C) 2019 Nordix Foundation.
+ * Modifications Copyright (C) 2019-2020 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,11 +23,6 @@ package org.onap.policy.apex.plugins.executor.javascript;
import java.util.Properties;
-import javax.script.Compilable;
-import javax.script.CompiledScript;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
import org.onap.policy.apex.context.ContextException;
import org.onap.policy.apex.core.engine.event.EnEvent;
import org.onap.policy.apex.core.engine.executor.TaskSelectExecutor;
@@ -46,16 +41,10 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor {
// Logger for this class
private static final XLogger LOGGER = XLoggerFactory.getXLogger(JavascriptTaskSelectExecutor.class);
- // Recurring string constants
- private static final String TSL_FAILED_PREFIX =
- "execute: task selection logic failed to set a return value for state \"";
-
- // Javascript engine
- private ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
- private CompiledScript compiled = null;
+ private JavascriptExecutor javascriptExecutor;
/**
- * Prepares the task for processing.
+ * Prepares the task selection logic for processing.
*
* @throws StateMachineException thrown when a state machine execution error occurs
*/
@@ -63,15 +52,8 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor {
public void prepare() throws StateMachineException {
// Call generic prepare logic
super.prepare();
- try {
- compiled = ((Compilable) engine).compile(getSubject().getTaskSelectionLogic().getLogic());
- } catch (final ScriptException e) {
- LOGGER.error("execute: task selection logic failed to compile for state \"" + getSubject().getKey().getId()
- + "\"");
- throw new StateMachineException(
- "task selection logic failed to compile for state \"" + getSubject().getKey().getId() + "\"", e);
- }
+ javascriptExecutor = new JavascriptExecutor(getSubject().getKey());
}
/**
@@ -90,31 +72,8 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor {
// Do execution pre work
executePre(executionId, executionProperties, incomingEvent);
- // Set up the Javascript engine
- engine.put("executor", getExecutionContext());
-
- // Check and execute the Javascript logic
- try {
- if (compiled == null) {
- engine.eval(getSubject().getTaskSelectionLogic().getLogic());
- } else {
- compiled.eval(engine.getContext());
- }
- } catch (final ScriptException e) {
- LOGGER.error(
- "execute: task selection logic failed to run for state \"" + getSubject().getKey().getId() + "\"");
- throw new StateMachineException(
- "task selection logic failed to run for state \"" + getSubject().getKey().getId() + "\"", e);
- }
-
- final Object ret = engine.get("returnValue");
- if (ret == null) {
- LOGGER.error(TSL_FAILED_PREFIX + getSubject().getKey().getId() + "\"");
- throw new StateMachineException(TSL_FAILED_PREFIX + getSubject().getKey().getId() + "\"");
- }
-
- // Do the execution post work
- executePost((Boolean) ret);
+ // Execute the Javascript and do post processing
+ executePost(javascriptExecutor.execute(getExecutionContext(), getSubject().getTaskSelectionLogic().getLogic()));
return getOutgoing();
}
@@ -129,6 +88,7 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor {
LOGGER.debug("cleanUp:" + getSubject().getKey().getId() + ","
+ getSubject().getTaskSelectionLogic().getLogicFlavour() + ","
+ getSubject().getTaskSelectionLogic().getLogic());
- engine = null;
+
+ javascriptExecutor.cleanUp();
}
}