Refactor MVEL -> TBEL
This commit is contained in:
		
							parent
							
								
									d8f87c45c8
								
							
						
					
					
						commit
						d10f64c348
					
				@ -57,9 +57,9 @@
 | 
			
		||||
        "name": "Log RPC from Device",
 | 
			
		||||
        "debugMode": false,
 | 
			
		||||
        "configuration": {
 | 
			
		||||
          "scriptLang": "MVEL",
 | 
			
		||||
          "scriptLang": "TBEL",
 | 
			
		||||
          "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
 | 
			
		||||
          "mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
          "tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
@ -71,9 +71,9 @@
 | 
			
		||||
        "name": "Log Other",
 | 
			
		||||
        "debugMode": false,
 | 
			
		||||
        "configuration": {
 | 
			
		||||
          "scriptLang": "MVEL",
 | 
			
		||||
          "scriptLang": "TBEL",
 | 
			
		||||
          "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
 | 
			
		||||
          "mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
          "tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
 | 
			
		||||
@ -70,9 +70,9 @@
 | 
			
		||||
        "name": "Log RPC from Device",
 | 
			
		||||
        "debugMode": false,
 | 
			
		||||
        "configuration": {
 | 
			
		||||
          "scriptLang": "MVEL",
 | 
			
		||||
          "scriptLang": "TBEL",
 | 
			
		||||
          "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
 | 
			
		||||
          "mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
          "tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
@ -84,9 +84,9 @@
 | 
			
		||||
        "name": "Log Other",
 | 
			
		||||
        "debugMode": false,
 | 
			
		||||
        "configuration": {
 | 
			
		||||
          "scriptLang": "MVEL",
 | 
			
		||||
          "scriptLang": "TBEL",
 | 
			
		||||
          "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
 | 
			
		||||
          "mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
          "tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
 | 
			
		||||
@ -57,9 +57,9 @@
 | 
			
		||||
        "name": "Log RPC from Device",
 | 
			
		||||
        "debugMode": false,
 | 
			
		||||
        "configuration": {
 | 
			
		||||
          "scriptLang": "MVEL",
 | 
			
		||||
          "scriptLang": "TBEL",
 | 
			
		||||
          "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
 | 
			
		||||
          "mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
          "tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
@ -71,9 +71,9 @@
 | 
			
		||||
        "name": "Log Other",
 | 
			
		||||
        "debugMode": false,
 | 
			
		||||
        "configuration": {
 | 
			
		||||
          "scriptLang": "MVEL",
 | 
			
		||||
          "scriptLang": "TBEL",
 | 
			
		||||
          "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
 | 
			
		||||
          "mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
          "tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ import org.thingsboard.rule.engine.api.MailService;
 | 
			
		||||
import org.thingsboard.rule.engine.api.SmsService;
 | 
			
		||||
import org.thingsboard.rule.engine.api.sms.SmsSenderFactory;
 | 
			
		||||
import org.thingsboard.script.api.js.JsInvokeService;
 | 
			
		||||
import org.thingsboard.script.api.mvel.MvelInvokeService;
 | 
			
		||||
import org.thingsboard.script.api.tbel.TbelInvokeService;
 | 
			
		||||
import org.thingsboard.server.actors.service.ActorService;
 | 
			
		||||
import org.thingsboard.server.actors.tenant.DebugTbRateLimits;
 | 
			
		||||
import org.thingsboard.server.cluster.TbClusterService;
 | 
			
		||||
@ -274,7 +274,7 @@ public class ActorSystemContext {
 | 
			
		||||
 | 
			
		||||
    @Autowired(required = false)
 | 
			
		||||
    @Getter
 | 
			
		||||
    private MvelInvokeService mvelInvokeService;
 | 
			
		||||
    private TbelInvokeService tbelInvokeService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    @Getter
 | 
			
		||||
 | 
			
		||||
@ -97,7 +97,7 @@ import org.thingsboard.server.gen.transport.TransportProtos;
 | 
			
		||||
import org.thingsboard.server.queue.TbQueueCallback;
 | 
			
		||||
import org.thingsboard.server.queue.TbQueueMsgMetadata;
 | 
			
		||||
import org.thingsboard.server.service.script.RuleNodeJsScriptEngine;
 | 
			
		||||
import org.thingsboard.server.service.script.RuleNodeMvelScriptEngine;
 | 
			
		||||
import org.thingsboard.server.service.script.RuleNodeTbelScriptEngine;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@ -474,11 +474,11 @@ class DefaultTbContext implements TbContext {
 | 
			
		||||
        return new RuleNodeJsScriptEngine(getTenantId(), mainCtx.getJsInvokeService(), script, argNames);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ScriptEngine createMvelScriptEngine(String script, String... argNames) {
 | 
			
		||||
        if (mainCtx.getMvelInvokeService() == null) {
 | 
			
		||||
            throw new RuntimeException("MVEL execution is disabled!");
 | 
			
		||||
    private ScriptEngine createTbelScriptEngine(String script, String... argNames) {
 | 
			
		||||
        if (mainCtx.getTbelInvokeService() == null) {
 | 
			
		||||
            throw new RuntimeException("TBEL execution is disabled!");
 | 
			
		||||
        }
 | 
			
		||||
        return new RuleNodeMvelScriptEngine(getTenantId(), mainCtx.getMvelInvokeService(), script, argNames);
 | 
			
		||||
        return new RuleNodeTbelScriptEngine(getTenantId(), mainCtx.getTbelInvokeService(), script, argNames);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@ -492,11 +492,11 @@ class DefaultTbContext implements TbContext {
 | 
			
		||||
        switch (scriptLang) {
 | 
			
		||||
            case JS:
 | 
			
		||||
                return createJsScriptEngine(script, argNames);
 | 
			
		||||
            case MVEL:
 | 
			
		||||
            case TBEL:
 | 
			
		||||
                if (Arrays.isNullOrEmpty(argNames)) {
 | 
			
		||||
                    return createMvelScriptEngine(script, "msg", "metadata", "msgType");
 | 
			
		||||
                    return createTbelScriptEngine(script, "msg", "metadata", "msgType");
 | 
			
		||||
                } else {
 | 
			
		||||
                    return createMvelScriptEngine(script, argNames);
 | 
			
		||||
                    return createTbelScriptEngine(script, argNames);
 | 
			
		||||
                }
 | 
			
		||||
            default:
 | 
			
		||||
                throw new RuntimeException("Unsupported script language: " + scriptLang.name());
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.thingsboard.rule.engine.api.ScriptEngine;
 | 
			
		||||
import org.thingsboard.script.api.js.JsInvokeService;
 | 
			
		||||
import org.thingsboard.script.api.mvel.MvelInvokeService;
 | 
			
		||||
import org.thingsboard.script.api.tbel.TbelInvokeService;
 | 
			
		||||
import org.thingsboard.server.actors.ActorSystemContext;
 | 
			
		||||
import org.thingsboard.server.actors.tenant.DebugTbRateLimits;
 | 
			
		||||
import org.thingsboard.server.common.data.EventInfo;
 | 
			
		||||
@ -69,7 +69,7 @@ import org.thingsboard.server.dao.event.EventService;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
import org.thingsboard.server.service.rule.TbRuleChainService;
 | 
			
		||||
import org.thingsboard.server.service.script.RuleNodeJsScriptEngine;
 | 
			
		||||
import org.thingsboard.server.service.script.RuleNodeMvelScriptEngine;
 | 
			
		||||
import org.thingsboard.server.service.script.RuleNodeTbelScriptEngine;
 | 
			
		||||
import org.thingsboard.server.service.security.permission.Operation;
 | 
			
		||||
import org.thingsboard.server.service.security.permission.Resource;
 | 
			
		||||
 | 
			
		||||
@ -146,7 +146,7 @@ public class RuleChainController extends BaseController {
 | 
			
		||||
    private JsInvokeService jsInvokeService;
 | 
			
		||||
 | 
			
		||||
    @Autowired(required = false)
 | 
			
		||||
    private MvelInvokeService mvelInvokeService;
 | 
			
		||||
    private TbelInvokeService tbelInvokeService;
 | 
			
		||||
 | 
			
		||||
    @Autowired(required = false)
 | 
			
		||||
    private ActorSystemContext actorContext;
 | 
			
		||||
@ -154,8 +154,8 @@ public class RuleChainController extends BaseController {
 | 
			
		||||
    @Value("${actors.rule.chain.debug_mode_rate_limits_per_tenant.enabled}")
 | 
			
		||||
    private boolean debugPerTenantEnabled;
 | 
			
		||||
 | 
			
		||||
    @Value("${mvel.enabled:true}")
 | 
			
		||||
    private boolean mvelEnabled;
 | 
			
		||||
    @Value("${tbel.enabled:true}")
 | 
			
		||||
    private boolean tbelEnabled;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get Rule Chain (getRuleChainById)",
 | 
			
		||||
            notes = "Fetch the Rule Chain object based on the provided Rule Chain Id. " + RULE_CHAIN_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
@ -378,13 +378,13 @@ public class RuleChainController extends BaseController {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Is MVEL script executor enabled",
 | 
			
		||||
            notes = "Returns 'True' if the MVEL script execution is enabled" + TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @ApiOperation(value = "Is TBEL script executor enabled",
 | 
			
		||||
            notes = "Returns 'True' if the TBEL script execution is enabled" + TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @PreAuthorize("hasAuthority('TENANT_ADMIN')")
 | 
			
		||||
    @RequestMapping(value = "/ruleChain/mvelEnabled", method = RequestMethod.GET)
 | 
			
		||||
    @RequestMapping(value = "/ruleChain/tbelEnabled", method = RequestMethod.GET)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public Boolean isMvelEnabled() {
 | 
			
		||||
        return mvelEnabled;
 | 
			
		||||
    public Boolean isTbelEnabled() {
 | 
			
		||||
        return tbelEnabled;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Test Script function",
 | 
			
		||||
@ -393,7 +393,7 @@ public class RuleChainController extends BaseController {
 | 
			
		||||
    @RequestMapping(value = "/ruleChain/testScript", method = RequestMethod.POST)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public JsonNode testScript(
 | 
			
		||||
            @ApiParam(value = "Script language: JS or MVEL")
 | 
			
		||||
            @ApiParam(value = "Script language: JS or TBEL")
 | 
			
		||||
            @RequestParam(required = false) ScriptLanguage scriptLang,
 | 
			
		||||
            @ApiParam(value = "Test JS request. See API call description above.")
 | 
			
		||||
            @RequestBody JsonNode inputParams) throws ThingsboardException {
 | 
			
		||||
@ -418,10 +418,10 @@ public class RuleChainController extends BaseController {
 | 
			
		||||
                if (ScriptLanguage.JS.equals(scriptLang)) {
 | 
			
		||||
                    engine = new RuleNodeJsScriptEngine(getTenantId(), jsInvokeService, script, argNames);
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (mvelInvokeService == null) {
 | 
			
		||||
                        throw new IllegalArgumentException("MVEL script engine is disabled!");
 | 
			
		||||
                    if (tbelInvokeService == null) {
 | 
			
		||||
                        throw new IllegalArgumentException("TBEL script engine is disabled!");
 | 
			
		||||
                    }
 | 
			
		||||
                    engine = new RuleNodeMvelScriptEngine(getTenantId(), mvelInvokeService, script, argNames);
 | 
			
		||||
                    engine = new RuleNodeTbelScriptEngine(getTenantId(), tbelInvokeService, script, argNames);
 | 
			
		||||
                }
 | 
			
		||||
                TbMsg inMsg = TbMsg.newMsg(msgType, null, new TbMsgMetaData(metadata), TbMsgDataType.JSON, data);
 | 
			
		||||
                switch (scriptType) {
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ import com.google.common.util.concurrent.MoreExecutors;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.script.api.RuleNodeScriptFactory;
 | 
			
		||||
import org.thingsboard.script.api.mvel.MvelInvokeService;
 | 
			
		||||
import org.thingsboard.script.api.tbel.TbelInvokeService;
 | 
			
		||||
import org.thingsboard.server.common.data.StringUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.msg.TbMsg;
 | 
			
		||||
@ -42,9 +42,9 @@ import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class RuleNodeMvelScriptEngine extends RuleNodeScriptEngine<MvelInvokeService, Object> {
 | 
			
		||||
public class RuleNodeTbelScriptEngine extends RuleNodeScriptEngine<TbelInvokeService, Object> {
 | 
			
		||||
 | 
			
		||||
    public RuleNodeMvelScriptEngine(TenantId tenantId, MvelInvokeService scriptInvokeService, String script, String... argNames) {
 | 
			
		||||
    public RuleNodeTbelScriptEngine(TenantId tenantId, TbelInvokeService scriptInvokeService, String script, String... argNames) {
 | 
			
		||||
        super(tenantId, scriptInvokeService, script, argNames);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -611,25 +611,25 @@ state:
 | 
			
		||||
  defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:60}"
 | 
			
		||||
  persistToTelemetry: "${PERSIST_STATE_TO_TELEMETRY:false}"
 | 
			
		||||
 | 
			
		||||
mvel:
 | 
			
		||||
  enabled: "${MVEL_ENABLED:true}"
 | 
			
		||||
  max_total_args_size: "${MVEL_MAX_TOTAL_ARGS_SIZE:100000}"
 | 
			
		||||
  max_result_size: "${MVEL_MAX_RESULT_SIZE:300000}"
 | 
			
		||||
  max_script_body_size: "${MVEL_MAX_SCRIPT_BODY_SIZE:50000}"
 | 
			
		||||
  # Maximum allowed MVEL script execution memory
 | 
			
		||||
  max_memory_limit_mb: "${MVEL_MAX_MEMORY_LIMIT_MB: 8}"
 | 
			
		||||
  # Maximum allowed MVEL script execution errors before it will be blacklisted
 | 
			
		||||
  max_errors: "${MVEL_MAX_ERRORS:3}"
 | 
			
		||||
  # MVEL Eval max request timeout in milliseconds. 0 - no timeout
 | 
			
		||||
  max_requests_timeout: "${MVEL_MAX_REQUEST_TIMEOUT:500}"
 | 
			
		||||
tbel:
 | 
			
		||||
  enabled: "${TBEL_ENABLED:true}"
 | 
			
		||||
  max_total_args_size: "${TBEL_MAX_TOTAL_ARGS_SIZE:100000}"
 | 
			
		||||
  max_result_size: "${TBEL_MAX_RESULT_SIZE:300000}"
 | 
			
		||||
  max_script_body_size: "${TBEL_MAX_SCRIPT_BODY_SIZE:50000}"
 | 
			
		||||
  # Maximum allowed TBEL script execution memory
 | 
			
		||||
  max_memory_limit_mb: "${TBEL_MAX_MEMORY_LIMIT_MB: 8}"
 | 
			
		||||
  # Maximum allowed TBEL script execution errors before it will be blacklisted
 | 
			
		||||
  max_errors: "${TBEL_MAX_ERRORS:3}"
 | 
			
		||||
  # TBEL Eval max request timeout in milliseconds. 0 - no timeout
 | 
			
		||||
  max_requests_timeout: "${TBEL_MAX_REQUEST_TIMEOUT:500}"
 | 
			
		||||
  # Maximum time in seconds for black listed function to stay in the list.
 | 
			
		||||
  max_black_list_duration_sec: "${MVEL_MAX_BLACKLIST_DURATION_SEC:60}"
 | 
			
		||||
  max_black_list_duration_sec: "${TBEL_MAX_BLACKLIST_DURATION_SEC:60}"
 | 
			
		||||
  # Specify thread pool size for javascript executor service
 | 
			
		||||
  thread_pool_size: "${MVEL_THREAD_POOL_SIZE:50}"
 | 
			
		||||
  compiled_scripts_cache_size: "${MVEL_COMPILED_SCRIPTS_CACHE_SIZE:1000}"
 | 
			
		||||
  thread_pool_size: "${TBEL_THREAD_POOL_SIZE:50}"
 | 
			
		||||
  compiled_scripts_cache_size: "${TBEL_COMPILED_SCRIPTS_CACHE_SIZE:1000}"
 | 
			
		||||
  stats:
 | 
			
		||||
    enabled: "${TB_MVEL_STATS_ENABLED:false}"
 | 
			
		||||
    print_interval_ms: "${TB_MVEL_STATS_PRINT_INTERVAL_MS:10000}"
 | 
			
		||||
    enabled: "${TB_TBEL_STATS_ENABLED:false}"
 | 
			
		||||
    print_interval_ms: "${TB_TBEL_STATS_PRINT_INTERVAL_MS:10000}"
 | 
			
		||||
 | 
			
		||||
js:
 | 
			
		||||
  evaluator: "${JS_EVALUATOR:local}" # local/remote
 | 
			
		||||
 | 
			
		||||
@ -24,8 +24,8 @@ import org.springframework.beans.factory.annotation.Value;
 | 
			
		||||
import org.springframework.test.context.TestPropertySource;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.script.api.ScriptType;
 | 
			
		||||
import org.thingsboard.script.api.mvel.MvelInvokeService;
 | 
			
		||||
import org.thingsboard.script.api.mvel.MvelScript;
 | 
			
		||||
import org.thingsboard.script.api.tbel.TbelInvokeService;
 | 
			
		||||
import org.thingsboard.script.api.tbel.TbelScript;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.controller.AbstractControllerTest;
 | 
			
		||||
import org.thingsboard.server.dao.service.DaoSqlTest;
 | 
			
		||||
@ -45,18 +45,18 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 | 
			
		||||
 | 
			
		||||
@DaoSqlTest
 | 
			
		||||
@TestPropertySource(properties = {
 | 
			
		||||
        "mvel.max_script_body_size=100",
 | 
			
		||||
        "mvel.max_total_args_size=50",
 | 
			
		||||
        "mvel.max_result_size=50",
 | 
			
		||||
        "mvel.max_errors=2",
 | 
			
		||||
        "mvel.compiled_scripts_cache_size=100"
 | 
			
		||||
        "tbel.max_script_body_size=100",
 | 
			
		||||
        "tbel.max_total_args_size=50",
 | 
			
		||||
        "tbel.max_result_size=50",
 | 
			
		||||
        "tbel.max_errors=2",
 | 
			
		||||
        "tbel.compiled_scripts_cache_size=100"
 | 
			
		||||
})
 | 
			
		||||
class MvelInvokeServiceTest extends AbstractControllerTest {
 | 
			
		||||
class TbelInvokeServiceTest extends AbstractControllerTest {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private MvelInvokeService invokeService;
 | 
			
		||||
    private TbelInvokeService invokeService;
 | 
			
		||||
 | 
			
		||||
    @Value("${mvel.max_errors}")
 | 
			
		||||
    @Value("${tbel.max_errors}")
 | 
			
		||||
    private int maxJsErrors;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@ -129,7 +129,7 @@ class MvelInvokeServiceTest extends AbstractControllerTest {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Map<UUID, String> scriptIdToHash = getFieldValue(invokeService, "scriptIdToHash");
 | 
			
		||||
        Map<String, MvelScript> scriptMap = getFieldValue(invokeService, "scriptMap");
 | 
			
		||||
        Map<String, TbelScript> scriptMap = getFieldValue(invokeService, "scriptMap");
 | 
			
		||||
        Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
 | 
			
		||||
 | 
			
		||||
        String scriptHash = scriptIdToHash.get(scriptsIds.get(0));
 | 
			
		||||
@ -149,7 +149,7 @@ class MvelInvokeServiceTest extends AbstractControllerTest {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Map<UUID, String> scriptIdToHash = getFieldValue(invokeService, "scriptIdToHash");
 | 
			
		||||
        Map<String, MvelScript> scriptMap = getFieldValue(invokeService, "scriptMap");
 | 
			
		||||
        Map<String, TbelScript> scriptMap = getFieldValue(invokeService, "scriptMap");
 | 
			
		||||
        Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
 | 
			
		||||
 | 
			
		||||
        String scriptHash = scriptIdToHash.get(scriptsIds.get(0));
 | 
			
		||||
@ -173,7 +173,7 @@ class MvelInvokeServiceTest extends AbstractControllerTest {
 | 
			
		||||
        Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
 | 
			
		||||
 | 
			
		||||
        List<UUID> scriptsIds = new ArrayList<>();
 | 
			
		||||
        for (int i = 0; i < 110; i++) { // mvel.compiled_scripts_cache_size = 100
 | 
			
		||||
        for (int i = 0; i < 110; i++) { // tbel.compiled_scripts_cache_size = 100
 | 
			
		||||
            String script = "return msg.temperature > " + i;
 | 
			
		||||
            UUID scriptId = evalScript(script);
 | 
			
		||||
            scriptsIds.add(scriptId);
 | 
			
		||||
@ -16,5 +16,5 @@
 | 
			
		||||
package org.thingsboard.server.common.data.script;
 | 
			
		||||
 | 
			
		||||
public enum ScriptLanguage {
 | 
			
		||||
    JS, MVEL
 | 
			
		||||
    JS, TBEL
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -90,7 +90,7 @@
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.thingsboard</groupId>
 | 
			
		||||
            <artifactId>mvel2</artifactId>
 | 
			
		||||
            <artifactId>tbel</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.script.api.mvel;
 | 
			
		||||
package org.thingsboard.script.api.tbel;
 | 
			
		||||
 | 
			
		||||
import com.github.benmanes.caffeine.cache.Cache;
 | 
			
		||||
import com.github.benmanes.caffeine.cache.Caffeine;
 | 
			
		||||
@ -58,12 +58,12 @@ import java.util.concurrent.locks.ReentrantLock;
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
@ConditionalOnProperty(prefix = "mvel", value = "enabled", havingValue = "true", matchIfMissing = true)
 | 
			
		||||
@ConditionalOnProperty(prefix = "tbel", value = "enabled", havingValue = "true", matchIfMissing = true)
 | 
			
		||||
@Service
 | 
			
		||||
public class DefaultMvelInvokeService extends AbstractScriptInvokeService implements MvelInvokeService {
 | 
			
		||||
public class DefaultTbelInvokeService extends AbstractScriptInvokeService implements TbelInvokeService {
 | 
			
		||||
 | 
			
		||||
    protected final Map<UUID, String> scriptIdToHash = new ConcurrentHashMap<>();
 | 
			
		||||
    protected final Map<String, MvelScript> scriptMap = new ConcurrentHashMap<>();
 | 
			
		||||
    protected final Map<String, TbelScript> scriptMap = new ConcurrentHashMap<>();
 | 
			
		||||
    protected Cache<String, Serializable> compiledScriptsCache;
 | 
			
		||||
 | 
			
		||||
    private SandboxedParserConfiguration parserConfig;
 | 
			
		||||
@ -71,49 +71,49 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
 | 
			
		||||
    private static final Pattern NEW_KEYWORD_PATTERN = Pattern.compile("new\\s");
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    @Value("${mvel.max_total_args_size:100000}")
 | 
			
		||||
    @Value("${tbel.max_total_args_size:100000}")
 | 
			
		||||
    private long maxTotalArgsSize;
 | 
			
		||||
    @Getter
 | 
			
		||||
    @Value("${mvel.max_result_size:300000}")
 | 
			
		||||
    @Value("${tbel.max_result_size:300000}")
 | 
			
		||||
    private long maxResultSize;
 | 
			
		||||
    @Getter
 | 
			
		||||
    @Value("${mvel.max_script_body_size:50000}")
 | 
			
		||||
    @Value("${tbel.max_script_body_size:50000}")
 | 
			
		||||
    private long maxScriptBodySize;
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    @Value("${mvel.max_errors:3}")
 | 
			
		||||
    @Value("${tbel.max_errors:3}")
 | 
			
		||||
    private int maxErrors;
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    @Value("${mvel.max_black_list_duration_sec:60}")
 | 
			
		||||
    @Value("${tbel.max_black_list_duration_sec:60}")
 | 
			
		||||
    private int maxBlackListDurationSec;
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    @Value("${mvel.max_requests_timeout:0}")
 | 
			
		||||
    @Value("${tbel.max_requests_timeout:0}")
 | 
			
		||||
    private long maxInvokeRequestsTimeout;
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    @Value("${mvel.stats.enabled:false}")
 | 
			
		||||
    @Value("${tbel.stats.enabled:false}")
 | 
			
		||||
    private boolean statsEnabled;
 | 
			
		||||
 | 
			
		||||
    @Value("${mvel.thread_pool_size:50}")
 | 
			
		||||
    @Value("${tbel.thread_pool_size:50}")
 | 
			
		||||
    private int threadPoolSize;
 | 
			
		||||
 | 
			
		||||
    @Value("${mvel.max_memory_limit_mb:8}")
 | 
			
		||||
    @Value("${tbel.max_memory_limit_mb:8}")
 | 
			
		||||
    private long maxMemoryLimitMb;
 | 
			
		||||
 | 
			
		||||
    @Value("${mvel.compiled_scripts_cache_size:1000}")
 | 
			
		||||
    @Value("${tbel.compiled_scripts_cache_size:1000}")
 | 
			
		||||
    private int compiledScriptsCacheSize;
 | 
			
		||||
 | 
			
		||||
    private ListeningExecutorService executor;
 | 
			
		||||
 | 
			
		||||
    private final Lock lock = new ReentrantLock();
 | 
			
		||||
 | 
			
		||||
    protected DefaultMvelInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) {
 | 
			
		||||
    protected DefaultTbelInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) {
 | 
			
		||||
        super(apiUsageStateClient, apiUsageReportClient);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Scheduled(fixedDelayString = "${mvel.stats.print_interval_ms:10000}")
 | 
			
		||||
    @Scheduled(fixedDelayString = "${tbel.stats.print_interval_ms:10000}")
 | 
			
		||||
    public void printStats() {
 | 
			
		||||
        super.printStats();
 | 
			
		||||
    }
 | 
			
		||||
@ -127,9 +127,9 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
 | 
			
		||||
        parserConfig.addImport("JSON", TbJson.class);
 | 
			
		||||
        parserConfig.registerDataType("Date", TbDate.class, date -> 8L);
 | 
			
		||||
        TbUtils.register(parserConfig);
 | 
			
		||||
        executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(threadPoolSize, "mvel-executor"));
 | 
			
		||||
        executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(threadPoolSize, "tbel-executor"));
 | 
			
		||||
        try {
 | 
			
		||||
            // Special command to warm up MVEL engine
 | 
			
		||||
            // Special command to warm up TBEL engine
 | 
			
		||||
            Serializable script = compileScript("var warmUp = {}; warmUp");
 | 
			
		||||
            MVEL.executeTbExpression(script, new ExecutionContext(parserConfig), Collections.emptyMap());
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
@ -149,7 +149,7 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected String getStatsName() {
 | 
			
		||||
        return "MVEL Scripts Stats";
 | 
			
		||||
        return "TBEL Scripts Stats";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@ -167,15 +167,11 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
 | 
			
		||||
        return executor.submit(() -> {
 | 
			
		||||
            try {
 | 
			
		||||
                String scriptHash = hash(scriptBody, argNames);
 | 
			
		||||
                compiledScriptsCache.get(scriptHash, k -> {
 | 
			
		||||
                    return compileScript(scriptBody);
 | 
			
		||||
                });
 | 
			
		||||
                compiledScriptsCache.get(scriptHash, k -> compileScript(scriptBody));
 | 
			
		||||
                lock.lock();
 | 
			
		||||
                try {
 | 
			
		||||
                    scriptIdToHash.put(scriptId, scriptHash);
 | 
			
		||||
                    scriptMap.computeIfAbsent(scriptHash, k -> {
 | 
			
		||||
                        return new MvelScript(scriptBody, argNames);
 | 
			
		||||
                    });
 | 
			
		||||
                    scriptMap.computeIfAbsent(scriptHash, k -> new TbelScript(scriptBody, argNames));
 | 
			
		||||
                } finally {
 | 
			
		||||
                    lock.unlock();
 | 
			
		||||
                }
 | 
			
		||||
@ -187,17 +183,15 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected MvelScriptExecutionTask doInvokeFunction(UUID scriptId, Object[] args) {
 | 
			
		||||
    protected TbelScriptExecutionTask doInvokeFunction(UUID scriptId, Object[] args) {
 | 
			
		||||
        ExecutionContext executionContext = new ExecutionContext(this.parserConfig, maxMemoryLimitMb * 1024 * 1024);
 | 
			
		||||
        return new MvelScriptExecutionTask(executionContext, executor.submit(() -> {
 | 
			
		||||
        return new TbelScriptExecutionTask(executionContext, executor.submit(() -> {
 | 
			
		||||
            String scriptHash = scriptIdToHash.get(scriptId);
 | 
			
		||||
            if (scriptHash == null) {
 | 
			
		||||
                throw new TbScriptException(scriptId, TbScriptException.ErrorCode.OTHER, null, new RuntimeException("Script not found!"));
 | 
			
		||||
            }
 | 
			
		||||
            MvelScript script = scriptMap.get(scriptHash);
 | 
			
		||||
            Serializable compiledScript = compiledScriptsCache.get(scriptHash, k -> {
 | 
			
		||||
                return compileScript(script.getScriptBody());
 | 
			
		||||
            });
 | 
			
		||||
            TbelScript script = scriptMap.get(scriptHash);
 | 
			
		||||
            Serializable compiledScript = compiledScriptsCache.get(scriptHash, k -> compileScript(script.getScriptBody()));
 | 
			
		||||
            try {
 | 
			
		||||
                return MVEL.executeTbExpression(compiledScript, executionContext, script.createVars(args));
 | 
			
		||||
            } catch (ScriptMemoryOverflowException e) {
 | 
			
		||||
@ -209,7 +203,7 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void doRelease(UUID scriptId) throws Exception {
 | 
			
		||||
    protected void doRelease(UUID scriptId) {
 | 
			
		||||
        String scriptHash = scriptIdToHash.remove(scriptId);
 | 
			
		||||
        if (scriptHash != null) {
 | 
			
		||||
            lock.lock();
 | 
			
		||||
@ -13,7 +13,7 @@
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.script.api.mvel;
 | 
			
		||||
package org.thingsboard.script.api.tbel;
 | 
			
		||||
 | 
			
		||||
import java.text.DateFormat;
 | 
			
		||||
import java.text.SimpleDateFormat;
 | 
			
		||||
@ -60,7 +60,7 @@ public class TbDate extends Date {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String toISOString() {
 | 
			
		||||
        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sssZ");
 | 
			
		||||
        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
 | 
			
		||||
        return formatter.format(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.script.api.mvel;
 | 
			
		||||
package org.thingsboard.script.api.tbel;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import org.mvel2.ExecutionContext;
 | 
			
		||||
@ -13,19 +13,25 @@
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.script.api.mvel;
 | 
			
		||||
package org.thingsboard.script.api.tbel;
 | 
			
		||||
 | 
			
		||||
import org.mvel2.ExecutionContext;
 | 
			
		||||
import org.mvel2.ParserConfiguration;
 | 
			
		||||
import org.mvel2.execution.ExecutionArrayList;
 | 
			
		||||
import org.mvel2.util.MethodStub;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.UnsupportedEncodingException;
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
import java.math.RoundingMode;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.util.Base64;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class TbUtils {
 | 
			
		||||
 | 
			
		||||
    private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
 | 
			
		||||
 | 
			
		||||
    public static void register(ParserConfiguration parserConfig) throws Exception {
 | 
			
		||||
        parserConfig.addImport("btoa", new MethodStub(TbUtils.class.getMethod("btoa",
 | 
			
		||||
                String.class)));
 | 
			
		||||
@ -35,6 +41,10 @@ public class TbUtils {
 | 
			
		||||
                List.class)));
 | 
			
		||||
        parserConfig.addImport("bytesToString", new MethodStub(TbUtils.class.getMethod("bytesToString",
 | 
			
		||||
                List.class, String.class)));
 | 
			
		||||
        parserConfig.addImport("decodeToString", new MethodStub(TbUtils.class.getMethod("bytesToString",
 | 
			
		||||
                List.class)));
 | 
			
		||||
        parserConfig.addImport("decodeToJson", new MethodStub(TbUtils.class.getMethod("decodeToJson",
 | 
			
		||||
                ExecutionContext.class, List.class)));
 | 
			
		||||
        parserConfig.addImport("stringToBytes", new MethodStub(TbUtils.class.getMethod("stringToBytes",
 | 
			
		||||
                ExecutionContext.class, String.class)));
 | 
			
		||||
        parserConfig.addImport("stringToBytes", new MethodStub(TbUtils.class.getMethod("stringToBytes",
 | 
			
		||||
@ -47,10 +57,24 @@ public class TbUtils {
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("parseDouble", new MethodStub(TbUtils.class.getMethod("parseDouble",
 | 
			
		||||
                String.class)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args) {
 | 
			
		||||
        System.out.println(Integer.class == int.class);
 | 
			
		||||
        parserConfig.addImport("parseLittleEndianHexToInt", new MethodStub(TbUtils.class.getMethod("parseLittleEndianHexToInt",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("parseBigEndianHexToInt", new MethodStub(TbUtils.class.getMethod("parseBigEndianHexToInt",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("parseHexToInt", new MethodStub(TbUtils.class.getMethod("parseHexToInt",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("parseHexToInt", new MethodStub(TbUtils.class.getMethod("parseHexToInt",
 | 
			
		||||
                String.class, boolean.class)));
 | 
			
		||||
        parserConfig.addImport("toFixed", new MethodStub(TbUtils.class.getMethod("toFixed",
 | 
			
		||||
                double.class, int.class)));
 | 
			
		||||
        parserConfig.addImport("hexToBytes", new MethodStub(TbUtils.class.getMethod("hexToBytes",
 | 
			
		||||
                ExecutionContext.class, String.class)));
 | 
			
		||||
        parserConfig.addImport("base64ToHex", new MethodStub(TbUtils.class.getMethod("base64ToHex",
 | 
			
		||||
                String.class)));
 | 
			
		||||
        parserConfig.addImport("bytesToHex", new MethodStub(TbUtils.class.getMethod("bytesToHex",
 | 
			
		||||
                byte[].class)));
 | 
			
		||||
        parserConfig.addImport("bytesToHex", new MethodStub(TbUtils.class.getMethod("bytesToHex",
 | 
			
		||||
                ExecutionArrayList.class)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String btoa(String input) {
 | 
			
		||||
@ -61,6 +85,10 @@ public class TbUtils {
 | 
			
		||||
        return new String(Base64.getDecoder().decode(encoded));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Object decodeToJson(ExecutionContext ctx, List<Byte> bytesList) throws IOException {
 | 
			
		||||
        return TbJson.parse(ctx, bytesToString(bytesList));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String bytesToString(List<Byte> bytesList) {
 | 
			
		||||
        byte[] bytes = bytesFromList(bytesList);
 | 
			
		||||
        return new String(bytes);
 | 
			
		||||
@ -149,6 +177,72 @@ public class TbUtils {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int parseLittleEndianHexToInt(String hex) {
 | 
			
		||||
        return parseHexToInt(hex, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int parseBigEndianHexToInt(String hex) {
 | 
			
		||||
        return parseHexToInt(hex, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int parseHexToInt(String hex) {
 | 
			
		||||
        return parseHexToInt(hex, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int parseHexToInt(String hex, boolean bigEndian) {
 | 
			
		||||
        int length = hex.length();
 | 
			
		||||
        if (length > 8) {
 | 
			
		||||
            throw new IllegalArgumentException("Hex string is too large. Maximum 8 symbols allowed.");
 | 
			
		||||
        }
 | 
			
		||||
        if (bigEndian) {
 | 
			
		||||
            return Integer.parseInt(hex, 16);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (length < 8) {
 | 
			
		||||
                hex = hex + "0".repeat(8 - length);
 | 
			
		||||
            }
 | 
			
		||||
            return Integer.reverseBytes(Integer.parseInt(hex, 16));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ExecutionArrayList<Integer> hexToBytes(ExecutionContext ctx, String hex) {
 | 
			
		||||
        int len = hex.length();
 | 
			
		||||
        if (len % 2 > 0) {
 | 
			
		||||
            throw new IllegalArgumentException("Hex string must be even-length.");
 | 
			
		||||
        }
 | 
			
		||||
        ExecutionArrayList<Integer> data = new ExecutionArrayList<>(ctx);
 | 
			
		||||
        for (int i = 0; i < len; i += 2) {
 | 
			
		||||
            data.add((Character.digit(hex.charAt(i), 16) << 4)
 | 
			
		||||
                    + Character.digit(hex.charAt(i+1), 16));
 | 
			
		||||
        }
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String base64ToHex(String base64) {
 | 
			
		||||
        return bytesToHex(Base64.getDecoder().decode(base64));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String bytesToHex(ExecutionArrayList<?> bytesList) {
 | 
			
		||||
        byte[] bytes = new byte[bytesList.size()];
 | 
			
		||||
        for (int i = 0; i < bytesList.size(); i++) {
 | 
			
		||||
            bytes[i] = Byte.parseByte(bytesList.get(i).toString());
 | 
			
		||||
        }
 | 
			
		||||
        return bytesToHex(bytes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String bytesToHex(byte[] bytes) {
 | 
			
		||||
        byte[] hexChars = new byte[bytes.length * 2];
 | 
			
		||||
        for (int j = 0; j < bytes.length; j++) {
 | 
			
		||||
            int v = bytes[j] & 0xFF;
 | 
			
		||||
            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
 | 
			
		||||
            hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
 | 
			
		||||
        }
 | 
			
		||||
        return new String(hexChars, StandardCharsets.UTF_8);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double toFixed(double value, int precision) {
 | 
			
		||||
        return BigDecimal.valueOf(value).setScale(precision, RoundingMode.HALF_UP).doubleValue();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static boolean isHexadecimal(String value) {
 | 
			
		||||
        return value != null && (value.contains("0x") || value.contains("0X"));
 | 
			
		||||
    }
 | 
			
		||||
@ -13,16 +13,16 @@
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.script.api.mvel;
 | 
			
		||||
package org.thingsboard.script.api.tbel;
 | 
			
		||||
 | 
			
		||||
import org.thingsboard.script.api.ScriptInvokeService;
 | 
			
		||||
import org.thingsboard.server.common.data.script.ScriptLanguage;
 | 
			
		||||
 | 
			
		||||
public interface MvelInvokeService extends ScriptInvokeService {
 | 
			
		||||
public interface TbelInvokeService extends ScriptInvokeService {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    default ScriptLanguage getLanguage() {
 | 
			
		||||
        return ScriptLanguage.MVEL;
 | 
			
		||||
        return ScriptLanguage.TBEL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -13,16 +13,15 @@
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.script.api.mvel;
 | 
			
		||||
package org.thingsboard.script.api.tbel;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class MvelScript {
 | 
			
		||||
public class TbelScript {
 | 
			
		||||
 | 
			
		||||
    private final String scriptBody;
 | 
			
		||||
    private final String[] argNames;
 | 
			
		||||
@ -13,20 +13,18 @@
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.script.api.mvel;
 | 
			
		||||
package org.thingsboard.script.api.tbel;
 | 
			
		||||
 | 
			
		||||
import com.google.common.util.concurrent.ListenableFuture;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
import org.mvel2.ExecutionContext;
 | 
			
		||||
import org.thingsboard.script.api.TbScriptExecutionTask;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public class MvelScriptExecutionTask extends TbScriptExecutionTask {
 | 
			
		||||
public class TbelScriptExecutionTask extends TbScriptExecutionTask {
 | 
			
		||||
 | 
			
		||||
    private final ExecutionContext context;
 | 
			
		||||
 | 
			
		||||
    public MvelScriptExecutionTask(ExecutionContext context, ListenableFuture<Object> resultFuture) {
 | 
			
		||||
    public TbelScriptExecutionTask(ExecutionContext context, ListenableFuture<Object> resultFuture) {
 | 
			
		||||
        super(resultFuture);
 | 
			
		||||
        this.context = context;
 | 
			
		||||
    }
 | 
			
		||||
							
								
								
									
										6
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								pom.xml
									
									
									
									
									
								
							@ -77,7 +77,7 @@
 | 
			
		||||
        <zookeeper.version>3.5.5</zookeeper.version>
 | 
			
		||||
        <protobuf.version>3.21.9</protobuf.version>
 | 
			
		||||
        <grpc.version>1.42.1</grpc.version>
 | 
			
		||||
        <mvel.version>2.4.25TB</mvel.version>
 | 
			
		||||
        <tbel.version>1.0.0</tbel.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>
 | 
			
		||||
@ -1575,8 +1575,8 @@
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.thingsboard</groupId>
 | 
			
		||||
                <artifactId>mvel2</artifactId>
 | 
			
		||||
                <version>${mvel.version}</version>
 | 
			
		||||
                <artifactId>tbel</artifactId>
 | 
			
		||||
                <version>${tbel.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.springframework</groupId>
 | 
			
		||||
 | 
			
		||||
@ -48,7 +48,7 @@ public abstract class TbAbstractAlarmNode<C extends TbAbstractAlarmNodeConfigura
 | 
			
		||||
    public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
 | 
			
		||||
        this.config = loadAlarmNodeConfig(configuration);
 | 
			
		||||
        scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
 | 
			
		||||
                ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getAlarmDetailsBuildMvel() : config.getAlarmDetailsBuildJs());
 | 
			
		||||
                ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getAlarmDetailsBuildTbel() : config.getAlarmDetailsBuildJs());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected abstract C loadAlarmNodeConfig(TbNodeConfiguration configuration) throws TbNodeException;
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ public abstract class TbAbstractAlarmNodeConfiguration {
 | 
			
		||||
            "\n" +
 | 
			
		||||
            "return details;";
 | 
			
		||||
 | 
			
		||||
    static final String ALARM_DETAILS_BUILD_MVEL_TEMPLATE = "" +
 | 
			
		||||
    static final String ALARM_DETAILS_BUILD_TBEL_TEMPLATE = "" +
 | 
			
		||||
            "var details = {};\n" +
 | 
			
		||||
            "if (metadata.prevAlarmDetails != null) {\n" +
 | 
			
		||||
            "    details = JSON.parse(metadata.prevAlarmDetails);\n" +
 | 
			
		||||
@ -49,6 +49,6 @@ public abstract class TbAbstractAlarmNodeConfiguration {
 | 
			
		||||
    private String alarmType;
 | 
			
		||||
    private ScriptLanguage scriptLang;
 | 
			
		||||
    private String alarmDetailsBuildJs;
 | 
			
		||||
    private String alarmDetailsBuildMvel;
 | 
			
		||||
    private String alarmDetailsBuildTbel;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,6 @@ package org.thingsboard.rule.engine.action;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.thingsboard.rule.engine.api.NodeConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
 | 
			
		||||
import org.thingsboard.server.common.data.script.ScriptLanguage;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@ -26,9 +25,9 @@ public class TbClearAlarmNodeConfiguration extends TbAbstractAlarmNodeConfigurat
 | 
			
		||||
    @Override
 | 
			
		||||
    public TbClearAlarmNodeConfiguration defaultConfiguration() {
 | 
			
		||||
        TbClearAlarmNodeConfiguration configuration = new TbClearAlarmNodeConfiguration();
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.MVEL);
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.TBEL);
 | 
			
		||||
        configuration.setAlarmDetailsBuildJs(ALARM_DETAILS_BUILD_JS_TEMPLATE);
 | 
			
		||||
        configuration.setAlarmDetailsBuildMvel(ALARM_DETAILS_BUILD_MVEL_TEMPLATE);
 | 
			
		||||
        configuration.setAlarmDetailsBuildTbel(ALARM_DETAILS_BUILD_TBEL_TEMPLATE);
 | 
			
		||||
        configuration.setAlarmType("General Alarm");
 | 
			
		||||
        return configuration;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -39,9 +39,9 @@ public class TbCreateAlarmNodeConfiguration extends TbAbstractAlarmNodeConfigura
 | 
			
		||||
    @Override
 | 
			
		||||
    public TbCreateAlarmNodeConfiguration defaultConfiguration() {
 | 
			
		||||
        TbCreateAlarmNodeConfiguration configuration = new TbCreateAlarmNodeConfiguration();
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.MVEL);
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.TBEL);
 | 
			
		||||
        configuration.setAlarmDetailsBuildJs(ALARM_DETAILS_BUILD_JS_TEMPLATE);
 | 
			
		||||
        configuration.setAlarmDetailsBuildMvel(ALARM_DETAILS_BUILD_MVEL_TEMPLATE);
 | 
			
		||||
        configuration.setAlarmDetailsBuildTbel(ALARM_DETAILS_BUILD_TBEL_TEMPLATE);
 | 
			
		||||
        configuration.setAlarmType("General Alarm");
 | 
			
		||||
        configuration.setSeverity(AlarmSeverity.CRITICAL.name());
 | 
			
		||||
        configuration.setPropagate(false);
 | 
			
		||||
 | 
			
		||||
@ -56,7 +56,7 @@ public class TbLogNode implements TbNode {
 | 
			
		||||
        this.config = TbNodeUtils.convert(configuration, TbLogNodeConfiguration.class);
 | 
			
		||||
        this.standard = new TbLogNodeConfiguration().defaultConfiguration().getJsScript().equals(config.getJsScript());
 | 
			
		||||
        this.scriptEngine = this.standard ? null : ctx.createScriptEngine(config.getScriptLang(),
 | 
			
		||||
                ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getMvelScript() : config.getJsScript());
 | 
			
		||||
                ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getTbelScript() : config.getJsScript());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 | 
			
		||||
@ -24,14 +24,14 @@ public class TbLogNodeConfiguration implements NodeConfiguration {
 | 
			
		||||
 | 
			
		||||
    private ScriptLanguage scriptLang;
 | 
			
		||||
    private String jsScript;
 | 
			
		||||
    private String mvelScript;
 | 
			
		||||
    private String tbelScript;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TbLogNodeConfiguration defaultConfiguration() {
 | 
			
		||||
        TbLogNodeConfiguration configuration = new TbLogNodeConfiguration();
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.MVEL);
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.TBEL);
 | 
			
		||||
        configuration.setJsScript("return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);");
 | 
			
		||||
        configuration.setMvelScript("return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);");
 | 
			
		||||
        configuration.setTbelScript("return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);");
 | 
			
		||||
        return configuration;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -96,7 +96,7 @@ public class TbMsgGeneratorNode implements TbNode {
 | 
			
		||||
        if (ctx.isLocalEntity(originatorId)) {
 | 
			
		||||
            if (initialized.compareAndSet(false, true)) {
 | 
			
		||||
                this.scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
 | 
			
		||||
                        ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getMvelScript() : config.getJsScript(), "prevMsg", "prevMetadata", "prevMsgType");
 | 
			
		||||
                        ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getTbelScript() : config.getJsScript(), "prevMsg", "prevMetadata", "prevMsgType");
 | 
			
		||||
                scheduleTickMsg(ctx);
 | 
			
		||||
            }
 | 
			
		||||
        } else if (initialized.compareAndSet(true, false)) {
 | 
			
		||||
 | 
			
		||||
@ -35,16 +35,16 @@ public class TbMsgGeneratorNodeConfiguration implements NodeConfiguration<TbMsgG
 | 
			
		||||
    private EntityType originatorType;
 | 
			
		||||
    private ScriptLanguage scriptLang;
 | 
			
		||||
    private String jsScript;
 | 
			
		||||
    private String mvelScript;
 | 
			
		||||
    private String tbelScript;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TbMsgGeneratorNodeConfiguration defaultConfiguration() {
 | 
			
		||||
        TbMsgGeneratorNodeConfiguration configuration = new TbMsgGeneratorNodeConfiguration();
 | 
			
		||||
        configuration.setMsgCount(UNLIMITED_MSG_COUNT);
 | 
			
		||||
        configuration.setPeriodInSeconds(1);
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.MVEL);
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.TBEL);
 | 
			
		||||
        configuration.setJsScript(DEFAULT_SCRIPT);
 | 
			
		||||
        configuration.setMvelScript(DEFAULT_SCRIPT);
 | 
			
		||||
        configuration.setTbelScript(DEFAULT_SCRIPT);
 | 
			
		||||
        return configuration;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,6 @@ import org.thingsboard.rule.engine.api.TbNode;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNodeException;
 | 
			
		||||
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.StringUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.plugin.ComponentType;
 | 
			
		||||
import org.thingsboard.server.common.data.script.ScriptLanguage;
 | 
			
		||||
import org.thingsboard.server.common.msg.TbMsg;
 | 
			
		||||
@ -53,7 +52,7 @@ public class TbJsFilterNode implements TbNode {
 | 
			
		||||
    public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
 | 
			
		||||
        this.config = TbNodeUtils.convert(configuration, TbJsFilterNodeConfiguration.class);
 | 
			
		||||
        scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
 | 
			
		||||
                ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getMvelScript() : config.getJsScript());
 | 
			
		||||
                ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getTbelScript() : config.getJsScript());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 | 
			
		||||
@ -24,14 +24,14 @@ public class TbJsFilterNodeConfiguration implements NodeConfiguration<TbJsFilter
 | 
			
		||||
 | 
			
		||||
    private ScriptLanguage scriptLang;
 | 
			
		||||
    private String jsScript;
 | 
			
		||||
    private String mvelScript;
 | 
			
		||||
    private String tbelScript;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TbJsFilterNodeConfiguration defaultConfiguration() {
 | 
			
		||||
        TbJsFilterNodeConfiguration configuration = new TbJsFilterNodeConfiguration();
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.MVEL);
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.TBEL);
 | 
			
		||||
        configuration.setJsScript("return msg.temperature > 20;");
 | 
			
		||||
        configuration.setMvelScript("return msg.temperature > 20;");
 | 
			
		||||
        configuration.setTbelScript("return msg.temperature > 20;");
 | 
			
		||||
        return configuration;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -56,7 +56,7 @@ public class TbJsSwitchNode implements TbNode {
 | 
			
		||||
    public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
 | 
			
		||||
        this.config = TbNodeUtils.convert(configuration, TbJsSwitchNodeConfiguration.class);
 | 
			
		||||
        this.scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
 | 
			
		||||
                ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getMvelScript() : config.getJsScript());
 | 
			
		||||
                ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getTbelScript() : config.getJsScript());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 | 
			
		||||
@ -15,13 +15,10 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.rule.engine.filter;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.Sets;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.thingsboard.rule.engine.api.NodeConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.script.ScriptLanguage;
 | 
			
		||||
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class TbJsSwitchNodeConfiguration implements NodeConfiguration<TbJsSwitchNodeConfiguration> {
 | 
			
		||||
 | 
			
		||||
@ -33,7 +30,7 @@ public class TbJsSwitchNodeConfiguration implements NodeConfiguration<TbJsSwitch
 | 
			
		||||
            "}\n" +
 | 
			
		||||
            "return nextRelation(metadata, msg);";
 | 
			
		||||
 | 
			
		||||
    private static final String DEFAULT_MVEL_SCRIPT = "function nextRelation(metadata, msg) {\n" +
 | 
			
		||||
    private static final String DEFAULT_TBEL_SCRIPT = "function nextRelation(metadata, msg) {\n" +
 | 
			
		||||
            "    return ['one','nine'];\n" +
 | 
			
		||||
            "}\n" +
 | 
			
		||||
            "if(msgType == 'POST_TELEMETRY_REQUEST') {\n" +
 | 
			
		||||
@ -43,14 +40,14 @@ public class TbJsSwitchNodeConfiguration implements NodeConfiguration<TbJsSwitch
 | 
			
		||||
 | 
			
		||||
    private ScriptLanguage scriptLang;
 | 
			
		||||
    private String jsScript;
 | 
			
		||||
    private String mvelScript;
 | 
			
		||||
    private String tbelScript;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TbJsSwitchNodeConfiguration defaultConfiguration() {
 | 
			
		||||
        TbJsSwitchNodeConfiguration configuration = new TbJsSwitchNodeConfiguration();
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.MVEL);
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.TBEL);
 | 
			
		||||
        configuration.setJsScript(DEFAULT_JS_SCRIPT);
 | 
			
		||||
        configuration.setMvelScript(DEFAULT_MVEL_SCRIPT);
 | 
			
		||||
        configuration.setTbelScript(DEFAULT_TBEL_SCRIPT);
 | 
			
		||||
        return configuration;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,6 @@ import org.thingsboard.rule.engine.api.TbContext;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNodeException;
 | 
			
		||||
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.StringUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.plugin.ComponentType;
 | 
			
		||||
import org.thingsboard.server.common.data.script.ScriptLanguage;
 | 
			
		||||
import org.thingsboard.server.common.msg.TbMsg;
 | 
			
		||||
@ -53,7 +52,7 @@ public class TbTransformMsgNode extends TbAbstractTransformNode {
 | 
			
		||||
    public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
 | 
			
		||||
        this.config = TbNodeUtils.convert(configuration, TbTransformMsgNodeConfiguration.class);
 | 
			
		||||
        scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
 | 
			
		||||
                ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getMvelScript() : config.getJsScript());
 | 
			
		||||
                ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getTbelScript() : config.getJsScript());
 | 
			
		||||
        setConfig(config);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -24,14 +24,14 @@ public class TbTransformMsgNodeConfiguration extends TbTransformNodeConfiguratio
 | 
			
		||||
 | 
			
		||||
    private ScriptLanguage scriptLang;
 | 
			
		||||
    private String jsScript;
 | 
			
		||||
    private String mvelScript;
 | 
			
		||||
    private String tbelScript;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TbTransformMsgNodeConfiguration defaultConfiguration() {
 | 
			
		||||
        TbTransformMsgNodeConfiguration configuration = new TbTransformMsgNodeConfiguration();
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.MVEL);
 | 
			
		||||
        configuration.setScriptLang(ScriptLanguage.TBEL);
 | 
			
		||||
        configuration.setJsScript("return {msg: msg, metadata: metadata, msgType: msgType};");
 | 
			
		||||
        configuration.setMvelScript("return {msg: msg, metadata: metadata, msgType: msgType};");
 | 
			
		||||
        configuration.setTbelScript("return {msg: msg, metadata: metadata, msgType: msgType};");
 | 
			
		||||
        return configuration;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -21,7 +21,7 @@ export interface SysParamsState {
 | 
			
		||||
  allowedDashboardIds: string[];
 | 
			
		||||
  edgesSupportEnabled: boolean;
 | 
			
		||||
  hasRepository: boolean;
 | 
			
		||||
  mvelEnabled: boolean;
 | 
			
		||||
  tbelEnabled: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface AuthPayload extends SysParamsState {
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ const emptyUserAuthState: AuthPayload = {
 | 
			
		||||
  allowedDashboardIds: [],
 | 
			
		||||
  edgesSupportEnabled: false,
 | 
			
		||||
  hasRepository: false,
 | 
			
		||||
  mvelEnabled: false
 | 
			
		||||
  tbelEnabled: false
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const initialState: AuthState = {
 | 
			
		||||
 | 
			
		||||
@ -60,9 +60,9 @@ export const selectHasRepository = createSelector(
 | 
			
		||||
  (state: AuthState) => state.hasRepository
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const selectMvelEnabled = createSelector(
 | 
			
		||||
export const selectTbelEnabled = createSelector(
 | 
			
		||||
  selectAuthState,
 | 
			
		||||
  (state: AuthState) => state.mvelEnabled
 | 
			
		||||
  (state: AuthState) => state.tbelEnabled
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export function getCurrentAuthState(store: Store<AppState>): AuthState {
 | 
			
		||||
 | 
			
		||||
@ -482,9 +482,9 @@ export class AuthService {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private loadMvelEnabled(authUser: AuthUser): Observable<boolean> {
 | 
			
		||||
  private loadTbelEnabled(authUser: AuthUser): Observable<boolean> {
 | 
			
		||||
    if (authUser.authority === Authority.TENANT_ADMIN) {
 | 
			
		||||
      return this.http.get<boolean>('/api/ruleChain/mvelEnabled', defaultHttpOptions());
 | 
			
		||||
      return this.http.get<boolean>('/api/ruleChain/tbelEnabled', defaultHttpOptions());
 | 
			
		||||
    } else {
 | 
			
		||||
      return of(false);
 | 
			
		||||
    }
 | 
			
		||||
@ -495,7 +495,7 @@ export class AuthService {
 | 
			
		||||
                     this.fetchAllowedDashboardIds(authPayload),
 | 
			
		||||
                     this.loadIsEdgesSupportEnabled(),
 | 
			
		||||
                     this.loadHasRepository(authPayload.authUser),
 | 
			
		||||
                     this.loadMvelEnabled(authPayload.authUser),
 | 
			
		||||
                     this.loadTbelEnabled(authPayload.authUser),
 | 
			
		||||
                     this.timeService.loadMaxDatapointsLimit()];
 | 
			
		||||
    return forkJoin(sources)
 | 
			
		||||
      .pipe(map((data) => {
 | 
			
		||||
@ -503,8 +503,8 @@ export class AuthService {
 | 
			
		||||
        const allowedDashboardIds: string[] = data[1] as string[];
 | 
			
		||||
        const edgesSupportEnabled: boolean = data[2] as boolean;
 | 
			
		||||
        const hasRepository: boolean = data[3] as boolean;
 | 
			
		||||
        const mvelEnabled: boolean = data[4] as boolean;
 | 
			
		||||
        return {userTokenAccessEnabled, allowedDashboardIds, edgesSupportEnabled, hasRepository, mvelEnabled};
 | 
			
		||||
        const tbelEnabled: boolean = data[4] as boolean;
 | 
			
		||||
        return {userTokenAccessEnabled, allowedDashboardIds, edgesSupportEnabled, hasRepository, tbelEnabled};
 | 
			
		||||
      }, catchError((err) => {
 | 
			
		||||
        return of({});
 | 
			
		||||
      })));
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,7 @@
 | 
			
		||||
<form class="tb-node-script-test-dialog"
 | 
			
		||||
      [formGroup]="nodeScriptTestFormGroup" (ngSubmit)="save()">
 | 
			
		||||
  <mat-toolbar fxLayout="row" color="primary">
 | 
			
		||||
    <h2>{{ 'rulenode.test-script-function' | translate }} ({{ (scriptLang === scriptLanguage.JS ? 'rulenode.script-lang-java-script' : 'rulenode.script-lang-mvel') | translate }})</h2>
 | 
			
		||||
    <h2>{{ 'rulenode.test-script-function' | translate }} ({{ (scriptLang === scriptLanguage.JS ? 'rulenode.script-lang-java-script' : 'rulenode.script-lang-tbel') | translate }})</h2>
 | 
			
		||||
    <span fxFlex></span>
 | 
			
		||||
    <button mat-button mat-icon-button
 | 
			
		||||
            (click)="cancel()"
 | 
			
		||||
@ -77,7 +77,7 @@
 | 
			
		||||
              functionName="{{ data.functionName }}"
 | 
			
		||||
              [functionArgs]="data.argNames"
 | 
			
		||||
              [validationArgs]="[data.msg, data.metadata, data.msgType]"
 | 
			
		||||
              [disableUndefinedCheck]="scriptLang === scriptLanguage.MVEL"
 | 
			
		||||
              [disableUndefinedCheck]="scriptLang === scriptLanguage.TBEL"
 | 
			
		||||
              resultType="object"
 | 
			
		||||
              [helpId]="data.helpId"
 | 
			
		||||
              [fillHeight]="true">
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@
 | 
			
		||||
  <mat-button-toggle-group class="tb-script-lang-toggle-group"
 | 
			
		||||
                           style="width: 320px;"
 | 
			
		||||
                           formControlName="scriptLang" aria-label="Script language">
 | 
			
		||||
    <mat-button-toggle fxFlex value="{{ scriptLanguage.MVEL }}">{{ 'rulenode.script-lang-mvel' | translate }}</mat-button-toggle>
 | 
			
		||||
    <mat-button-toggle fxFlex value="{{ scriptLanguage.TBEL }}">{{ 'rulenode.script-lang-tbel' | translate }}</mat-button-toggle>
 | 
			
		||||
    <mat-button-toggle fxFlex value="{{ scriptLanguage.JS }}">{{ 'rulenode.script-lang-java-script' | translate }}</mat-button-toggle>
 | 
			
		||||
  </mat-button-toggle-group>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@ -330,7 +330,7 @@ export interface FcRuleEdge extends FcEdge {
 | 
			
		||||
 | 
			
		||||
export enum ScriptLanguage {
 | 
			
		||||
  JS = 'JS',
 | 
			
		||||
  MVEL = 'MVEL'
 | 
			
		||||
  TBEL = 'TBEL'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface TestScriptInputParams {
 | 
			
		||||
 | 
			
		||||
@ -3013,7 +3013,7 @@
 | 
			
		||||
        "invalid-target-rulechain": "Unable to resolve target rule chain!",
 | 
			
		||||
        "test-script-function": "Test script function",
 | 
			
		||||
        "script-lang-java-script": "Java Script",
 | 
			
		||||
        "script-lang-mvel": "MVEL",
 | 
			
		||||
        "script-lang-tbel": "TBEL",
 | 
			
		||||
        "message": "Message",
 | 
			
		||||
        "message-type": "Message type",
 | 
			
		||||
        "select-message-type": "Select message type",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user