2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2020 Nordix Foundation.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.apex.plugins.executor.javascript;
23 import org.apache.commons.lang3.StringUtils;
24 import org.mozilla.javascript.Context;
25 import org.mozilla.javascript.Script;
26 import org.mozilla.javascript.Scriptable;
27 import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
28 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
31 * The Class JavascriptExecutor is the executor for task logic written in Javascript.
33 * @author Liam Fallon (liam.fallon@ericsson.com)
35 public class JavascriptExecutor {
36 public static final int DEFAULT_OPTIMIZATION_LEVEL = 9;
38 // Recurring string constants
39 private static final String WITH_MESSAGE = " with message: ";
41 // The key of the subject that wants to execute Javascript code
42 private final AxKey subjectKey;
44 private final Script script;
47 * Initializes the Javascript executor.
49 * @param subjectKey the key of the subject that is requesting Javascript execution
50 * @param javascriptCode the Javascript code to execute
52 public JavascriptExecutor(final AxKey subjectKey, String javascriptCode) throws StateMachineException {
53 if (StringUtils.isBlank(javascriptCode)) {
54 throw new StateMachineException("no logic specified for " + subjectKey.getId());
56 this.subjectKey = subjectKey;
57 this.script = compile(subjectKey.getId(), javascriptCode);
61 * Executes the Javascript code.
63 * @param executionContext the execution context of the subject to be passed to the Javascript context
64 * @return true if the Javascript executed properly
65 * @throws StateMachineException thrown when Javascript execution fails
67 public boolean execute(final Object executionContext) throws StateMachineException {
68 Object returnObject = null;
70 Context context = Context.enter();
72 // Pass the subject context to the Javascript engine
73 Scriptable javascriptScope = context.initStandardObjects();
74 javascriptScope.put("executor", javascriptScope, executionContext);
77 returnObject = script.exec(context, javascriptScope);
78 } catch (final Exception e) {
79 throw new StateMachineException(
80 "logic failed to run for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e);
85 if (!(returnObject instanceof Boolean)) {
86 throw new StateMachineException(
87 "execute: logic for " + subjectKey.getId() + " returned a non-boolean value " + returnObject);
90 return (boolean) returnObject;
93 private Script compile(String id, String javascriptCode) throws StateMachineException {
94 Context context = Context.enter();
96 // Set up the default values of the context
97 context.setOptimizationLevel(DEFAULT_OPTIMIZATION_LEVEL);
98 context.setLanguageVersion(Context.VERSION_1_8);
99 return context.compileString(javascriptCode, id, 1, null);
100 } catch (Exception e) {
101 throw new StateMachineException(
102 "logic failed to compile for " + id + WITH_MESSAGE + e.getMessage(), e);