diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml
index 7fcb9ce3b1..62dc00ca97 100644
--- a/common/script/script-api/pom.xml
+++ b/common/script/script-api/pom.xml
@@ -85,7 +85,7 @@
commons-lang3
- org.mvel
+ org.thingsboard
mvel2
diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/DefaultMvelInvokeService.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/DefaultMvelInvokeService.java
index 06f225cb1d..706ef2ed46 100644
--- a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/DefaultMvelInvokeService.java
+++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/DefaultMvelInvokeService.java
@@ -22,15 +22,15 @@ import com.google.common.util.concurrent.MoreExecutors;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
+import org.mvel2.ExecutionContext;
import org.mvel2.MVEL;
import org.mvel2.ParserContext;
-import org.mvel2.optimizers.AccessorOptimizer;
+import org.mvel2.SandboxedParserContext;
import org.mvel2.optimizers.OptimizerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
-import org.springframework.util.ReflectionUtils;
import org.thingsboard.common.util.ThingsBoardExecutors;
import org.thingsboard.script.api.AbstractScriptInvokeService;
import org.thingsboard.script.api.ScriptType;
@@ -101,12 +101,9 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
@PostConstruct
public void init() {
super.init();
- Field field = ReflectionUtils.findField(OptimizerFactory.class, "accessorCompilers");
- ReflectionUtils.makeAccessible(field);
- Map accessorCompilers = (Map) field.get(null);
- accessorCompilers.put(OptimizerFactory.SAFE_REFLECTIVE, new TbReflectiveAccessorOptimizer());
-
- parserContext = new ParserContext(new TbMvelParserConfiguration());
+ OptimizerFactory.setDefaultOptimizer(OptimizerFactory.SAFE_REFLECTIVE);
+ parserContext = new SandboxedParserContext();
+ parserContext.addImport("JSON", TbJson.class);
executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(2, "mvel-executor"));
}
@@ -159,7 +156,9 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.OTHER, null, new RuntimeException("Script not found!"));
}
try {
- return MVEL.executeExpression(script.getCompiledScript(), script.createVars(args));
+ ExecutionContext executionContext = new ExecutionContext();
+ // TODO:
+ return MVEL.executeExpression(script.getCompiledScript(), executionContext, script.createVars(args));
} catch (OutOfMemoryError e) {
Runtime.getRuntime().gc();
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.OTHER, script.getScriptBody(), new RuntimeException("Memory error!"));
diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbJson.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbJson.java
index c9baba5322..18f3abb4df 100644
--- a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbJson.java
+++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbJson.java
@@ -16,6 +16,8 @@
package org.thingsboard.script.api.mvel;
import com.fasterxml.jackson.databind.JsonNode;
+import org.mvel2.ExecutionContext;
+import org.mvel2.util.ArgsRepackUtil;
import org.thingsboard.common.util.JacksonUtil;
import java.io.IOException;
@@ -28,13 +30,13 @@ public class TbJson {
return value != null ? JacksonUtil.toString(value) : "null";
}
- public static Object parse(String value) throws IOException {
+ public static Object parse(ExecutionContext ctx, String value) throws IOException {
if (value != null) {
JsonNode node = JacksonUtil.toJsonNode(value);
if (node.isObject()) {
- return JacksonUtil.convertValue(node, Map.class);
+ return ArgsRepackUtil.repack(ctx, JacksonUtil.convertValue(node, Map.class));
} else if (node.isArray()) {
- return JacksonUtil.convertValue(node, List.class);
+ return ArgsRepackUtil.repack(ctx, JacksonUtil.convertValue(node, List.class));
} else if (node.isDouble()) {
return node.doubleValue();
} else if (node.isLong()) {
diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMapCreator.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMapCreator.java
deleted file mode 100644
index 7b00cbbc4f..0000000000
--- a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMapCreator.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Copyright © 2016-2022 The Thingsboard Authors
- *
- * 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.thingsboard.script.api.mvel;
-
-import org.mvel2.compiler.Accessor;
-import org.mvel2.compiler.ExecutableAccessor;
-import org.mvel2.compiler.ExecutableStatement;
-import org.mvel2.integration.VariableResolverFactory;
-import org.mvel2.optimizers.impl.refl.collection.ExprValueAccessor;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class TbMapCreator implements Accessor {
- private Accessor[] keys;
- private Accessor[] vals;
- private int size;
-
- public Object getValue(Object ctx, Object elCtx, VariableResolverFactory variableFactory) {
- Map map = new HashMap<>(size * 2);
- for (int i = size - 1; i != -1; i--) {
- //noinspection unchecked
- map.put(getKey(i, ctx, elCtx, variableFactory), vals[i].getValue(ctx, elCtx, variableFactory));
- }
- return map;
- }
-
- private Object getKey(int index, Object ctx, Object elCtx, VariableResolverFactory variableFactory) {
- Accessor keyAccessor = keys[index];
- if (keyAccessor instanceof ExprValueAccessor) {
- ExecutableStatement executableStatement = ((ExprValueAccessor) keyAccessor).stmt;
- if (executableStatement instanceof ExecutableAccessor) {
- return ((ExecutableAccessor) executableStatement).getNode().getName();
- }
- }
- return keys[index].getValue(ctx, elCtx, variableFactory);
- }
-
- public TbMapCreator(Accessor[] keys, Accessor[] vals) {
- this.size = (this.keys = keys).length;
- this.vals = vals;
- }
-
- public Object setValue(Object ctx, Object elCtx, VariableResolverFactory variableFactory, Object value) {
- // not implemented
- return null;
- }
-
- public Class getKnownEgressType() {
- return Map.class;
- }
-}
diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMvelClassLoader.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMvelClassLoader.java
deleted file mode 100644
index 40f3bf70e2..0000000000
--- a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMvelClassLoader.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * Copyright © 2016-2022 The Thingsboard Authors
- *
- * 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.thingsboard.script.api.mvel;
-
-import org.mvel2.compiler.AbstractParser;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.HashSet;
-import java.util.Set;
-
-public class TbMvelClassLoader extends URLClassLoader {
-
- private static final Set allowedClasses = new HashSet<>();
- private static final Set allowedPackages = new HashSet<>();
-
- static {
-
- AbstractParser.LITERALS.remove("System");
- AbstractParser.LITERALS.remove("Runtime");
- AbstractParser.LITERALS.remove("Class");
- AbstractParser.LITERALS.remove("ClassLoader");
- AbstractParser.LITERALS.remove("Thread");
- AbstractParser.LITERALS.remove("Compiler");
- AbstractParser.LITERALS.remove("ThreadLocal");
- AbstractParser.LITERALS.remove("SecurityManager");
-
- AbstractParser.CLASS_LITERALS.remove("System");
- AbstractParser.CLASS_LITERALS.remove("Runtime");
- AbstractParser.CLASS_LITERALS.remove("Class");
- AbstractParser.CLASS_LITERALS.remove("ClassLoader");
- AbstractParser.CLASS_LITERALS.remove("Thread");
- AbstractParser.CLASS_LITERALS.remove("Compiler");
- AbstractParser.CLASS_LITERALS.remove("ThreadLocal");
- AbstractParser.CLASS_LITERALS.remove("SecurityManager");
- AbstractParser.CLASS_LITERALS.put("JSON", TbJson.class);
- AbstractParser.LITERALS.put("JSON", TbJson.class);
-
- AbstractParser.CLASS_LITERALS.values().forEach(val -> allowedClasses.add(((Class) val).getName()));
- }
-
- static {
- allowedPackages.add("org.mvel2");
- allowedPackages.add("java.util");
- }
-
- public TbMvelClassLoader() {
- super(new URL[0], Thread.currentThread().getContextClassLoader());
- }
-
- @Override
- protected Class> loadClass(String name, boolean resolve) throws ClassNotFoundException {
- if (!classNameAllowed(name)) {
- throw new ClassNotFoundException();
- }
- return super.loadClass(name, resolve);
- }
-
- @Override
- public Class> loadClass(String name) throws ClassNotFoundException {
- if (!classNameAllowed(name)) {
- throw new ClassNotFoundException();
- }
- return super.loadClass(name);
- }
-
- private boolean classNameAllowed(String name) {
- if (allowedClasses.contains(name)) {
- return true;
- }
- for (String pkgName : allowedPackages) {
- if (name.startsWith(pkgName)) {
- return true;
- }
- }
- return false;
- }
-
-}
diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMvelParserConfiguration.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMvelParserConfiguration.java
deleted file mode 100644
index 03f6e9bea0..0000000000
--- a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMvelParserConfiguration.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Copyright © 2016-2022 The Thingsboard Authors
- *
- * 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.thingsboard.script.api.mvel;
-
-import org.mvel2.ParserConfiguration;
-import org.mvel2.integration.VariableResolverFactory;
-
-public class TbMvelParserConfiguration extends ParserConfiguration {
-
- private static final long serialVersionUID = 5558151976348875590L;
-
- TbMvelParserConfiguration() {
- setClassLoader(new TbMvelClassLoader());
- }
-
- @Override
- public VariableResolverFactory getVariableFactory(VariableResolverFactory factory) {
- if (Thread.interrupted()) {
- throw new RuntimeException("Thread is interrupted!");
- }
- return new TbMvelResolverFactory(factory);
- }
-
-}
diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMvelResolverFactory.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMvelResolverFactory.java
deleted file mode 100644
index 2715057b3a..0000000000
--- a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbMvelResolverFactory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright © 2016-2022 The Thingsboard Authors
- *
- * 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.thingsboard.script.api.mvel;
-
-import org.mvel2.integration.VariableResolver;
-import org.mvel2.integration.VariableResolverFactory;
-import org.mvel2.integration.impl.StackResetResolverFactory;
-
-public class TbMvelResolverFactory extends StackResetResolverFactory {
-
- public TbMvelResolverFactory(VariableResolverFactory delegate) {
- super(delegate);
- }
-
- @Override
- public VariableResolver getVariableResolver(String name) {
- if (Thread.interrupted()) {
- throw new RuntimeException("Thread is interrupted!");
- }
- return super.getVariableResolver(name);
- }
-}
diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbReflectiveAccessorOptimizer.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbReflectiveAccessorOptimizer.java
deleted file mode 100644
index 0fb27a27fa..0000000000
--- a/common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbReflectiveAccessorOptimizer.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * Copyright © 2016-2022 The Thingsboard Authors
- *
- * 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.thingsboard.script.api.mvel;
-
-import org.mvel2.ParserContext;
-import org.mvel2.compiler.Accessor;
-import org.mvel2.integration.VariableResolverFactory;
-import org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer;
-import org.mvel2.optimizers.impl.refl.collection.ArrayCreator;
-import org.mvel2.optimizers.impl.refl.collection.ExprValueAccessor;
-import org.mvel2.optimizers.impl.refl.collection.ListCreator;
-import org.mvel2.optimizers.impl.refl.nodes.Union;
-
-import java.util.List;
-import java.util.Map;
-
-import static org.mvel2.util.CompilerTools.expectType;
-import static org.mvel2.util.ParseTools.findClass;
-import static org.mvel2.util.ParseTools.getBaseComponentType;
-import static org.mvel2.util.ParseTools.getSubComponentType;
-import static org.mvel2.util.ParseTools.repeatChar;
-
-public class TbReflectiveAccessorOptimizer extends ReflectiveAccessorOptimizer {
- private Object ctx;
- private Class returnType;
- private VariableResolverFactory variableFactory;
-
- @Override
- public Accessor optimizeCollection(ParserContext pCtx, Object o, Class type, char[] property, int start, int offset,
- Object ctx, Object thisRef, VariableResolverFactory factory) {
- this.start = this.cursor = start;
- this.length = start + offset;
- this.returnType = type;
- this.ctx = ctx;
- this.variableFactory = factory;
- this.pCtx = pCtx;
-
- Accessor root = _getAccessor(o, returnType);
-
- if (property != null && length > start) {
- return new Union(pCtx, root, property, cursor, offset);
- } else {
- return root;
- }
- }
-
- private Accessor _getAccessor(Object o, Class type) {
- if (o instanceof List) {
- Accessor[] a = new Accessor[((List) o).size()];
- int i = 0;
-
- for (Object item : (List) o) {
- a[i++] = _getAccessor(item, type);
- }
-
- returnType = List.class;
-
- return new ListCreator(a);
- } else if (o instanceof Map) {
- Accessor[] k = new Accessor[((Map) o).size()];
- Accessor[] v = new Accessor[k.length];
- int i = 0;
-
- for (Object item : ((Map) o).keySet()) {
- k[i] = _getAccessor(item, type); // key
- v[i++] = _getAccessor(((Map) o).get(item), type); // value
- }
-
- returnType = Map.class;
-
- return new TbMapCreator(k, v);
- } else if (o instanceof Object[]) {
- Accessor[] a = new Accessor[((Object[]) o).length];
- int i = 0;
- int dim = 0;
-
- if (type != null) {
- String nm = type.getName();
- while (nm.charAt(dim) == '[') dim++;
- } else {
- type = Object[].class;
- dim = 1;
- }
-
- try {
- Class base = getBaseComponentType(type);
- Class cls = dim > 1 ? findClass(null, repeatChar('[', dim - 1) + "L" + base.getName() + ";", pCtx)
- : type;
-
- for (Object item : (Object[]) o) {
- expectType(pCtx, a[i++] = _getAccessor(item, cls), base, true);
- }
-
- return new ArrayCreator(a, getSubComponentType(type));
- } catch (ClassNotFoundException e) {
- throw new RuntimeException("this error should never throw:" + getBaseComponentType(type).getName(), e);
- }
- } else {
- if (returnType == null) returnType = Object.class;
- if (type.isArray()) {
- return new ExprValueAccessor((String) o, type, ctx, variableFactory, pCtx);
- } else {
- return new ExprValueAccessor((String) o, Object.class, ctx, variableFactory, pCtx);
- }
- }
- }
-}
diff --git a/pom.xml b/pom.xml
index c56316f44c..9589570026 100755
--- a/pom.xml
+++ b/pom.xml
@@ -77,7 +77,7 @@
3.5.5
3.17.2
1.42.1
- 2.4.14.Final
+ 2.4.16TB
1.18.18
1.2.4
4.1.75.Final
@@ -1575,7 +1575,7 @@
${grpc.version}
- org.mvel
+ org.thingsboard
mvel2
${mvel.version}