Showing
12 changed files
with
218 additions
and
22 deletions
@@ -256,6 +256,10 @@ | @@ -256,6 +256,10 @@ | ||
256 | <groupId>org.hsqldb</groupId> | 256 | <groupId>org.hsqldb</groupId> |
257 | <artifactId>hsqldb</artifactId> | 257 | <artifactId>hsqldb</artifactId> |
258 | </dependency> | 258 | </dependency> |
259 | + <dependency> | ||
260 | + <groupId>org.javadelight</groupId> | ||
261 | + <artifactId>delight-nashorn-sandbox</artifactId> | ||
262 | + </dependency> | ||
259 | </dependencies> | 263 | </dependencies> |
260 | 264 | ||
261 | <build> | 265 | <build> |
@@ -62,6 +62,7 @@ import org.thingsboard.server.service.mail.MailExecutorService; | @@ -62,6 +62,7 @@ import org.thingsboard.server.service.mail.MailExecutorService; | ||
62 | import org.thingsboard.server.service.queue.MsgQueueService; | 62 | import org.thingsboard.server.service.queue.MsgQueueService; |
63 | import org.thingsboard.server.service.rpc.DeviceRpcService; | 63 | import org.thingsboard.server.service.rpc.DeviceRpcService; |
64 | import org.thingsboard.server.service.script.JsExecutorService; | 64 | import org.thingsboard.server.service.script.JsExecutorService; |
65 | +import org.thingsboard.server.service.script.JsSandboxService; | ||
65 | import org.thingsboard.server.service.state.DeviceStateService; | 66 | import org.thingsboard.server.service.state.DeviceStateService; |
66 | import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; | 67 | import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; |
67 | 68 | ||
@@ -164,6 +165,10 @@ public class ActorSystemContext { | @@ -164,6 +165,10 @@ public class ActorSystemContext { | ||
164 | 165 | ||
165 | @Autowired | 166 | @Autowired |
166 | @Getter | 167 | @Getter |
168 | + private JsSandboxService jsSandbox; | ||
169 | + | ||
170 | + @Autowired | ||
171 | + @Getter | ||
167 | private JsExecutorService jsExecutor; | 172 | private JsExecutorService jsExecutor; |
168 | 173 | ||
169 | @Autowired | 174 | @Autowired |
@@ -44,7 +44,7 @@ import org.thingsboard.server.dao.relation.RelationService; | @@ -44,7 +44,7 @@ import org.thingsboard.server.dao.relation.RelationService; | ||
44 | import org.thingsboard.server.dao.rule.RuleChainService; | 44 | import org.thingsboard.server.dao.rule.RuleChainService; |
45 | import org.thingsboard.server.dao.timeseries.TimeseriesService; | 45 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
46 | import org.thingsboard.server.dao.user.UserService; | 46 | import org.thingsboard.server.dao.user.UserService; |
47 | -import org.thingsboard.server.service.script.NashornJsEngine; | 47 | +import org.thingsboard.server.service.script.JsScriptEngine; |
48 | import scala.concurrent.duration.Duration; | 48 | import scala.concurrent.duration.Duration; |
49 | 49 | ||
50 | import java.util.Collections; | 50 | import java.util.Collections; |
@@ -152,7 +152,7 @@ class DefaultTbContext implements TbContext { | @@ -152,7 +152,7 @@ class DefaultTbContext implements TbContext { | ||
152 | 152 | ||
153 | @Override | 153 | @Override |
154 | public ScriptEngine createJsScriptEngine(String script, String functionName, String... argNames) { | 154 | public ScriptEngine createJsScriptEngine(String script, String functionName, String... argNames) { |
155 | - return new NashornJsEngine(script, functionName, argNames); | 155 | + return new JsScriptEngine(mainCtx.getJsSandbox(), script, functionName, argNames); |
156 | } | 156 | } |
157 | 157 | ||
158 | @Override | 158 | @Override |
@@ -50,7 +50,9 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; | @@ -50,7 +50,9 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; | ||
50 | import org.thingsboard.server.common.msg.TbMsg; | 50 | import org.thingsboard.server.common.msg.TbMsg; |
51 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 51 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
52 | import org.thingsboard.server.dao.event.EventService; | 52 | import org.thingsboard.server.dao.event.EventService; |
53 | -import org.thingsboard.server.service.script.NashornJsEngine; | 53 | +import org.thingsboard.server.service.script.JsExecutorService; |
54 | +import org.thingsboard.server.service.script.JsSandboxService; | ||
55 | +import org.thingsboard.server.service.script.JsScriptEngine; | ||
54 | 56 | ||
55 | import java.util.List; | 57 | import java.util.List; |
56 | import java.util.Map; | 58 | import java.util.Map; |
@@ -69,6 +71,9 @@ public class RuleChainController extends BaseController { | @@ -69,6 +71,9 @@ public class RuleChainController extends BaseController { | ||
69 | @Autowired | 71 | @Autowired |
70 | private EventService eventService; | 72 | private EventService eventService; |
71 | 73 | ||
74 | + @Autowired | ||
75 | + private JsSandboxService jsSandboxService; | ||
76 | + | ||
72 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | 77 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
73 | @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.GET) | 78 | @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.GET) |
74 | @ResponseBody | 79 | @ResponseBody |
@@ -273,7 +278,7 @@ public class RuleChainController extends BaseController { | @@ -273,7 +278,7 @@ public class RuleChainController extends BaseController { | ||
273 | String errorText = ""; | 278 | String errorText = ""; |
274 | ScriptEngine engine = null; | 279 | ScriptEngine engine = null; |
275 | try { | 280 | try { |
276 | - engine = new NashornJsEngine(script, functionName, argNames); | 281 | + engine = new JsScriptEngine(jsSandboxService, script, functionName, argNames); |
277 | TbMsg inMsg = new TbMsg(UUIDs.timeBased(), msgType, null, new TbMsgMetaData(metadata), data, null, null, 0L); | 282 | TbMsg inMsg = new TbMsg(UUIDs.timeBased(), msgType, null, new TbMsgMetaData(metadata), data, null, null, 0L); |
278 | switch (scriptType) { | 283 | switch (scriptType) { |
279 | case "update": | 284 | case "update": |
@@ -54,6 +54,10 @@ public abstract class AbstractListeningExecutor implements ListeningExecutor { | @@ -54,6 +54,10 @@ public abstract class AbstractListeningExecutor implements ListeningExecutor { | ||
54 | service.execute(command); | 54 | service.execute(command); |
55 | } | 55 | } |
56 | 56 | ||
57 | + public ListeningExecutorService executor() { | ||
58 | + return service; | ||
59 | + } | ||
60 | + | ||
57 | protected abstract int getThreadPollSize(); | 61 | protected abstract int getThreadPollSize(); |
58 | 62 | ||
59 | } | 63 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.thingsboard.server.service.script; | ||
18 | + | ||
19 | +import javax.script.ScriptException; | ||
20 | + | ||
21 | +public interface JsSandboxService { | ||
22 | + | ||
23 | + Object eval(String js) throws ScriptException; | ||
24 | + | ||
25 | + Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException; | ||
26 | + | ||
27 | +} |
application/src/main/java/org/thingsboard/server/service/script/JsScriptEngine.java
renamed from
application/src/main/java/org/thingsboard/server/service/script/NashornJsEngine.java
@@ -19,14 +19,11 @@ import com.fasterxml.jackson.core.type.TypeReference; | @@ -19,14 +19,11 @@ import com.fasterxml.jackson.core.type.TypeReference; | ||
19 | import com.fasterxml.jackson.databind.JsonNode; | 19 | import com.fasterxml.jackson.databind.JsonNode; |
20 | import com.fasterxml.jackson.databind.ObjectMapper; | 20 | import com.fasterxml.jackson.databind.ObjectMapper; |
21 | import com.google.common.collect.Sets; | 21 | import com.google.common.collect.Sets; |
22 | -import jdk.nashorn.api.scripting.NashornScriptEngineFactory; | ||
23 | import lombok.extern.slf4j.Slf4j; | 22 | import lombok.extern.slf4j.Slf4j; |
24 | import org.apache.commons.lang3.StringUtils; | 23 | import org.apache.commons.lang3.StringUtils; |
25 | import org.thingsboard.server.common.msg.TbMsg; | 24 | import org.thingsboard.server.common.msg.TbMsg; |
26 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 25 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
27 | 26 | ||
28 | -import javax.script.Invocable; | ||
29 | -import javax.script.ScriptEngine; | ||
30 | import javax.script.ScriptException; | 27 | import javax.script.ScriptException; |
31 | import java.util.Collections; | 28 | import java.util.Collections; |
32 | import java.util.Map; | 29 | import java.util.Map; |
@@ -34,7 +31,7 @@ import java.util.Set; | @@ -34,7 +31,7 @@ import java.util.Set; | ||
34 | 31 | ||
35 | 32 | ||
36 | @Slf4j | 33 | @Slf4j |
37 | -public class NashornJsEngine implements org.thingsboard.rule.engine.api.ScriptEngine { | 34 | +public class JsScriptEngine implements org.thingsboard.rule.engine.api.ScriptEngine { |
38 | 35 | ||
39 | public static final String MSG = "msg"; | 36 | public static final String MSG = "msg"; |
40 | public static final String METADATA = "metadata"; | 37 | public static final String METADATA = "metadata"; |
@@ -49,12 +46,14 @@ public class NashornJsEngine implements org.thingsboard.rule.engine.api.ScriptEn | @@ -49,12 +46,14 @@ public class NashornJsEngine implements org.thingsboard.rule.engine.api.ScriptEn | ||
49 | "\n}"; | 46 | "\n}"; |
50 | 47 | ||
51 | private static final ObjectMapper mapper = new ObjectMapper(); | 48 | private static final ObjectMapper mapper = new ObjectMapper(); |
52 | - private static NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); | ||
53 | - private ScriptEngine engine = factory.getScriptEngine(new String[]{"--no-java"}); | 49 | +// private static NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); |
50 | +// private ScriptEngine engine = factory.getScriptEngine(new String[]{"--no-java"}); | ||
51 | + private final JsSandboxService sandboxService; | ||
54 | 52 | ||
55 | private final String invokeFunctionName; | 53 | private final String invokeFunctionName; |
56 | 54 | ||
57 | - public NashornJsEngine(String script, String functionName, String... argNames) { | 55 | + public JsScriptEngine(JsSandboxService sandboxService, String script, String functionName, String... argNames) { |
56 | + this.sandboxService = sandboxService; | ||
58 | this.invokeFunctionName = "invokeInternal" + this.hashCode(); | 57 | this.invokeFunctionName = "invokeInternal" + this.hashCode(); |
59 | String msgArg; | 58 | String msgArg; |
60 | String metadataArg; | 59 | String metadataArg; |
@@ -75,7 +74,8 @@ public class NashornJsEngine implements org.thingsboard.rule.engine.api.ScriptEn | @@ -75,7 +74,8 @@ public class NashornJsEngine implements org.thingsboard.rule.engine.api.ScriptEn | ||
75 | 74 | ||
76 | private void compileScript(String script) { | 75 | private void compileScript(String script) { |
77 | try { | 76 | try { |
78 | - engine.eval(script); | 77 | + //engine.eval(script); |
78 | + sandboxService.eval(script); | ||
79 | } catch (ScriptException e) { | 79 | } catch (ScriptException e) { |
80 | log.warn("Failed to compile JS script: {}", e.getMessage(), e); | 80 | log.warn("Failed to compile JS script: {}", e.getMessage(), e); |
81 | throw new IllegalArgumentException("Can't compile script: " + e.getMessage()); | 81 | throw new IllegalArgumentException("Can't compile script: " + e.getMessage()); |
@@ -195,7 +195,8 @@ public class NashornJsEngine implements org.thingsboard.rule.engine.api.ScriptEn | @@ -195,7 +195,8 @@ public class NashornJsEngine implements org.thingsboard.rule.engine.api.ScriptEn | ||
195 | private JsonNode executeScript(TbMsg msg) throws ScriptException { | 195 | private JsonNode executeScript(TbMsg msg) throws ScriptException { |
196 | try { | 196 | try { |
197 | String[] inArgs = prepareArgs(msg); | 197 | String[] inArgs = prepareArgs(msg); |
198 | - String eval = ((Invocable)engine).invokeFunction(this.invokeFunctionName, inArgs[0], inArgs[1], inArgs[2]).toString(); | 198 | + //String eval = ((Invocable)engine).invokeFunction(this.invokeFunctionName, inArgs[0], inArgs[1], inArgs[2]).toString(); |
199 | + String eval = sandboxService.invokeFunction(this.invokeFunctionName, inArgs[0], inArgs[1], inArgs[2]).toString(); | ||
199 | return mapper.readTree(eval); | 200 | return mapper.readTree(eval); |
200 | } catch (ScriptException | IllegalArgumentException th) { | 201 | } catch (ScriptException | IllegalArgumentException th) { |
201 | throw th; | 202 | throw th; |
@@ -206,6 +207,6 @@ public class NashornJsEngine implements org.thingsboard.rule.engine.api.ScriptEn | @@ -206,6 +207,6 @@ public class NashornJsEngine implements org.thingsboard.rule.engine.api.ScriptEn | ||
206 | } | 207 | } |
207 | 208 | ||
208 | public void destroy() { | 209 | public void destroy() { |
209 | - engine = null; | 210 | + //engine = null; |
210 | } | 211 | } |
211 | } | 212 | } |
application/src/main/java/org/thingsboard/server/service/script/NashornJsSandboxService.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.thingsboard.server.service.script; | ||
18 | + | ||
19 | +import delight.nashornsandbox.NashornSandbox; | ||
20 | +import delight.nashornsandbox.NashornSandboxes; | ||
21 | +import lombok.extern.slf4j.Slf4j; | ||
22 | +import org.springframework.beans.factory.annotation.Value; | ||
23 | +import org.springframework.stereotype.Service; | ||
24 | + | ||
25 | +import javax.annotation.PostConstruct; | ||
26 | +import javax.annotation.PreDestroy; | ||
27 | +import javax.script.ScriptException; | ||
28 | +import java.util.concurrent.ExecutorService; | ||
29 | +import java.util.concurrent.Executors; | ||
30 | + | ||
31 | +@Slf4j | ||
32 | +@Service | ||
33 | +public class NashornJsSandboxService implements JsSandboxService { | ||
34 | + | ||
35 | + @Value("${actors.rule.js_sandbox.monitor_thread_pool_size}") | ||
36 | + private int monitorThreadPoolSize; | ||
37 | + | ||
38 | + @Value("${actors.rule.js_sandbox.max_cpu_time}") | ||
39 | + private long maxCpuTime; | ||
40 | + | ||
41 | + private NashornSandbox sandbox = NashornSandboxes.create(); | ||
42 | + private ExecutorService monitorExecutorService; | ||
43 | + | ||
44 | + @PostConstruct | ||
45 | + public void init() { | ||
46 | + monitorExecutorService = Executors.newFixedThreadPool(monitorThreadPoolSize); | ||
47 | + sandbox.setExecutor(monitorExecutorService); | ||
48 | + sandbox.setMaxCPUTime(maxCpuTime); | ||
49 | + sandbox.allowNoBraces(false); | ||
50 | + sandbox.setMaxPreparedStatements(30); | ||
51 | + } | ||
52 | + | ||
53 | + @PreDestroy | ||
54 | + public void stop() { | ||
55 | + if (monitorExecutorService != null) { | ||
56 | + monitorExecutorService.shutdownNow(); | ||
57 | + } | ||
58 | + } | ||
59 | + | ||
60 | + @Override | ||
61 | + public Object eval(String js) throws ScriptException { | ||
62 | + return sandbox.eval(js); | ||
63 | + } | ||
64 | + | ||
65 | + @Override | ||
66 | + public Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException { | ||
67 | + return sandbox.getSandboxedInvocable().invokeFunction(name, args); | ||
68 | + } | ||
69 | + | ||
70 | +} |
@@ -238,6 +238,11 @@ actors: | @@ -238,6 +238,11 @@ actors: | ||
238 | mail_thread_pool_size: "${ACTORS_RULE_MAIL_THREAD_POOL_SIZE:10}" | 238 | mail_thread_pool_size: "${ACTORS_RULE_MAIL_THREAD_POOL_SIZE:10}" |
239 | # Specify thread pool size for external call service | 239 | # Specify thread pool size for external call service |
240 | external_call_thread_pool_size: "${ACTORS_RULE_EXTERNAL_CALL_THREAD_POOL_SIZE:10}" | 240 | external_call_thread_pool_size: "${ACTORS_RULE_EXTERNAL_CALL_THREAD_POOL_SIZE:10}" |
241 | + js_sandbox: | ||
242 | + # Specify thread pool size for JavaScript sandbox resource monitor | ||
243 | + monitor_thread_pool_size: "${ACTORS_RULE_JS_SANDBOX_MONITOR_THREAD_POOL_SIZE:4}" | ||
244 | + # Maximum CPU time in milliseconds allowed for script execution | ||
245 | + max_cpu_time: "${ACTORS_RULE_JS_SANDBOX_MAX_CPU_TIME:100}" | ||
241 | chain: | 246 | chain: |
242 | # Errors for particular actor are persisted once per specified amount of milliseconds | 247 | # Errors for particular actor are persisted once per specified amount of milliseconds |
243 | error_persist_frequency: "${ACTORS_RULE_CHAIN_ERROR_FREQUENCY:3000}" | 248 | error_persist_frequency: "${ACTORS_RULE_CHAIN_ERROR_FREQUENCY:3000}" |
application/src/test/java/org/thingsboard/server/service/script/JsScriptEngineTest.java
renamed from
application/src/test/java/org/thingsboard/server/service/script/NashornJsEngineTest.java
@@ -17,6 +17,8 @@ package org.thingsboard.server.service.script; | @@ -17,6 +17,8 @@ package org.thingsboard.server.service.script; | ||
17 | 17 | ||
18 | import com.datastax.driver.core.utils.UUIDs; | 18 | import com.datastax.driver.core.utils.UUIDs; |
19 | import com.google.common.collect.Sets; | 19 | import com.google.common.collect.Sets; |
20 | +import org.junit.After; | ||
21 | +import org.junit.Before; | ||
20 | import org.junit.Test; | 22 | import org.junit.Test; |
21 | import org.thingsboard.rule.engine.api.ScriptEngine; | 23 | import org.thingsboard.rule.engine.api.ScriptEngine; |
22 | import org.thingsboard.server.common.msg.TbMsg; | 24 | import org.thingsboard.server.common.msg.TbMsg; |
@@ -25,17 +27,30 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; | @@ -25,17 +27,30 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; | ||
25 | import javax.script.ScriptException; | 27 | import javax.script.ScriptException; |
26 | 28 | ||
27 | import java.util.Set; | 29 | import java.util.Set; |
30 | +import java.util.concurrent.ExecutorService; | ||
31 | +import java.util.concurrent.Executors; | ||
28 | 32 | ||
29 | import static org.junit.Assert.*; | 33 | import static org.junit.Assert.*; |
30 | 34 | ||
31 | -public class NashornJsEngineTest { | 35 | +public class JsScriptEngineTest { |
32 | 36 | ||
33 | private ScriptEngine scriptEngine; | 37 | private ScriptEngine scriptEngine; |
38 | + private TestNashornJsSandboxService jsSandboxService; | ||
39 | + | ||
40 | + @Before | ||
41 | + public void beforeTest() throws Exception { | ||
42 | + jsSandboxService = new TestNashornJsSandboxService(1, 100); | ||
43 | + } | ||
44 | + | ||
45 | + @After | ||
46 | + public void afterTest() throws Exception { | ||
47 | + jsSandboxService.destroy(); | ||
48 | + } | ||
34 | 49 | ||
35 | @Test | 50 | @Test |
36 | public void msgCanBeUpdated() throws ScriptException { | 51 | public void msgCanBeUpdated() throws ScriptException { |
37 | String function = "metadata.temp = metadata.temp * 10; return {metadata: metadata};"; | 52 | String function = "metadata.temp = metadata.temp * 10; return {metadata: metadata};"; |
38 | - scriptEngine = new NashornJsEngine(function, "Transform"); | 53 | + scriptEngine = new JsScriptEngine(jsSandboxService, function, "Transform"); |
39 | 54 | ||
40 | TbMsgMetaData metaData = new TbMsgMetaData(); | 55 | TbMsgMetaData metaData = new TbMsgMetaData(); |
41 | metaData.putValue("temp", "7"); | 56 | metaData.putValue("temp", "7"); |
@@ -51,7 +66,7 @@ public class NashornJsEngineTest { | @@ -51,7 +66,7 @@ public class NashornJsEngineTest { | ||
51 | @Test | 66 | @Test |
52 | public void newAttributesCanBeAddedInMsg() throws ScriptException { | 67 | public void newAttributesCanBeAddedInMsg() throws ScriptException { |
53 | String function = "metadata.newAttr = metadata.humidity - msg.passed; return {metadata: metadata};"; | 68 | String function = "metadata.newAttr = metadata.humidity - msg.passed; return {metadata: metadata};"; |
54 | - scriptEngine = new NashornJsEngine(function, "Transform"); | 69 | + scriptEngine = new JsScriptEngine(jsSandboxService, function, "Transform"); |
55 | TbMsgMetaData metaData = new TbMsgMetaData(); | 70 | TbMsgMetaData metaData = new TbMsgMetaData(); |
56 | metaData.putValue("temp", "7"); | 71 | metaData.putValue("temp", "7"); |
57 | metaData.putValue("humidity", "99"); | 72 | metaData.putValue("humidity", "99"); |
@@ -66,7 +81,7 @@ public class NashornJsEngineTest { | @@ -66,7 +81,7 @@ public class NashornJsEngineTest { | ||
66 | @Test | 81 | @Test |
67 | public void payloadCanBeUpdated() throws ScriptException { | 82 | public void payloadCanBeUpdated() throws ScriptException { |
68 | String function = "msg.passed = msg.passed * metadata.temp; msg.bigObj.newProp = 'Ukraine'; return {msg: msg};"; | 83 | String function = "msg.passed = msg.passed * metadata.temp; msg.bigObj.newProp = 'Ukraine'; return {msg: msg};"; |
69 | - scriptEngine = new NashornJsEngine(function, "Transform"); | 84 | + scriptEngine = new JsScriptEngine(jsSandboxService, function, "Transform"); |
70 | TbMsgMetaData metaData = new TbMsgMetaData(); | 85 | TbMsgMetaData metaData = new TbMsgMetaData(); |
71 | metaData.putValue("temp", "7"); | 86 | metaData.putValue("temp", "7"); |
72 | metaData.putValue("humidity", "99"); | 87 | metaData.putValue("humidity", "99"); |
@@ -83,7 +98,7 @@ public class NashornJsEngineTest { | @@ -83,7 +98,7 @@ public class NashornJsEngineTest { | ||
83 | @Test | 98 | @Test |
84 | public void metadataAccessibleForFilter() throws ScriptException { | 99 | public void metadataAccessibleForFilter() throws ScriptException { |
85 | String function = "return metadata.humidity < 15;"; | 100 | String function = "return metadata.humidity < 15;"; |
86 | - scriptEngine = new NashornJsEngine(function, "Filter"); | 101 | + scriptEngine = new JsScriptEngine(jsSandboxService, function, "Filter"); |
87 | TbMsgMetaData metaData = new TbMsgMetaData(); | 102 | TbMsgMetaData metaData = new TbMsgMetaData(); |
88 | metaData.putValue("temp", "7"); | 103 | metaData.putValue("temp", "7"); |
89 | metaData.putValue("humidity", "99"); | 104 | metaData.putValue("humidity", "99"); |
@@ -96,7 +111,7 @@ public class NashornJsEngineTest { | @@ -96,7 +111,7 @@ public class NashornJsEngineTest { | ||
96 | @Test | 111 | @Test |
97 | public void dataAccessibleForFilter() throws ScriptException { | 112 | public void dataAccessibleForFilter() throws ScriptException { |
98 | String function = "return msg.passed < 15 && msg.name === 'Vit' && metadata.temp == 7 && msg.bigObj.prop == 42;"; | 113 | String function = "return msg.passed < 15 && msg.name === 'Vit' && metadata.temp == 7 && msg.bigObj.prop == 42;"; |
99 | - scriptEngine = new NashornJsEngine(function, "Filter"); | 114 | + scriptEngine = new JsScriptEngine(jsSandboxService, function, "Filter"); |
100 | TbMsgMetaData metaData = new TbMsgMetaData(); | 115 | TbMsgMetaData metaData = new TbMsgMetaData(); |
101 | metaData.putValue("temp", "7"); | 116 | metaData.putValue("temp", "7"); |
102 | metaData.putValue("humidity", "99"); | 117 | metaData.putValue("humidity", "99"); |
@@ -116,7 +131,7 @@ public class NashornJsEngineTest { | @@ -116,7 +131,7 @@ public class NashornJsEngineTest { | ||
116 | "};\n" + | 131 | "};\n" + |
117 | "\n" + | 132 | "\n" + |
118 | "return nextRelation(metadata, msg);"; | 133 | "return nextRelation(metadata, msg);"; |
119 | - scriptEngine = new NashornJsEngine(jsCode, "Switch"); | 134 | + scriptEngine = new JsScriptEngine(jsSandboxService, jsCode, "Switch"); |
120 | TbMsgMetaData metaData = new TbMsgMetaData(); | 135 | TbMsgMetaData metaData = new TbMsgMetaData(); |
121 | metaData.putValue("temp", "10"); | 136 | metaData.putValue("temp", "10"); |
122 | metaData.putValue("humidity", "99"); | 137 | metaData.putValue("humidity", "99"); |
@@ -137,7 +152,7 @@ public class NashornJsEngineTest { | @@ -137,7 +152,7 @@ public class NashornJsEngineTest { | ||
137 | "};\n" + | 152 | "};\n" + |
138 | "\n" + | 153 | "\n" + |
139 | "return nextRelation(metadata, msg);"; | 154 | "return nextRelation(metadata, msg);"; |
140 | - scriptEngine = new NashornJsEngine(jsCode, "Switch"); | 155 | + scriptEngine = new JsScriptEngine(jsSandboxService, jsCode, "Switch"); |
141 | TbMsgMetaData metaData = new TbMsgMetaData(); | 156 | TbMsgMetaData metaData = new TbMsgMetaData(); |
142 | metaData.putValue("temp", "10"); | 157 | metaData.putValue("temp", "10"); |
143 | metaData.putValue("humidity", "99"); | 158 | metaData.putValue("humidity", "99"); |
application/src/test/java/org/thingsboard/server/service/script/TestNashornJsSandboxService.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.thingsboard.server.service.script; | ||
18 | + | ||
19 | +import delight.nashornsandbox.NashornSandbox; | ||
20 | +import delight.nashornsandbox.NashornSandboxes; | ||
21 | + | ||
22 | +import javax.script.ScriptException; | ||
23 | +import java.util.concurrent.ExecutorService; | ||
24 | +import java.util.concurrent.Executors; | ||
25 | + | ||
26 | +public class TestNashornJsSandboxService implements JsSandboxService { | ||
27 | + | ||
28 | + private NashornSandbox sandbox = NashornSandboxes.create(); | ||
29 | + private ExecutorService monitorExecutorService; | ||
30 | + | ||
31 | + public TestNashornJsSandboxService(int monitorThreadPoolSize, long maxCpuTime) { | ||
32 | + monitorExecutorService = Executors.newFixedThreadPool(monitorThreadPoolSize); | ||
33 | + sandbox.setExecutor(monitorExecutorService); | ||
34 | + sandbox.setMaxCPUTime(maxCpuTime); | ||
35 | + sandbox.allowNoBraces(false); | ||
36 | + sandbox.setMaxPreparedStatements(30); | ||
37 | + } | ||
38 | + | ||
39 | + @Override | ||
40 | + public Object eval(String js) throws ScriptException { | ||
41 | + return sandbox.eval(js); | ||
42 | + } | ||
43 | + | ||
44 | + @Override | ||
45 | + public Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException { | ||
46 | + return sandbox.getSandboxedInvocable().invokeFunction(name, args); | ||
47 | + } | ||
48 | + | ||
49 | + public void destroy() { | ||
50 | + if (monitorExecutorService != null) { | ||
51 | + monitorExecutorService.shutdownNow(); | ||
52 | + } | ||
53 | + } | ||
54 | +} |
@@ -81,6 +81,7 @@ | @@ -81,6 +81,7 @@ | ||
81 | org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/* | 81 | org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/* |
82 | </sonar.exclusions> | 82 | </sonar.exclusions> |
83 | <elasticsearch.version>5.0.2</elasticsearch.version> | 83 | <elasticsearch.version>5.0.2</elasticsearch.version> |
84 | + <delight-nashorn-sandbox.version>0.1.14</delight-nashorn-sandbox.version> | ||
84 | </properties> | 85 | </properties> |
85 | 86 | ||
86 | <modules> | 87 | <modules> |
@@ -814,6 +815,11 @@ | @@ -814,6 +815,11 @@ | ||
814 | <artifactId>rest</artifactId> | 815 | <artifactId>rest</artifactId> |
815 | <version>${elasticsearch.version}</version> | 816 | <version>${elasticsearch.version}</version> |
816 | </dependency> | 817 | </dependency> |
818 | + <dependency> | ||
819 | + <groupId>org.javadelight</groupId> | ||
820 | + <artifactId>delight-nashorn-sandbox</artifactId> | ||
821 | + <version>${delight-nashorn-sandbox.version}</version> | ||
822 | + </dependency> | ||
817 | </dependencies> | 823 | </dependencies> |
818 | </dependencyManagement> | 824 | </dependencyManagement> |
819 | 825 |