Browse Source

Minor fixes

pull/7455/head
Igor Kulikov 3 years ago
parent
commit
1898ea4a15
  1. 2
      common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractScriptInvokeService.java
  2. 14
      common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/DefaultMvelInvokeService.java
  3. 87
      common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbUtils.java
  4. 2
      pom.xml
  5. 1
      ui-ngx/src/app/shared/components/dialog/node-script-test-dialog.component.html

2
common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractScriptInvokeService.java

@ -274,7 +274,7 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService
private boolean resultSizeExceeded(String result) {
if (getMaxResultSize() <= 0) return false;
return result.length() > getMaxResultSize();
return result != null && result.length() > getMaxResultSize();
}
private <T> ListenableFuture<T> error(String message) {

14
common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/DefaultMvelInvokeService.java

@ -25,6 +25,7 @@ import lombok.extern.slf4j.Slf4j;
import org.mvel2.ExecutionContext;
import org.mvel2.MVEL;
import org.mvel2.ParserContext;
import org.mvel2.SandboxedParserConfiguration;
import org.mvel2.SandboxedParserContext;
import org.mvel2.ScriptMemoryOverflowException;
import org.mvel2.optimizers.OptimizerFactory;
@ -56,7 +57,7 @@ import java.util.regex.Pattern;
public class DefaultMvelInvokeService extends AbstractScriptInvokeService implements MvelInvokeService {
protected Map<UUID, MvelScript> scriptMap = new ConcurrentHashMap<>();
private ParserContext parserContext;
private SandboxedParserConfiguration parserConfig;
private static final Pattern NEW_KEYWORD_PATTERN = Pattern.compile("new\\s");
@ -108,8 +109,9 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
public void init() {
super.init();
OptimizerFactory.setDefaultOptimizer(OptimizerFactory.SAFE_REFLECTIVE);
parserContext = new SandboxedParserContext();
parserContext.addImport("JSON", TbJson.class);
parserConfig = new SandboxedParserConfiguration();
parserConfig.addImport("JSON", TbJson.class);
TbUtils.register(parserConfig);
executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(threadPoolSize, "mvel-executor"));
}
@ -144,7 +146,7 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
}
return executor.submit(() -> {
try {
Serializable compiledScript = MVEL.compileExpression(scriptBody, parserContext);
Serializable compiledScript = MVEL.compileExpression(scriptBody, new SandboxedParserContext(parserConfig));
MvelScript script = new MvelScript(compiledScript, scriptBody, argNames);
scriptMap.put(scriptId, script);
return scriptId;
@ -163,9 +165,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(), executionContext, script.createVars(args));
return MVEL.executeTbExpression(script.getCompiledScript(), executionContext, script.createVars(args));
} catch (ScriptMemoryOverflowException e) {
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.OTHER, script.getScriptBody(), new RuntimeException("Memory error!"));
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.OTHER, script.getScriptBody(), new RuntimeException("Script memory overflow!"));
} catch (Exception e) {
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.RUNTIME, script.getScriptBody(), e);
}

87
common/script/script-api/src/main/java/org/thingsboard/script/api/mvel/TbUtils.java

@ -0,0 +1,87 @@
/**
* 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.ExecutionContext;
import org.mvel2.ParserConfiguration;
import org.mvel2.execution.ExecutionArrayList;
import org.mvel2.util.MethodStub;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.List;
public class TbUtils {
public static void register(ParserConfiguration parserConfig) throws Exception {
parserConfig.addImport("btoa", new MethodStub(TbUtils.class.getMethod("btoa",
String.class)));
parserConfig.addImport("atob", new MethodStub(TbUtils.class.getMethod("atob",
String.class)));
parserConfig.addImport("bytesToString", new MethodStub(TbUtils.class.getMethod("bytesToString",
List.class)));
parserConfig.addImport("bytesToString", new MethodStub(TbUtils.class.getMethod("bytesToString",
List.class, String.class)));
parserConfig.addImport("stringToBytes", new MethodStub(TbUtils.class.getMethod("stringToBytes",
ExecutionContext.class, String.class)));
parserConfig.addImport("stringToBytes", new MethodStub(TbUtils.class.getMethod("stringToBytes",
ExecutionContext.class, String.class, String.class)));
}
public static String btoa(String input) {
return new String(Base64.getEncoder().encode(input.getBytes()));
}
public static String atob(String encoded) {
return new String(Base64.getDecoder().decode(encoded));
}
public static String bytesToString(List<Byte> bytesList) {
byte[] bytes = bytesFromList(bytesList);
return new String(bytes);
}
public static String bytesToString(List<Byte> bytesList, String charsetName) throws UnsupportedEncodingException {
byte[] bytes = bytesFromList(bytesList);
return new String(bytes, charsetName);
}
public static List<Byte> stringToBytes(ExecutionContext ctx, String str) {
byte[] bytes = str.getBytes();
return bytesToList(ctx, bytes);
}
public static List<Byte> stringToBytes(ExecutionContext ctx, String str, String charsetName) throws UnsupportedEncodingException {
byte[] bytes = str.getBytes(charsetName);
return bytesToList(ctx, bytes);
}
private static byte[] bytesFromList(List<Byte> bytesList) {
byte[] bytes = new byte[bytesList.size()];
for (int i = 0; i < bytesList.size(); i++) {
bytes[i] = bytesList.get(i);
}
return bytes;
}
private static List<Byte> bytesToList(ExecutionContext ctx, byte[] bytes) {
List<Byte> list = new ExecutionArrayList<>(ctx);
for (int i = 0; i < bytes.length; i++) {
list.add(bytes[i]);
}
return list;
}
}

2
pom.xml

@ -77,7 +77,7 @@
<zookeeper.version>3.5.5</zookeeper.version>
<protobuf.version>3.17.2</protobuf.version>
<grpc.version>1.42.1</grpc.version>
<mvel.version>2.4.16TB</mvel.version>
<mvel.version>2.4.19TB</mvel.version>
<lombok.version>1.18.18</lombok.version>
<paho.client.version>1.2.4</paho.client.version>
<netty.version>4.1.75.Final</netty.version>

1
ui-ngx/src/app/shared/components/dialog/node-script-test-dialog.component.html

@ -77,6 +77,7 @@
functionName="{{ data.functionName }}"
[functionArgs]="data.argNames"
[validationArgs]="[data.msg, data.metadata, data.msgType]"
[disableUndefinedCheck]="scriptLang === scriptLanguage.MVEL"
resultType="object"
[helpId]="data.helpId"
[fillHeight]="true">

Loading…
Cancel
Save