Showing
38 changed files
with
283 additions
and
225 deletions
@@ -32,6 +32,8 @@ import org.thingsboard.server.actors.shared.rule.SystemRuleManager; | @@ -32,6 +32,8 @@ import org.thingsboard.server.actors.shared.rule.SystemRuleManager; | ||
32 | import org.thingsboard.server.actors.tenant.RuleChainDeviceMsg; | 32 | import org.thingsboard.server.actors.tenant.RuleChainDeviceMsg; |
33 | import org.thingsboard.server.actors.tenant.TenantActor; | 33 | import org.thingsboard.server.actors.tenant.TenantActor; |
34 | import org.thingsboard.server.common.data.Tenant; | 34 | import org.thingsboard.server.common.data.Tenant; |
35 | +import org.thingsboard.server.common.data.id.PluginId; | ||
36 | +import org.thingsboard.server.common.data.id.RuleId; | ||
35 | import org.thingsboard.server.common.data.id.TenantId; | 37 | import org.thingsboard.server.common.data.id.TenantId; |
36 | import org.thingsboard.server.common.data.page.PageDataIterable; | 38 | import org.thingsboard.server.common.data.page.PageDataIterable; |
37 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 39 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
@@ -149,14 +151,16 @@ public class AppActor extends ContextAwareActor { | @@ -149,14 +151,16 @@ public class AppActor extends ContextAwareActor { | ||
149 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { | 151 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { |
150 | ActorRef target = null; | 152 | ActorRef target = null; |
151 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { | 153 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { |
152 | - if (msg.getPluginId().isPresent()) { | ||
153 | - target = pluginManager.getOrCreatePluginActor(this.context(), msg.getPluginId().get()); | ||
154 | - } else if (msg.getRuleId().isPresent()) { | ||
155 | - Optional<ActorRef> ref = ruleManager.update(this.context(), msg.getRuleId().get(), msg.getEvent()); | 154 | + Optional<PluginId> pluginId = msg.getPluginId(); |
155 | + Optional<RuleId> ruleId = msg.getRuleId(); | ||
156 | + if (pluginId.isPresent()) { | ||
157 | + target = pluginManager.getOrCreatePluginActor(this.context(), pluginId.get()); | ||
158 | + } else if (ruleId.isPresent()) { | ||
159 | + Optional<ActorRef> ref = ruleManager.update(this.context(), ruleId.get(), msg.getEvent()); | ||
156 | if (ref.isPresent()) { | 160 | if (ref.isPresent()) { |
157 | target = ref.get(); | 161 | target = ref.get(); |
158 | } else { | 162 | } else { |
159 | - logger.debug("Failed to find actor for rule: [{}]", msg.getRuleId()); | 163 | + logger.debug("Failed to find actor for rule: [{}]", ruleId); |
160 | return; | 164 | return; |
161 | } | 165 | } |
162 | } | 166 | } |
@@ -32,6 +32,8 @@ import org.thingsboard.server.actors.shared.plugin.TenantPluginManager; | @@ -32,6 +32,8 @@ import org.thingsboard.server.actors.shared.plugin.TenantPluginManager; | ||
32 | import org.thingsboard.server.actors.shared.rule.RuleManager; | 32 | import org.thingsboard.server.actors.shared.rule.RuleManager; |
33 | import org.thingsboard.server.actors.shared.rule.TenantRuleManager; | 33 | import org.thingsboard.server.actors.shared.rule.TenantRuleManager; |
34 | import org.thingsboard.server.common.data.id.DeviceId; | 34 | import org.thingsboard.server.common.data.id.DeviceId; |
35 | +import org.thingsboard.server.common.data.id.PluginId; | ||
36 | +import org.thingsboard.server.common.data.id.RuleId; | ||
35 | import org.thingsboard.server.common.data.id.TenantId; | 37 | import org.thingsboard.server.common.data.id.TenantId; |
36 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; | 38 | import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; |
37 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; | 39 | import org.thingsboard.server.common.msg.device.ToDeviceActorMsg; |
@@ -126,16 +128,18 @@ public class TenantActor extends ContextAwareActor { | @@ -126,16 +128,18 @@ public class TenantActor extends ContextAwareActor { | ||
126 | } | 128 | } |
127 | 129 | ||
128 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { | 130 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { |
129 | - if (msg.getPluginId().isPresent()) { | ||
130 | - ActorRef pluginActor = pluginManager.getOrCreatePluginActor(this.context(), msg.getPluginId().get()); | 131 | + Optional<PluginId> pluginId = msg.getPluginId(); |
132 | + Optional<RuleId> ruleId = msg.getRuleId(); | ||
133 | + if (pluginId.isPresent()) { | ||
134 | + ActorRef pluginActor = pluginManager.getOrCreatePluginActor(this.context(), pluginId.get()); | ||
131 | pluginActor.tell(msg, ActorRef.noSender()); | 135 | pluginActor.tell(msg, ActorRef.noSender()); |
132 | - } else if (msg.getRuleId().isPresent()) { | 136 | + } else if (ruleId.isPresent()) { |
133 | ActorRef target; | 137 | ActorRef target; |
134 | - Optional<ActorRef> ref = ruleManager.update(this.context(), msg.getRuleId().get(), msg.getEvent()); | 138 | + Optional<ActorRef> ref = ruleManager.update(this.context(), ruleId.get(), msg.getEvent()); |
135 | if (ref.isPresent()) { | 139 | if (ref.isPresent()) { |
136 | target = ref.get(); | 140 | target = ref.get(); |
137 | } else { | 141 | } else { |
138 | - logger.debug("Failed to find actor for rule: [{}]", msg.getRuleId()); | 142 | + logger.debug("Failed to find actor for rule: [{}]", ruleId); |
139 | return; | 143 | return; |
140 | } | 144 | } |
141 | target.tell(msg, ActorRef.noSender()); | 145 | target.tell(msg, ActorRef.noSender()); |
@@ -64,7 +64,7 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt | @@ -64,7 +64,7 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt | ||
64 | public static final String FORM_BASED_LOGIN_ENTRY_POINT = "/api/auth/login"; | 64 | public static final String FORM_BASED_LOGIN_ENTRY_POINT = "/api/auth/login"; |
65 | public static final String PUBLIC_LOGIN_ENTRY_POINT = "/api/auth/login/public"; | 65 | public static final String PUBLIC_LOGIN_ENTRY_POINT = "/api/auth/login/public"; |
66 | public static final String TOKEN_REFRESH_ENTRY_POINT = "/api/auth/token"; | 66 | public static final String TOKEN_REFRESH_ENTRY_POINT = "/api/auth/token"; |
67 | - public static final String[] NON_TOKEN_BASED_AUTH_ENTRY_POINTS = new String[] {"/index.html", "/static/**", "/api/noauth/**", "/webjars/**"}; | 67 | + protected static final String[] NON_TOKEN_BASED_AUTH_ENTRY_POINTS = new String[] {"/index.html", "/static/**", "/api/noauth/**", "/webjars/**"}; |
68 | public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**"; | 68 | public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**"; |
69 | public static final String WS_TOKEN_BASED_AUTH_ENTRY_POINT = "/api/ws/**"; | 69 | public static final String WS_TOKEN_BASED_AUTH_ENTRY_POINT = "/api/ws/**"; |
70 | 70 |
@@ -103,13 +103,13 @@ public class AuthController extends BaseController { | @@ -103,13 +103,13 @@ public class AuthController extends BaseController { | ||
103 | HttpStatus responseStatus; | 103 | HttpStatus responseStatus; |
104 | UserCredentials userCredentials = userService.findUserCredentialsByActivateToken(activateToken); | 104 | UserCredentials userCredentials = userService.findUserCredentialsByActivateToken(activateToken); |
105 | if (userCredentials != null) { | 105 | if (userCredentials != null) { |
106 | - String createPasswordURI = "/login/createPassword"; | 106 | + String createURI = "/login/createPassword"; |
107 | try { | 107 | try { |
108 | - URI location = new URI(createPasswordURI + "?activateToken=" + activateToken); | 108 | + URI location = new URI(createURI + "?activateToken=" + activateToken); |
109 | headers.setLocation(location); | 109 | headers.setLocation(location); |
110 | responseStatus = HttpStatus.SEE_OTHER; | 110 | responseStatus = HttpStatus.SEE_OTHER; |
111 | } catch (URISyntaxException e) { | 111 | } catch (URISyntaxException e) { |
112 | - log.error("Unable to create URI with address [{}]", createPasswordURI); | 112 | + log.error("Unable to create URI with address [{}]", createURI); |
113 | responseStatus = HttpStatus.BAD_REQUEST; | 113 | responseStatus = HttpStatus.BAD_REQUEST; |
114 | } | 114 | } |
115 | } else { | 115 | } else { |
@@ -126,10 +126,10 @@ public class AuthController extends BaseController { | @@ -126,10 +126,10 @@ public class AuthController extends BaseController { | ||
126 | try { | 126 | try { |
127 | UserCredentials userCredentials = userService.requestPasswordReset(email); | 127 | UserCredentials userCredentials = userService.requestPasswordReset(email); |
128 | String baseUrl = constructBaseUrl(request); | 128 | String baseUrl = constructBaseUrl(request); |
129 | - String resetPasswordUrl = String.format("%s/api/noauth/resetPassword?resetToken=%s", baseUrl, | 129 | + String resetUrl = String.format("%s/api/noauth/resetPassword?resetToken=%s", baseUrl, |
130 | userCredentials.getResetToken()); | 130 | userCredentials.getResetToken()); |
131 | 131 | ||
132 | - mailService.sendResetPasswordEmail(resetPasswordUrl, email); | 132 | + mailService.sendResetPasswordEmail(resetUrl, email); |
133 | } catch (Exception e) { | 133 | } catch (Exception e) { |
134 | throw handleException(e); | 134 | throw handleException(e); |
135 | } | 135 | } |
@@ -140,15 +140,15 @@ public class AuthController extends BaseController { | @@ -140,15 +140,15 @@ public class AuthController extends BaseController { | ||
140 | @RequestParam(value = "resetToken") String resetToken) { | 140 | @RequestParam(value = "resetToken") String resetToken) { |
141 | HttpHeaders headers = new HttpHeaders(); | 141 | HttpHeaders headers = new HttpHeaders(); |
142 | HttpStatus responseStatus; | 142 | HttpStatus responseStatus; |
143 | - String resetPasswordURI = "/login/resetPassword"; | 143 | + String resetURI = "/login/resetPassword"; |
144 | UserCredentials userCredentials = userService.findUserCredentialsByResetToken(resetToken); | 144 | UserCredentials userCredentials = userService.findUserCredentialsByResetToken(resetToken); |
145 | if (userCredentials != null) { | 145 | if (userCredentials != null) { |
146 | try { | 146 | try { |
147 | - URI location = new URI(resetPasswordURI + "?resetToken=" + resetToken); | 147 | + URI location = new URI(resetURI + "?resetToken=" + resetToken); |
148 | headers.setLocation(location); | 148 | headers.setLocation(location); |
149 | responseStatus = HttpStatus.SEE_OTHER; | 149 | responseStatus = HttpStatus.SEE_OTHER; |
150 | } catch (URISyntaxException e) { | 150 | } catch (URISyntaxException e) { |
151 | - log.error("Unable to create URI with address [{}]", resetPasswordURI); | 151 | + log.error("Unable to create URI with address [{}]", resetURI); |
152 | responseStatus = HttpStatus.BAD_REQUEST; | 152 | responseStatus = HttpStatus.BAD_REQUEST; |
153 | } | 153 | } |
154 | } else { | 154 | } else { |
@@ -267,9 +267,7 @@ public class EntityRelationController extends BaseController { | @@ -267,9 +267,7 @@ public class EntityRelationController extends BaseController { | ||
267 | if (strRelationTypeGroup != null && strRelationTypeGroup.trim().length()>0) { | 267 | if (strRelationTypeGroup != null && strRelationTypeGroup.trim().length()>0) { |
268 | try { | 268 | try { |
269 | result = RelationTypeGroup.valueOf(strRelationTypeGroup); | 269 | result = RelationTypeGroup.valueOf(strRelationTypeGroup); |
270 | - } catch (IllegalArgumentException e) { | ||
271 | - result = defaultValue; | ||
272 | - } | 270 | + } catch (IllegalArgumentException e) { } |
273 | } | 271 | } |
274 | return result; | 272 | return result; |
275 | } | 273 | } |
@@ -71,7 +71,7 @@ public class PluginApiController extends BaseController { | @@ -71,7 +71,7 @@ public class PluginApiController extends BaseController { | ||
71 | TenantId tenantId = getCurrentUser().getTenantId(); | 71 | TenantId tenantId = getCurrentUser().getTenantId(); |
72 | CustomerId customerId = getCurrentUser().getCustomerId(); | 72 | CustomerId customerId = getCurrentUser().getCustomerId(); |
73 | if (validatePluginAccess(pluginMd, tenantId, customerId)) { | 73 | if (validatePluginAccess(pluginMd, tenantId, customerId)) { |
74 | - if(ModelConstants.NULL_UUID.equals(tenantId.getId())){ | 74 | + if(tenantId != null && ModelConstants.NULL_UUID.equals(tenantId.getId())){ |
75 | tenantId = null; | 75 | tenantId = null; |
76 | } | 76 | } |
77 | PluginApiCallSecurityContext securityCtx = new PluginApiCallSecurityContext(pluginMd.getTenantId(), pluginMd.getId(), tenantId, customerId); | 77 | PluginApiCallSecurityContext securityCtx = new PluginApiCallSecurityContext(pluginMd.getTenantId(), pluginMd.getId(), tenantId, customerId); |
@@ -97,7 +97,7 @@ public class PluginApiController extends BaseController { | @@ -97,7 +97,7 @@ public class PluginApiController extends BaseController { | ||
97 | validUser = true; | 97 | validUser = true; |
98 | } | 98 | } |
99 | } else { | 99 | } else { |
100 | - if ((pluginMd.isPublicAccess() || tenantAdministrator) && tenantId.equals(pluginMd.getTenantId())) { | 100 | + if ((pluginMd.isPublicAccess() || tenantAdministrator) && tenantId != null && tenantId.equals(pluginMd.getTenantId())) { |
101 | // All tenant users can access public tenant plugins. Only tenant | 101 | // All tenant users can access public tenant plugins. Only tenant |
102 | // administrator can access private tenant plugins | 102 | // administrator can access private tenant plugins |
103 | validUser = true; | 103 | validUser = true; |
@@ -95,6 +95,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI | @@ -95,6 +95,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI | ||
95 | future.onMsg(msg); | 95 | future.onMsg(msg); |
96 | } catch (InterruptedException e) { | 96 | } catch (InterruptedException e) { |
97 | log.warn("Failed to report created session!"); | 97 | log.warn("Failed to report created session!"); |
98 | + Thread.currentThread().interrupt(); | ||
98 | } | 99 | } |
99 | } else { | 100 | } else { |
100 | log.warn("Failed to lookup pending session!"); | 101 | log.warn("Failed to lookup pending session!"); |
@@ -117,6 +118,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI | @@ -117,6 +118,7 @@ public class ClusterGrpcService extends ClusterRpcServiceGrpc.ClusterRpcServiceI | ||
117 | log.info("RPC server stopped!"); | 118 | log.info("RPC server stopped!"); |
118 | } catch (InterruptedException e) { | 119 | } catch (InterruptedException e) { |
119 | log.warn("Failed to onStop RPC server!"); | 120 | log.warn("Failed to onStop RPC server!"); |
121 | + Thread.currentThread().interrupt(); | ||
120 | } | 122 | } |
121 | } | 123 | } |
122 | } | 124 | } |
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
@@ -51,6 +51,7 @@ import org.thingsboard.server.dao.widget.WidgetTypeService; | @@ -51,6 +51,7 @@ import org.thingsboard.server.dao.widget.WidgetTypeService; | ||
51 | import org.thingsboard.server.dao.widget.WidgetsBundleService; | 51 | import org.thingsboard.server.dao.widget.WidgetsBundleService; |
52 | 52 | ||
53 | import java.io.IOException; | 53 | import java.io.IOException; |
54 | +import java.nio.file.DirectoryStream; | ||
54 | import java.nio.file.Files; | 55 | import java.nio.file.Files; |
55 | import java.nio.file.Path; | 56 | import java.nio.file.Path; |
56 | import java.nio.file.Paths; | 57 | import java.nio.file.Paths; |
@@ -138,7 +139,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -138,7 +139,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
138 | node.put("timeout", "10000"); | 139 | node.put("timeout", "10000"); |
139 | node.put("enableTls", "false"); | 140 | node.put("enableTls", "false"); |
140 | node.put("username", ""); | 141 | node.put("username", ""); |
141 | - node.put("password", ""); | 142 | + node.put("password", ""); //NOSONAR, key used to identify password field (not password value itself) |
142 | mailSettings.setJsonValue(node); | 143 | mailSettings.setJsonValue(node); |
143 | adminSettingsService.saveAdminSettings(mailSettings); | 144 | adminSettingsService.saveAdminSettings(mailSettings); |
144 | } | 145 | } |
@@ -146,33 +147,34 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -146,33 +147,34 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
146 | @Override | 147 | @Override |
147 | public void loadSystemWidgets() throws Exception { | 148 | public void loadSystemWidgets() throws Exception { |
148 | Path widgetBundlesDir = Paths.get(dataDir, JSON_DIR, SYSTEM_DIR, WIDGET_BUNDLES_DIR); | 149 | Path widgetBundlesDir = Paths.get(dataDir, JSON_DIR, SYSTEM_DIR, WIDGET_BUNDLES_DIR); |
149 | - Files.newDirectoryStream(widgetBundlesDir, path -> path.toString().endsWith(".json")) | ||
150 | - .forEach( | ||
151 | - path -> { | ||
152 | - try { | ||
153 | - JsonNode widgetsBundleDescriptorJson = objectMapper.readTree(path.toFile()); | ||
154 | - JsonNode widgetsBundleJson = widgetsBundleDescriptorJson.get("widgetsBundle"); | ||
155 | - WidgetsBundle widgetsBundle = objectMapper.treeToValue(widgetsBundleJson, WidgetsBundle.class); | ||
156 | - WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); | ||
157 | - JsonNode widgetTypesArrayJson = widgetsBundleDescriptorJson.get("widgetTypes"); | ||
158 | - widgetTypesArrayJson.forEach( | ||
159 | - widgetTypeJson -> { | ||
160 | - try { | ||
161 | - WidgetType widgetType = objectMapper.treeToValue(widgetTypeJson, WidgetType.class); | ||
162 | - widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); | ||
163 | - widgetTypeService.saveWidgetType(widgetType); | ||
164 | - } catch (Exception e) { | ||
165 | - log.error("Unable to load widget type from json: [{}]", path.toString()); | ||
166 | - throw new RuntimeException("Unable to load widget type from json", e); | ||
167 | - } | 150 | + try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(widgetBundlesDir, path -> path.toString().endsWith(".json"))) { |
151 | + dirStream.forEach( | ||
152 | + path -> { | ||
153 | + try { | ||
154 | + JsonNode widgetsBundleDescriptorJson = objectMapper.readTree(path.toFile()); | ||
155 | + JsonNode widgetsBundleJson = widgetsBundleDescriptorJson.get("widgetsBundle"); | ||
156 | + WidgetsBundle widgetsBundle = objectMapper.treeToValue(widgetsBundleJson, WidgetsBundle.class); | ||
157 | + WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); | ||
158 | + JsonNode widgetTypesArrayJson = widgetsBundleDescriptorJson.get("widgetTypes"); | ||
159 | + widgetTypesArrayJson.forEach( | ||
160 | + widgetTypeJson -> { | ||
161 | + try { | ||
162 | + WidgetType widgetType = objectMapper.treeToValue(widgetTypeJson, WidgetType.class); | ||
163 | + widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); | ||
164 | + widgetTypeService.saveWidgetType(widgetType); | ||
165 | + } catch (Exception e) { | ||
166 | + log.error("Unable to load widget type from json: [{}]", path.toString()); | ||
167 | + throw new RuntimeException("Unable to load widget type from json", e); | ||
168 | } | 168 | } |
169 | - ); | ||
170 | - } catch (Exception e) { | ||
171 | - log.error("Unable to load widgets bundle from json: [{}]", path.toString()); | ||
172 | - throw new RuntimeException("Unable to load widgets bundle from json", e); | ||
173 | - } | 169 | + } |
170 | + ); | ||
171 | + } catch (Exception e) { | ||
172 | + log.error("Unable to load widgets bundle from json: [{}]", path.toString()); | ||
173 | + throw new RuntimeException("Unable to load widgets bundle from json", e); | ||
174 | } | 174 | } |
175 | - ); | 175 | + } |
176 | + ); | ||
177 | + } | ||
176 | } | 178 | } |
177 | 179 | ||
178 | @Override | 180 | @Override |
@@ -279,67 +281,69 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -279,67 +281,69 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
279 | } | 281 | } |
280 | 282 | ||
281 | private void loadPlugins(Path pluginsDir, TenantId tenantId) throws Exception{ | 283 | private void loadPlugins(Path pluginsDir, TenantId tenantId) throws Exception{ |
282 | - Files.newDirectoryStream(pluginsDir, path -> path.toString().endsWith(".json")) | ||
283 | - .forEach( | ||
284 | - path -> { | ||
285 | - try { | ||
286 | - JsonNode pluginJson = objectMapper.readTree(path.toFile()); | ||
287 | - PluginMetaData plugin = objectMapper.treeToValue(pluginJson, PluginMetaData.class); | ||
288 | - plugin.setTenantId(tenantId); | ||
289 | - if (plugin.getState() == ComponentLifecycleState.ACTIVE) { | ||
290 | - plugin.setState(ComponentLifecycleState.SUSPENDED); | ||
291 | - PluginMetaData savedPlugin = pluginService.savePlugin(plugin); | ||
292 | - pluginService.activatePluginById(savedPlugin.getId()); | ||
293 | - } else { | ||
294 | - pluginService.savePlugin(plugin); | ||
295 | - } | ||
296 | - } catch (Exception e) { | ||
297 | - log.error("Unable to load plugin from json: [{}]", path.toString()); | ||
298 | - throw new RuntimeException("Unable to load plugin from json", e); | 284 | + try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(pluginsDir, path -> path.toString().endsWith(".json"))) { |
285 | + dirStream.forEach( | ||
286 | + path -> { | ||
287 | + try { | ||
288 | + JsonNode pluginJson = objectMapper.readTree(path.toFile()); | ||
289 | + PluginMetaData plugin = objectMapper.treeToValue(pluginJson, PluginMetaData.class); | ||
290 | + plugin.setTenantId(tenantId); | ||
291 | + if (plugin.getState() == ComponentLifecycleState.ACTIVE) { | ||
292 | + plugin.setState(ComponentLifecycleState.SUSPENDED); | ||
293 | + PluginMetaData savedPlugin = pluginService.savePlugin(plugin); | ||
294 | + pluginService.activatePluginById(savedPlugin.getId()); | ||
295 | + } else { | ||
296 | + pluginService.savePlugin(plugin); | ||
299 | } | 297 | } |
298 | + } catch (Exception e) { | ||
299 | + log.error("Unable to load plugin from json: [{}]", path.toString()); | ||
300 | + throw new RuntimeException("Unable to load plugin from json", e); | ||
300 | } | 301 | } |
301 | - ); | ||
302 | - | 302 | + } |
303 | + ); | ||
304 | + } | ||
303 | } | 305 | } |
304 | 306 | ||
305 | private void loadRules(Path rulesDir, TenantId tenantId) throws Exception { | 307 | private void loadRules(Path rulesDir, TenantId tenantId) throws Exception { |
306 | - Files.newDirectoryStream(rulesDir, path -> path.toString().endsWith(".json")) | ||
307 | - .forEach( | ||
308 | - path -> { | ||
309 | - try { | ||
310 | - JsonNode ruleJson = objectMapper.readTree(path.toFile()); | ||
311 | - RuleMetaData rule = objectMapper.treeToValue(ruleJson, RuleMetaData.class); | ||
312 | - rule.setTenantId(tenantId); | ||
313 | - if (rule.getState() == ComponentLifecycleState.ACTIVE) { | ||
314 | - rule.setState(ComponentLifecycleState.SUSPENDED); | ||
315 | - RuleMetaData savedRule = ruleService.saveRule(rule); | ||
316 | - ruleService.activateRuleById(savedRule.getId()); | ||
317 | - } else { | ||
318 | - ruleService.saveRule(rule); | ||
319 | - } | ||
320 | - } catch (Exception e) { | ||
321 | - log.error("Unable to load rule from json: [{}]", path.toString()); | ||
322 | - throw new RuntimeException("Unable to load rule from json", e); | 308 | + try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(rulesDir, path -> path.toString().endsWith(".json"))) { |
309 | + dirStream.forEach( | ||
310 | + path -> { | ||
311 | + try { | ||
312 | + JsonNode ruleJson = objectMapper.readTree(path.toFile()); | ||
313 | + RuleMetaData rule = objectMapper.treeToValue(ruleJson, RuleMetaData.class); | ||
314 | + rule.setTenantId(tenantId); | ||
315 | + if (rule.getState() == ComponentLifecycleState.ACTIVE) { | ||
316 | + rule.setState(ComponentLifecycleState.SUSPENDED); | ||
317 | + RuleMetaData savedRule = ruleService.saveRule(rule); | ||
318 | + ruleService.activateRuleById(savedRule.getId()); | ||
319 | + } else { | ||
320 | + ruleService.saveRule(rule); | ||
323 | } | 321 | } |
322 | + } catch (Exception e) { | ||
323 | + log.error("Unable to load rule from json: [{}]", path.toString()); | ||
324 | + throw new RuntimeException("Unable to load rule from json", e); | ||
324 | } | 325 | } |
325 | - ); | 326 | + } |
327 | + ); | ||
328 | + } | ||
326 | } | 329 | } |
327 | 330 | ||
328 | private void loadDashboards(Path dashboardsDir, TenantId tenantId, CustomerId customerId) throws Exception { | 331 | private void loadDashboards(Path dashboardsDir, TenantId tenantId, CustomerId customerId) throws Exception { |
329 | - Files.newDirectoryStream(dashboardsDir, path -> path.toString().endsWith(".json")) | ||
330 | - .forEach( | ||
331 | - path -> { | ||
332 | - try { | ||
333 | - JsonNode dashboardJson = objectMapper.readTree(path.toFile()); | ||
334 | - Dashboard dashboard = objectMapper.treeToValue(dashboardJson, Dashboard.class); | ||
335 | - dashboard.setTenantId(tenantId); | ||
336 | - dashboard.setCustomerId(customerId); | ||
337 | - dashboardService.saveDashboard(dashboard); | ||
338 | - } catch (Exception e) { | ||
339 | - log.error("Unable to load dashboard from json: [{}]", path.toString()); | ||
340 | - throw new RuntimeException("Unable to load dashboard from json", e); | ||
341 | - } | 332 | + try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dashboardsDir, path -> path.toString().endsWith(".json"))) { |
333 | + dirStream.forEach( | ||
334 | + path -> { | ||
335 | + try { | ||
336 | + JsonNode dashboardJson = objectMapper.readTree(path.toFile()); | ||
337 | + Dashboard dashboard = objectMapper.treeToValue(dashboardJson, Dashboard.class); | ||
338 | + dashboard.setTenantId(tenantId); | ||
339 | + dashboard.setCustomerId(customerId); | ||
340 | + dashboardService.saveDashboard(dashboard); | ||
341 | + } catch (Exception e) { | ||
342 | + log.error("Unable to load dashboard from json: [{}]", path.toString()); | ||
343 | + throw new RuntimeException("Unable to load dashboard from json", e); | ||
342 | } | 344 | } |
343 | - ); | 345 | + } |
346 | + ); | ||
347 | + } | ||
344 | } | 348 | } |
345 | } | 349 | } |
@@ -28,6 +28,7 @@ import java.nio.file.Path; | @@ -28,6 +28,7 @@ import java.nio.file.Path; | ||
28 | import java.nio.file.Paths; | 28 | import java.nio.file.Paths; |
29 | import java.sql.Connection; | 29 | import java.sql.Connection; |
30 | import java.sql.DriverManager; | 30 | import java.sql.DriverManager; |
31 | +import java.sql.PreparedStatement; | ||
31 | 32 | ||
32 | @Service | 33 | @Service |
33 | @Profile("install") | 34 | @Profile("install") |
@@ -58,7 +59,7 @@ public class SqlDatabaseSchemaService implements DatabaseSchemaService { | @@ -58,7 +59,7 @@ public class SqlDatabaseSchemaService implements DatabaseSchemaService { | ||
58 | Path schemaFile = Paths.get(this.dataDir, SQL_DIR, SCHEMA_SQL); | 59 | Path schemaFile = Paths.get(this.dataDir, SQL_DIR, SCHEMA_SQL); |
59 | try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { | 60 | try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { |
60 | String sql = new String(Files.readAllBytes(schemaFile), Charset.forName("UTF-8")); | 61 | String sql = new String(Files.readAllBytes(schemaFile), Charset.forName("UTF-8")); |
61 | - conn.createStatement().execute(sql); | 62 | + conn.prepareStatement(sql).execute(); //NOSONAR, ignoring because method used to load initial thingsboard database schema |
62 | } | 63 | } |
63 | 64 | ||
64 | } | 65 | } |
@@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest; | @@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest; | ||
24 | 24 | ||
25 | @Component(value="jwtHeaderTokenExtractor") | 25 | @Component(value="jwtHeaderTokenExtractor") |
26 | public class JwtHeaderTokenExtractor implements TokenExtractor { | 26 | public class JwtHeaderTokenExtractor implements TokenExtractor { |
27 | - public static String HEADER_PREFIX = "Bearer "; | 27 | + public static final String HEADER_PREFIX = "Bearer "; |
28 | 28 | ||
29 | @Override | 29 | @Override |
30 | public String extract(HttpServletRequest request) { | 30 | public String extract(HttpServletRequest request) { |
@@ -29,7 +29,9 @@ public class DataConstants { | @@ -29,7 +29,9 @@ public class DataConstants { | ||
29 | public static final String SERVER_SCOPE = "SERVER_SCOPE"; | 29 | public static final String SERVER_SCOPE = "SERVER_SCOPE"; |
30 | public static final String SHARED_SCOPE = "SHARED_SCOPE"; | 30 | public static final String SHARED_SCOPE = "SHARED_SCOPE"; |
31 | 31 | ||
32 | - public static final String[] ALL_SCOPES = {CLIENT_SCOPE, SHARED_SCOPE, SERVER_SCOPE}; | 32 | + public static final String[] allScopes() { |
33 | + return new String[]{CLIENT_SCOPE, SHARED_SCOPE, SERVER_SCOPE}; | ||
34 | + } | ||
33 | 35 | ||
34 | public static final String ALARM = "ALARM"; | 36 | public static final String ALARM = "ALARM"; |
35 | public static final String ERROR = "ERROR"; | 37 | public static final String ERROR = "ERROR"; |
@@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.page; | @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.page; | ||
17 | 17 | ||
18 | import java.util.Iterator; | 18 | import java.util.Iterator; |
19 | import java.util.List; | 19 | import java.util.List; |
20 | +import java.util.NoSuchElementException; | ||
20 | 21 | ||
21 | import org.thingsboard.server.common.data.SearchTextBased; | 22 | import org.thingsboard.server.common.data.SearchTextBased; |
22 | import org.thingsboard.server.common.data.id.UUIDBased; | 23 | import org.thingsboard.server.common.data.id.UUIDBased; |
@@ -54,7 +55,7 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | @@ -54,7 +55,7 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | ||
54 | fetch(nextPackLink); | 55 | fetch(nextPackLink); |
55 | } | 56 | } |
56 | } | 57 | } |
57 | - return currentIdx != currentItems.size(); | 58 | + return currentIdx < currentItems.size(); |
58 | } | 59 | } |
59 | 60 | ||
60 | private void fetch(TextPageLink link) { | 61 | private void fetch(TextPageLink link) { |
@@ -67,6 +68,9 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | @@ -67,6 +68,9 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | ||
67 | 68 | ||
68 | @Override | 69 | @Override |
69 | public T next() { | 70 | public T next() { |
71 | + if(!hasNext()){ | ||
72 | + throw new NoSuchElementException(); | ||
73 | + } | ||
70 | return currentItems.get(currentIdx++); | 74 | return currentItems.get(currentIdx++); |
71 | } | 75 | } |
72 | 76 |
@@ -46,10 +46,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover; | @@ -46,10 +46,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover; | ||
46 | import org.thingsboard.server.dao.tenant.TenantDao; | 46 | import org.thingsboard.server.dao.tenant.TenantDao; |
47 | 47 | ||
48 | import javax.annotation.Nullable; | 48 | import javax.annotation.Nullable; |
49 | -import java.util.ArrayList; | ||
50 | -import java.util.Comparator; | ||
51 | -import java.util.List; | ||
52 | -import java.util.Optional; | 49 | +import java.util.*; |
53 | import java.util.stream.Collectors; | 50 | import java.util.stream.Collectors; |
54 | 51 | ||
55 | import static org.thingsboard.server.dao.DaoUtil.toUUIDs; | 52 | import static org.thingsboard.server.dao.DaoUtil.toUUIDs; |
@@ -210,7 +207,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ | @@ -210,7 +207,7 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ | ||
210 | @Nullable | 207 | @Nullable |
211 | @Override | 208 | @Override |
212 | public List<Asset> apply(@Nullable List<Asset> assetList) { | 209 | public List<Asset> apply(@Nullable List<Asset> assetList) { |
213 | - return assetList.stream().filter(asset -> query.getAssetTypes().contains(asset.getType())).collect(Collectors.toList()); | 210 | + return assetList == null ? Collections.emptyList() : assetList.stream().filter(asset -> query.getAssetTypes().contains(asset.getType())).collect(Collectors.toList()); |
214 | } | 211 | } |
215 | }); | 212 | }); |
216 | 213 |
@@ -109,18 +109,21 @@ public class CassandraBaseAttributesDao extends CassandraAbstractAsyncDao implem | @@ -109,18 +109,21 @@ public class CassandraBaseAttributesDao extends CassandraAbstractAsyncDao implem | ||
109 | stmt.setString(3, attribute.getKey()); | 109 | stmt.setString(3, attribute.getKey()); |
110 | stmt.setLong(4, attribute.getLastUpdateTs()); | 110 | stmt.setLong(4, attribute.getLastUpdateTs()); |
111 | stmt.setString(5, attribute.getStrValue().orElse(null)); | 111 | stmt.setString(5, attribute.getStrValue().orElse(null)); |
112 | - if (attribute.getBooleanValue().isPresent()) { | ||
113 | - stmt.setBool(6, attribute.getBooleanValue().get()); | 112 | + Optional<Boolean> booleanValue = attribute.getBooleanValue(); |
113 | + if (booleanValue.isPresent()) { | ||
114 | + stmt.setBool(6, booleanValue.get()); | ||
114 | } else { | 115 | } else { |
115 | stmt.setToNull(6); | 116 | stmt.setToNull(6); |
116 | } | 117 | } |
117 | - if (attribute.getLongValue().isPresent()) { | ||
118 | - stmt.setLong(7, attribute.getLongValue().get()); | 118 | + Optional<Long> longValue = attribute.getLongValue(); |
119 | + if (longValue.isPresent()) { | ||
120 | + stmt.setLong(7, longValue.get()); | ||
119 | } else { | 121 | } else { |
120 | stmt.setToNull(7); | 122 | stmt.setToNull(7); |
121 | } | 123 | } |
122 | - if (attribute.getDoubleValue().isPresent()) { | ||
123 | - stmt.setDouble(8, attribute.getDoubleValue().get()); | 124 | + Optional<Double> doubleValue = attribute.getDoubleValue(); |
125 | + if (doubleValue.isPresent()) { | ||
126 | + stmt.setDouble(8, doubleValue.get()); | ||
124 | } else { | 127 | } else { |
125 | stmt.setToNull(8); | 128 | stmt.setToNull(8); |
126 | } | 129 | } |
@@ -153,6 +153,7 @@ public abstract class AbstractCassandraCluster { | @@ -153,6 +153,7 @@ public abstract class AbstractCassandraCluster { | ||
153 | Thread.sleep(initRetryInterval); | 153 | Thread.sleep(initRetryInterval); |
154 | } catch (InterruptedException ie) { | 154 | } catch (InterruptedException ie) { |
155 | log.warn("Failed to wait until retry", ie); | 155 | log.warn("Failed to wait until retry", ie); |
156 | + Thread.currentThread().interrupt(); | ||
156 | } | 157 | } |
157 | } | 158 | } |
158 | } | 159 | } |
@@ -44,10 +44,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover; | @@ -44,10 +44,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover; | ||
44 | import org.thingsboard.server.dao.tenant.TenantDao; | 44 | import org.thingsboard.server.dao.tenant.TenantDao; |
45 | 45 | ||
46 | import javax.annotation.Nullable; | 46 | import javax.annotation.Nullable; |
47 | -import java.util.ArrayList; | ||
48 | -import java.util.Comparator; | ||
49 | -import java.util.List; | ||
50 | -import java.util.Optional; | 47 | +import java.util.*; |
51 | import java.util.stream.Collectors; | 48 | import java.util.stream.Collectors; |
52 | 49 | ||
53 | import static org.thingsboard.server.dao.DaoUtil.toUUIDs; | 50 | import static org.thingsboard.server.dao.DaoUtil.toUUIDs; |
@@ -230,7 +227,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -230,7 +227,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
230 | @Nullable | 227 | @Nullable |
231 | @Override | 228 | @Override |
232 | public List<Device> apply(@Nullable List<Device> deviceList) { | 229 | public List<Device> apply(@Nullable List<Device> deviceList) { |
233 | - return deviceList.stream().filter(device -> query.getDeviceTypes().contains(device.getType())).collect(Collectors.toList()); | 230 | + return deviceList == null ? Collections.emptyList() : deviceList.stream().filter(device -> query.getDeviceTypes().contains(device.getType())).collect(Collectors.toList()); |
234 | } | 231 | } |
235 | }); | 232 | }); |
236 | 233 |
@@ -27,8 +27,8 @@ public class ModelConstants { | @@ -27,8 +27,8 @@ public class ModelConstants { | ||
27 | private ModelConstants() { | 27 | private ModelConstants() { |
28 | } | 28 | } |
29 | 29 | ||
30 | - public static UUID NULL_UUID = UUIDs.startOf(0); | ||
31 | - public static String NULL_UUID_STR = UUIDConverter.fromTimeUUID(NULL_UUID); | 30 | + public static final UUID NULL_UUID = UUIDs.startOf(0); |
31 | + public static final String NULL_UUID_STR = UUIDConverter.fromTimeUUID(NULL_UUID); | ||
32 | 32 | ||
33 | /** | 33 | /** |
34 | * Generic constants. | 34 | * Generic constants. |
@@ -66,7 +66,7 @@ public class ModelConstants { | @@ -66,7 +66,7 @@ public class ModelConstants { | ||
66 | public static final String USER_CREDENTIALS_COLUMN_FAMILY_NAME = "user_credentials"; | 66 | public static final String USER_CREDENTIALS_COLUMN_FAMILY_NAME = "user_credentials"; |
67 | public static final String USER_CREDENTIALS_USER_ID_PROPERTY = USER_ID_PROPERTY; | 67 | public static final String USER_CREDENTIALS_USER_ID_PROPERTY = USER_ID_PROPERTY; |
68 | public static final String USER_CREDENTIALS_ENABLED_PROPERTY = "enabled"; | 68 | public static final String USER_CREDENTIALS_ENABLED_PROPERTY = "enabled"; |
69 | - public static final String USER_CREDENTIALS_PASSWORD_PROPERTY = "password"; | 69 | + public static final String USER_CREDENTIALS_PASSWORD_PROPERTY = "password"; //NOSONAR, the constant used to identify password column name (not password value itself) |
70 | public static final String USER_CREDENTIALS_ACTIVATE_TOKEN_PROPERTY = "activate_token"; | 70 | public static final String USER_CREDENTIALS_ACTIVATE_TOKEN_PROPERTY = "activate_token"; |
71 | public static final String USER_CREDENTIALS_RESET_TOKEN_PROPERTY = "reset_token"; | 71 | public static final String USER_CREDENTIALS_RESET_TOKEN_PROPERTY = "reset_token"; |
72 | 72 | ||
@@ -328,17 +328,17 @@ public class ModelConstants { | @@ -328,17 +328,17 @@ public class ModelConstants { | ||
328 | public static final String LONG_VALUE_COLUMN = "long_v"; | 328 | public static final String LONG_VALUE_COLUMN = "long_v"; |
329 | public static final String DOUBLE_VALUE_COLUMN = "dbl_v"; | 329 | public static final String DOUBLE_VALUE_COLUMN = "dbl_v"; |
330 | 330 | ||
331 | - public static final String[] NONE_AGGREGATION_COLUMNS = new String[]{LONG_VALUE_COLUMN, DOUBLE_VALUE_COLUMN, BOOLEAN_VALUE_COLUMN, STRING_VALUE_COLUMN, KEY_COLUMN, TS_COLUMN}; | 331 | + protected static final String[] NONE_AGGREGATION_COLUMNS = new String[]{LONG_VALUE_COLUMN, DOUBLE_VALUE_COLUMN, BOOLEAN_VALUE_COLUMN, STRING_VALUE_COLUMN, KEY_COLUMN, TS_COLUMN}; |
332 | 332 | ||
333 | - public static final String[] COUNT_AGGREGATION_COLUMNS = new String[]{count(LONG_VALUE_COLUMN), count(DOUBLE_VALUE_COLUMN), count(BOOLEAN_VALUE_COLUMN), count(STRING_VALUE_COLUMN)}; | 333 | + protected static final String[] COUNT_AGGREGATION_COLUMNS = new String[]{count(LONG_VALUE_COLUMN), count(DOUBLE_VALUE_COLUMN), count(BOOLEAN_VALUE_COLUMN), count(STRING_VALUE_COLUMN)}; |
334 | 334 | ||
335 | - public static final String[] MIN_AGGREGATION_COLUMNS = ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, | 335 | + protected static final String[] MIN_AGGREGATION_COLUMNS = ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, |
336 | new String[]{min(LONG_VALUE_COLUMN), min(DOUBLE_VALUE_COLUMN), min(BOOLEAN_VALUE_COLUMN), min(STRING_VALUE_COLUMN)}); | 336 | new String[]{min(LONG_VALUE_COLUMN), min(DOUBLE_VALUE_COLUMN), min(BOOLEAN_VALUE_COLUMN), min(STRING_VALUE_COLUMN)}); |
337 | - public static final String[] MAX_AGGREGATION_COLUMNS = ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, | 337 | + protected static final String[] MAX_AGGREGATION_COLUMNS = ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, |
338 | new String[]{max(LONG_VALUE_COLUMN), max(DOUBLE_VALUE_COLUMN), max(BOOLEAN_VALUE_COLUMN), max(STRING_VALUE_COLUMN)}); | 338 | new String[]{max(LONG_VALUE_COLUMN), max(DOUBLE_VALUE_COLUMN), max(BOOLEAN_VALUE_COLUMN), max(STRING_VALUE_COLUMN)}); |
339 | - public static final String[] SUM_AGGREGATION_COLUMNS = ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, | 339 | + protected static final String[] SUM_AGGREGATION_COLUMNS = ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, |
340 | new String[]{sum(LONG_VALUE_COLUMN), sum(DOUBLE_VALUE_COLUMN)}); | 340 | new String[]{sum(LONG_VALUE_COLUMN), sum(DOUBLE_VALUE_COLUMN)}); |
341 | - public static final String[] AVG_AGGREGATION_COLUMNS = SUM_AGGREGATION_COLUMNS; | 341 | + protected static final String[] AVG_AGGREGATION_COLUMNS = SUM_AGGREGATION_COLUMNS; |
342 | 342 | ||
343 | public static String min(String s) { | 343 | public static String min(String s) { |
344 | return "min(" + s + ")"; | 344 | return "min(" + s + ")"; |
@@ -57,12 +57,7 @@ public abstract class DataValidator<D extends BaseData<?>> { | @@ -57,12 +57,7 @@ public abstract class DataValidator<D extends BaseData<?>> { | ||
57 | } | 57 | } |
58 | 58 | ||
59 | protected boolean isSameData(D existentData, D actualData) { | 59 | protected boolean isSameData(D existentData, D actualData) { |
60 | - if (actualData.getId() == null) { | ||
61 | - return false; | ||
62 | - } else if (!existentData.getId().equals(actualData.getId())) { | ||
63 | - return false; | ||
64 | - } | ||
65 | - return true; | 60 | + return actualData.getId() != null && existentData.getId().equals(actualData.getId()); |
66 | } | 61 | } |
67 | 62 | ||
68 | protected static void validateEmail(String email) { | 63 | protected static void validateEmail(String email) { |
@@ -117,11 +117,7 @@ public class Validator { | @@ -117,11 +117,7 @@ public class Validator { | ||
117 | * @param errorMessage the error message for exception | 117 | * @param errorMessage the error message for exception |
118 | */ | 118 | */ |
119 | public static void validatePageLink(TextPageLink pageLink, String errorMessage) { | 119 | public static void validatePageLink(TextPageLink pageLink, String errorMessage) { |
120 | - if (pageLink == null) { | ||
121 | - throw new IncorrectParameterException(errorMessage); | ||
122 | - } else if (pageLink.getLimit() < 1) { | ||
123 | - throw new IncorrectParameterException(errorMessage); | ||
124 | - } else if (pageLink.getIdOffset() != null && pageLink.getIdOffset().version() != 1) { | 120 | + if (pageLink == null || pageLink.getLimit() < 1 || (pageLink.getIdOffset() != null && pageLink.getIdOffset().version() != 1)) { |
125 | throw new IncorrectParameterException(errorMessage); | 121 | throw new IncorrectParameterException(errorMessage); |
126 | } | 122 | } |
127 | } | 123 | } |
@@ -168,7 +168,6 @@ public class JpaTimeseriesDao extends JpaAbstractDaoListeningExecutorService imp | @@ -168,7 +168,6 @@ public class JpaTimeseriesDao extends JpaAbstractDaoListeningExecutorService imp | ||
168 | } | 168 | } |
169 | }); | 169 | }); |
170 | return Futures.transform(listenableFuture, new Function<TsKvEntity, Optional<TsKvEntry>>() { | 170 | return Futures.transform(listenableFuture, new Function<TsKvEntity, Optional<TsKvEntry>>() { |
171 | - @Nullable | ||
172 | @Override | 171 | @Override |
173 | public Optional<TsKvEntry> apply(@Nullable TsKvEntity entity) { | 172 | public Optional<TsKvEntry> apply(@Nullable TsKvEntity entity) { |
174 | if (entity != null && entity.isNotEmpty()) { | 173 | if (entity != null && entity.isNotEmpty()) { |
@@ -49,7 +49,6 @@ public class AggregatePartitionsFunction implements com.google.common.base.Funct | @@ -49,7 +49,6 @@ public class AggregatePartitionsFunction implements com.google.common.base.Funct | ||
49 | this.ts = ts; | 49 | this.ts = ts; |
50 | } | 50 | } |
51 | 51 | ||
52 | - @Nullable | ||
53 | @Override | 52 | @Override |
54 | public Optional<TsKvEntry> apply(@Nullable List<ResultSet> rsList) { | 53 | public Optional<TsKvEntry> apply(@Nullable List<ResultSet> rsList) { |
55 | try { | 54 | try { |
@@ -42,6 +42,7 @@ import java.time.Instant; | @@ -42,6 +42,7 @@ import java.time.Instant; | ||
42 | import java.time.LocalDateTime; | 42 | import java.time.LocalDateTime; |
43 | import java.time.ZoneOffset; | 43 | import java.time.ZoneOffset; |
44 | import java.util.ArrayList; | 44 | import java.util.ArrayList; |
45 | +import java.util.Collections; | ||
45 | import java.util.List; | 46 | import java.util.List; |
46 | import java.util.Optional; | 47 | import java.util.Optional; |
47 | import java.util.stream.Collectors; | 48 | import java.util.stream.Collectors; |
@@ -136,7 +137,7 @@ public class CassandraBaseTimeseriesDao extends CassandraAbstractAsyncDao implem | @@ -136,7 +137,7 @@ public class CassandraBaseTimeseriesDao extends CassandraAbstractAsyncDao implem | ||
136 | @Nullable | 137 | @Nullable |
137 | @Override | 138 | @Override |
138 | public List<TsKvEntry> apply(@Nullable List<Optional<TsKvEntry>> input) { | 139 | public List<TsKvEntry> apply(@Nullable List<Optional<TsKvEntry>> input) { |
139 | - return input.stream().filter(v -> v.isPresent()).map(v -> v.get()).collect(Collectors.toList()); | 140 | + return input == null ? Collections.emptyList() : input.stream().filter(v -> v.isPresent()).map(v -> v.get()).collect(Collectors.toList()); |
140 | } | 141 | } |
141 | }, readResultsProcessingExecutor); | 142 | }, readResultsProcessingExecutor); |
142 | } | 143 | } |
@@ -189,7 +190,7 @@ public class CassandraBaseTimeseriesDao extends CassandraAbstractAsyncDao implem | @@ -189,7 +190,7 @@ public class CassandraBaseTimeseriesDao extends CassandraAbstractAsyncDao implem | ||
189 | Futures.addCallback(executeAsyncRead(stmt), new FutureCallback<ResultSet>() { | 190 | Futures.addCallback(executeAsyncRead(stmt), new FutureCallback<ResultSet>() { |
190 | @Override | 191 | @Override |
191 | public void onSuccess(@Nullable ResultSet result) { | 192 | public void onSuccess(@Nullable ResultSet result) { |
192 | - cursor.addData(convertResultToTsKvEntryList(result.all())); | 193 | + cursor.addData(convertResultToTsKvEntryList(result == null ? Collections.emptyList() : result.all())); |
193 | findAllAsyncSequentiallyWithLimit(cursor, resultFuture); | 194 | findAllAsyncSequentiallyWithLimit(cursor, resultFuture); |
194 | } | 195 | } |
195 | 196 | ||
@@ -523,16 +524,28 @@ public class CassandraBaseTimeseriesDao extends CassandraAbstractAsyncDao implem | @@ -523,16 +524,28 @@ public class CassandraBaseTimeseriesDao extends CassandraAbstractAsyncDao implem | ||
523 | private static void addValue(KvEntry kvEntry, BoundStatement stmt, int column) { | 524 | private static void addValue(KvEntry kvEntry, BoundStatement stmt, int column) { |
524 | switch (kvEntry.getDataType()) { | 525 | switch (kvEntry.getDataType()) { |
525 | case BOOLEAN: | 526 | case BOOLEAN: |
526 | - stmt.setBool(column, kvEntry.getBooleanValue().get().booleanValue()); | 527 | + Optional<Boolean> booleanValue = kvEntry.getBooleanValue(); |
528 | + if (booleanValue.isPresent()) { | ||
529 | + stmt.setBool(column, booleanValue.get().booleanValue()); | ||
530 | + } | ||
527 | break; | 531 | break; |
528 | case STRING: | 532 | case STRING: |
529 | - stmt.setString(column, kvEntry.getStrValue().get()); | 533 | + Optional<String> stringValue = kvEntry.getStrValue(); |
534 | + if (stringValue.isPresent()) { | ||
535 | + stmt.setString(column, stringValue.get()); | ||
536 | + } | ||
530 | break; | 537 | break; |
531 | case LONG: | 538 | case LONG: |
532 | - stmt.setLong(column, kvEntry.getLongValue().get().longValue()); | 539 | + Optional<Long> longValue = kvEntry.getLongValue(); |
540 | + if (longValue.isPresent()) { | ||
541 | + stmt.setLong(column, longValue.get().longValue()); | ||
542 | + } | ||
533 | break; | 543 | break; |
534 | case DOUBLE: | 544 | case DOUBLE: |
535 | - stmt.setDouble(column, kvEntry.getDoubleValue().get().doubleValue()); | 545 | + Optional<Double> doubleValue = kvEntry.getDoubleValue(); |
546 | + if (doubleValue.isPresent()) { | ||
547 | + stmt.setDouble(column, doubleValue.get().doubleValue()); | ||
548 | + } | ||
536 | break; | 549 | break; |
537 | } | 550 | } |
538 | } | 551 | } |
@@ -25,7 +25,7 @@ public enum TsPartitionDate { | @@ -25,7 +25,7 @@ public enum TsPartitionDate { | ||
25 | MINUTES("yyyy-MM-dd-HH-mm", ChronoUnit.MINUTES), HOURS("yyyy-MM-dd-HH", ChronoUnit.HOURS), DAYS("yyyy-MM-dd", ChronoUnit.DAYS), MONTHS("yyyy-MM", ChronoUnit.MONTHS), YEARS("yyyy", ChronoUnit.YEARS); | 25 | MINUTES("yyyy-MM-dd-HH-mm", ChronoUnit.MINUTES), HOURS("yyyy-MM-dd-HH", ChronoUnit.HOURS), DAYS("yyyy-MM-dd", ChronoUnit.DAYS), MONTHS("yyyy-MM", ChronoUnit.MONTHS), YEARS("yyyy", ChronoUnit.YEARS); |
26 | 26 | ||
27 | private final String pattern; | 27 | private final String pattern; |
28 | - private final TemporalUnit truncateUnit; | 28 | + private final transient TemporalUnit truncateUnit; |
29 | 29 | ||
30 | TsPartitionDate(String pattern, TemporalUnit truncateUnit) { | 30 | TsPartitionDate(String pattern, TemporalUnit truncateUnit) { |
31 | this.pattern = pattern; | 31 | this.pattern = pattern; |
@@ -71,7 +71,7 @@ public class DefaultWebsocketMsgHandler implements WebsocketMsgHandler { | @@ -71,7 +71,7 @@ public class DefaultWebsocketMsgHandler implements WebsocketMsgHandler { | ||
71 | wsSessionsMap.put(sessionId, new WsSessionMetaData(sessionRef)); | 71 | wsSessionsMap.put(sessionId, new WsSessionMetaData(sessionRef)); |
72 | break; | 72 | break; |
73 | case ERROR: | 73 | case ERROR: |
74 | - log.debug("[{}] Unknown websocket session error: {}. ", sessionId, event.getError().get()); | 74 | + log.debug("[{}] Unknown websocket session error: {}. ", sessionId, event.getError().orElse(null)); |
75 | break; | 75 | break; |
76 | case CLOSED: | 76 | case CLOSED: |
77 | wsSessionsMap.remove(sessionId); | 77 | wsSessionsMap.remove(sessionId); |
@@ -85,13 +85,13 @@ public class NashornJsEvaluator { | @@ -85,13 +85,13 @@ public class NashornJsEvaluator { | ||
85 | protected static Object getValue(KvEntry attr) { | 85 | protected static Object getValue(KvEntry attr) { |
86 | switch (attr.getDataType()) { | 86 | switch (attr.getDataType()) { |
87 | case STRING: | 87 | case STRING: |
88 | - return attr.getStrValue().get(); | 88 | + return attr.getStrValue().orElse(null); |
89 | case LONG: | 89 | case LONG: |
90 | - return attr.getLongValue().get(); | 90 | + return attr.getLongValue().orElse(null); |
91 | case DOUBLE: | 91 | case DOUBLE: |
92 | - return attr.getDoubleValue().get(); | 92 | + return attr.getDoubleValue().orElse(null); |
93 | case BOOLEAN: | 93 | case BOOLEAN: |
94 | - return attr.getBooleanValue().get(); | 94 | + return attr.getBooleanValue().orElse(null); |
95 | } | 95 | } |
96 | return null; | 96 | return null; |
97 | } | 97 | } |
@@ -34,10 +34,7 @@ import org.thingsboard.server.extensions.api.plugins.handlers.RuleMsgHandler; | @@ -34,10 +34,7 @@ import org.thingsboard.server.extensions.api.plugins.handlers.RuleMsgHandler; | ||
34 | import org.thingsboard.server.extensions.api.plugins.msg.*; | 34 | import org.thingsboard.server.extensions.api.plugins.msg.*; |
35 | import org.thingsboard.server.extensions.api.rules.RuleException; | 35 | import org.thingsboard.server.extensions.api.rules.RuleException; |
36 | 36 | ||
37 | -import java.util.HashMap; | ||
38 | -import java.util.List; | ||
39 | -import java.util.Map; | ||
40 | -import java.util.UUID; | 37 | +import java.util.*; |
41 | 38 | ||
42 | /** | 39 | /** |
43 | * @author Andrew Shvayka | 40 | * @author Andrew Shvayka |
@@ -89,8 +86,9 @@ public class DeviceMessagingRuleMsgHandler implements RuleMsgHandler { | @@ -89,8 +86,9 @@ public class DeviceMessagingRuleMsgHandler implements RuleMsgHandler { | ||
89 | if (pendindMsg != null) { | 86 | if (pendindMsg != null) { |
90 | log.trace("[{}] Received response: {}", requestId, msg); | 87 | log.trace("[{}] Received response: {}", requestId, msg); |
91 | ToServerRpcResponseMsg response; | 88 | ToServerRpcResponseMsg response; |
92 | - if (msg.getError().isPresent()) { | ||
93 | - response = new ToServerRpcResponseMsg(pendindMsg.getRequestId(), toJsonString(msg.getError().get())); | 89 | + Optional<RpcError> rpcError = msg.getError(); |
90 | + if (rpcError.isPresent()) { | ||
91 | + response = new ToServerRpcResponseMsg(pendindMsg.getRequestId(), toJsonString(rpcError.get())); | ||
94 | } else { | 92 | } else { |
95 | response = new ToServerRpcResponseMsg(pendindMsg.getRequestId(), msg.getResponse().orElse("")); | 93 | response = new ToServerRpcResponseMsg(pendindMsg.getRequestId(), msg.getResponse().orElse("")); |
96 | } | 94 | } |
@@ -110,8 +110,9 @@ public class RpcRestMsgHandler extends DefaultRestMsgHandler { | @@ -110,8 +110,9 @@ public class RpcRestMsgHandler extends DefaultRestMsgHandler { | ||
110 | } | 110 | } |
111 | 111 | ||
112 | public void reply(PluginContext ctx, DeferredResult<ResponseEntity> responseWriter, FromDeviceRpcResponse response) { | 112 | public void reply(PluginContext ctx, DeferredResult<ResponseEntity> responseWriter, FromDeviceRpcResponse response) { |
113 | - if (response.getError().isPresent()) { | ||
114 | - RpcError error = response.getError().get(); | 113 | + Optional<RpcError> rpcError = response.getError(); |
114 | + if (rpcError.isPresent()) { | ||
115 | + RpcError error = rpcError.get(); | ||
115 | switch (error) { | 116 | switch (error) { |
116 | case TIMEOUT: | 117 | case TIMEOUT: |
117 | responseWriter.setResult(new ResponseEntity<>(HttpStatus.REQUEST_TIMEOUT)); | 118 | responseWriter.setResult(new ResponseEntity<>(HttpStatus.REQUEST_TIMEOUT)); |
@@ -124,8 +125,9 @@ public class RpcRestMsgHandler extends DefaultRestMsgHandler { | @@ -124,8 +125,9 @@ public class RpcRestMsgHandler extends DefaultRestMsgHandler { | ||
124 | break; | 125 | break; |
125 | } | 126 | } |
126 | } else { | 127 | } else { |
127 | - if (response.getResponse().isPresent() && !StringUtils.isEmpty(response.getResponse().get())) { | ||
128 | - String data = response.getResponse().get(); | 128 | + Optional<String> responseData = response.getResponse(); |
129 | + if (responseData.isPresent() && !StringUtils.isEmpty(responseData.get())) { | ||
130 | + String data = responseData.get(); | ||
129 | try { | 131 | try { |
130 | responseWriter.setResult(new ResponseEntity<>(jsonMapper.readTree(data), HttpStatus.OK)); | 132 | responseWriter.setResult(new ResponseEntity<>(jsonMapper.readTree(data), HttpStatus.OK)); |
131 | } catch (IOException e) { | 133 | } catch (IOException e) { |
@@ -92,7 +92,7 @@ public class TelemetryRestMsgHandler extends DefaultRestMsgHandler { | @@ -92,7 +92,7 @@ public class TelemetryRestMsgHandler extends DefaultRestMsgHandler { | ||
92 | if (!StringUtils.isEmpty(scope)) { | 92 | if (!StringUtils.isEmpty(scope)) { |
93 | ctx.loadAttributes(entityId, scope, callback); | 93 | ctx.loadAttributes(entityId, scope, callback); |
94 | } else { | 94 | } else { |
95 | - ctx.loadAttributes(entityId, Arrays.asList(DataConstants.ALL_SCOPES), callback); | 95 | + ctx.loadAttributes(entityId, Arrays.asList(DataConstants.allScopes()), callback); |
96 | } | 96 | } |
97 | } | 97 | } |
98 | } else if (method.equals("values")) { | 98 | } else if (method.equals("values")) { |
@@ -132,9 +132,9 @@ public class TelemetryRestMsgHandler extends DefaultRestMsgHandler { | @@ -132,9 +132,9 @@ public class TelemetryRestMsgHandler extends DefaultRestMsgHandler { | ||
132 | } else { | 132 | } else { |
133 | if (!StringUtils.isEmpty(keys)) { | 133 | if (!StringUtils.isEmpty(keys)) { |
134 | List<String> keyList = Arrays.asList(keys.split(",")); | 134 | List<String> keyList = Arrays.asList(keys.split(",")); |
135 | - ctx.loadAttributes(entityId, Arrays.asList(DataConstants.ALL_SCOPES), keyList, callback); | 135 | + ctx.loadAttributes(entityId, Arrays.asList(DataConstants.allScopes()), keyList, callback); |
136 | } else { | 136 | } else { |
137 | - ctx.loadAttributes(entityId, Arrays.asList(DataConstants.ALL_SCOPES), callback); | 137 | + ctx.loadAttributes(entityId, Arrays.asList(DataConstants.allScopes()), callback); |
138 | } | 138 | } |
139 | } | 139 | } |
140 | } | 140 | } |
@@ -29,10 +29,7 @@ import org.thingsboard.server.extensions.core.plugin.telemetry.SubscriptionManag | @@ -29,10 +29,7 @@ import org.thingsboard.server.extensions.core.plugin.telemetry.SubscriptionManag | ||
29 | import org.thingsboard.server.extensions.core.plugin.telemetry.gen.TelemetryPluginProtos.*; | 29 | import org.thingsboard.server.extensions.core.plugin.telemetry.gen.TelemetryPluginProtos.*; |
30 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.*; | 30 | import org.thingsboard.server.extensions.core.plugin.telemetry.sub.*; |
31 | 31 | ||
32 | -import java.util.ArrayList; | ||
33 | -import java.util.List; | ||
34 | -import java.util.Map; | ||
35 | -import java.util.TreeMap; | 32 | +import java.util.*; |
36 | import java.util.stream.Collectors; | 33 | import java.util.stream.Collectors; |
37 | 34 | ||
38 | /** | 35 | /** |
@@ -244,16 +241,28 @@ public class TelemetryRpcMsgHandler implements RpcMsgHandler { | @@ -244,16 +241,28 @@ public class TelemetryRpcMsgHandler implements RpcMsgHandler { | ||
244 | dataBuilder.setValueType(attr.getDataType().ordinal()); | 241 | dataBuilder.setValueType(attr.getDataType().ordinal()); |
245 | switch (attr.getDataType()) { | 242 | switch (attr.getDataType()) { |
246 | case BOOLEAN: | 243 | case BOOLEAN: |
247 | - dataBuilder.setBoolValue(attr.getBooleanValue().get()); | 244 | + Optional<Boolean> booleanValue = attr.getBooleanValue(); |
245 | + if (booleanValue.isPresent()) { | ||
246 | + dataBuilder.setBoolValue(booleanValue.get()); | ||
247 | + } | ||
248 | break; | 248 | break; |
249 | case LONG: | 249 | case LONG: |
250 | - dataBuilder.setLongValue(attr.getLongValue().get()); | 250 | + Optional<Long> longValue = attr.getLongValue(); |
251 | + if (longValue.isPresent()) { | ||
252 | + dataBuilder.setLongValue(longValue.get()); | ||
253 | + } | ||
251 | break; | 254 | break; |
252 | case DOUBLE: | 255 | case DOUBLE: |
253 | - dataBuilder.setDoubleValue(attr.getDoubleValue().get()); | 256 | + Optional<Double> doubleValue = attr.getDoubleValue(); |
257 | + if (doubleValue.isPresent()) { | ||
258 | + dataBuilder.setDoubleValue(doubleValue.get()); | ||
259 | + } | ||
254 | break; | 260 | break; |
255 | case STRING: | 261 | case STRING: |
256 | - dataBuilder.setStrValue(attr.getStrValue().get()); | 262 | + Optional<String> stringValue = attr.getStrValue(); |
263 | + if (stringValue.isPresent()) { | ||
264 | + dataBuilder.setStrValue(stringValue.get()); | ||
265 | + } | ||
257 | break; | 266 | break; |
258 | } | 267 | } |
259 | return dataBuilder; | 268 | return dataBuilder; |
@@ -139,7 +139,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | @@ -139,7 +139,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | ||
139 | }; | 139 | }; |
140 | 140 | ||
141 | if (StringUtils.isEmpty(cmd.getScope())) { | 141 | if (StringUtils.isEmpty(cmd.getScope())) { |
142 | - ctx.loadAttributes(entityId, Arrays.asList(DataConstants.ALL_SCOPES), keys, callback); | 142 | + ctx.loadAttributes(entityId, Arrays.asList(DataConstants.allScopes()), keys, callback); |
143 | } else { | 143 | } else { |
144 | ctx.loadAttributes(entityId, cmd.getScope(), keys, callback); | 144 | ctx.loadAttributes(entityId, cmd.getScope(), keys, callback); |
145 | } | 145 | } |
@@ -167,7 +167,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | @@ -167,7 +167,7 @@ public class TelemetryWebsocketMsgHandler extends DefaultWebsocketMsgHandler { | ||
167 | }; | 167 | }; |
168 | 168 | ||
169 | if (StringUtils.isEmpty(cmd.getScope())) { | 169 | if (StringUtils.isEmpty(cmd.getScope())) { |
170 | - ctx.loadAttributes(entityId, Arrays.asList(DataConstants.ALL_SCOPES), callback); | 170 | + ctx.loadAttributes(entityId, Arrays.asList(DataConstants.allScopes()), callback); |
171 | } else { | 171 | } else { |
172 | ctx.loadAttributes(entityId, cmd.getScope(), callback); | 172 | ctx.loadAttributes(entityId, cmd.getScope(), callback); |
173 | } | 173 | } |
@@ -84,9 +84,10 @@ public class MqttPlugin extends AbstractPlugin<MqttPluginConfiguration> { | @@ -84,9 +84,10 @@ public class MqttPlugin extends AbstractPlugin<MqttPluginConfiguration> { | ||
84 | log.warn("Failed to connect to requested mqtt host [{}]!", mqttClient.getServerURI(), e); | 84 | log.warn("Failed to connect to requested mqtt host [{}]!", mqttClient.getServerURI(), e); |
85 | if (!mqttClient.isConnected()) { | 85 | if (!mqttClient.isConnected()) { |
86 | try { | 86 | try { |
87 | - Thread.sleep(retryInterval); | 87 | + connectLock.wait(retryInterval); |
88 | } catch (InterruptedException e1) { | 88 | } catch (InterruptedException e1) { |
89 | log.trace("Failed to wait for retry interval!", e); | 89 | log.trace("Failed to wait for retry interval!", e); |
90 | + Thread.currentThread().interrupt(); | ||
90 | } | 91 | } |
91 | } | 92 | } |
92 | } | 93 | } |
@@ -21,18 +21,18 @@ package org.thingsboard.client.tools; | @@ -21,18 +21,18 @@ package org.thingsboard.client.tools; | ||
21 | */ | 21 | */ |
22 | 22 | ||
23 | import com.google.common.io.Resources; | 23 | import com.google.common.io.Resources; |
24 | -import org.eclipse.paho.client.mqttv3.*; | 24 | +import lombok.extern.slf4j.Slf4j; |
25 | +import org.eclipse.paho.client.mqttv3.MqttAsyncClient; | ||
26 | +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; | ||
27 | +import org.eclipse.paho.client.mqttv3.MqttMessage; | ||
25 | 28 | ||
26 | import javax.net.ssl.*; | 29 | import javax.net.ssl.*; |
27 | import java.io.File; | 30 | import java.io.File; |
28 | import java.io.FileInputStream; | 31 | import java.io.FileInputStream; |
29 | -import java.io.FileNotFoundException; | ||
30 | -import java.io.IOException; | ||
31 | -import java.net.URISyntaxException; | ||
32 | import java.net.URL; | 32 | import java.net.URL; |
33 | -import java.security.*; | ||
34 | -import java.security.cert.CertificateException; | 33 | +import java.security.KeyStore; |
35 | 34 | ||
35 | +@Slf4j | ||
36 | public class MqttSslClient { | 36 | public class MqttSslClient { |
37 | 37 | ||
38 | 38 | ||
@@ -43,13 +43,10 @@ public class MqttSslClient { | @@ -43,13 +43,10 @@ public class MqttSslClient { | ||
43 | private static final String keyStoreFile = "mqttclient.jks"; | 43 | private static final String keyStoreFile = "mqttclient.jks"; |
44 | private static final String JKS="JKS"; | 44 | private static final String JKS="JKS"; |
45 | private static final String TLS="TLS"; | 45 | private static final String TLS="TLS"; |
46 | - private static final String CLIENT_KEYSTORE_PASSWORD = "client_ks_password"; | ||
47 | - private static final String CLIENT_KEY_PASSWORD = "client_key_password"; | ||
48 | 46 | ||
49 | public static void main(String[] args) { | 47 | public static void main(String[] args) { |
50 | 48 | ||
51 | try { | 49 | try { |
52 | - | ||
53 | URL ksUrl = Resources.getResource(keyStoreFile); | 50 | URL ksUrl = Resources.getResource(keyStoreFile); |
54 | File ksFile = new File(ksUrl.toURI()); | 51 | File ksFile = new File(ksUrl.toURI()); |
55 | URL tsUrl = Resources.getResource(keyStoreFile); | 52 | URL tsUrl = Resources.getResource(keyStoreFile); |
@@ -58,13 +55,15 @@ public class MqttSslClient { | @@ -58,13 +55,15 @@ public class MqttSslClient { | ||
58 | TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); | 55 | TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); |
59 | 56 | ||
60 | KeyStore trustStore = KeyStore.getInstance(JKS); | 57 | KeyStore trustStore = KeyStore.getInstance(JKS); |
61 | - trustStore.load(new FileInputStream(tsFile), CLIENT_KEYSTORE_PASSWORD.toCharArray()); | 58 | + char[] ksPwd = new char[]{0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x5F, 0x6B, 0x73, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64}; |
59 | + trustStore.load(new FileInputStream(tsFile), ksPwd); | ||
62 | tmf.init(trustStore); | 60 | tmf.init(trustStore); |
63 | KeyStore ks = KeyStore.getInstance(JKS); | 61 | KeyStore ks = KeyStore.getInstance(JKS); |
64 | 62 | ||
65 | - ks.load(new FileInputStream(ksFile), CLIENT_KEYSTORE_PASSWORD.toCharArray()); | 63 | + ks.load(new FileInputStream(ksFile), ksPwd); |
66 | KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); | 64 | KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); |
67 | - kmf.init(ks, CLIENT_KEY_PASSWORD.toCharArray()); | 65 | + char[] clientPwd = new char[]{0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x5F, 0x6B, 0x65, 0x79, 0x5F, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64}; |
66 | + kmf.init(ks, clientPwd); | ||
68 | 67 | ||
69 | KeyManager[] km = kmf.getKeyManagers(); | 68 | KeyManager[] km = kmf.getKeyManagers(); |
70 | TrustManager[] tm = tmf.getTrustManagers(); | 69 | TrustManager[] tm = tmf.getTrustManagers(); |
@@ -83,7 +82,7 @@ public class MqttSslClient { | @@ -83,7 +82,7 @@ public class MqttSslClient { | ||
83 | System.out.println("Disconnected"); | 82 | System.out.println("Disconnected"); |
84 | System.exit(0); | 83 | System.exit(0); |
85 | } catch (Exception e) { | 84 | } catch (Exception e) { |
86 | - e.printStackTrace(); | 85 | + log.error("Unexpected exception occurred in MqttSslClient", e); |
87 | } | 86 | } |
88 | } | 87 | } |
89 | } | 88 | } |
@@ -167,7 +167,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | @@ -167,7 +167,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | ||
167 | 167 | ||
168 | private FromDeviceMsg convertToGetAttributesRequest(SessionContext ctx, Request inbound) throws AdaptorException { | 168 | private FromDeviceMsg convertToGetAttributesRequest(SessionContext ctx, Request inbound) throws AdaptorException { |
169 | List<String> queryElements = inbound.getOptions().getUriQuery(); | 169 | List<String> queryElements = inbound.getOptions().getUriQuery(); |
170 | - if (queryElements != null || queryElements.size() > 0) { | 170 | + if (queryElements != null && queryElements.size() > 0) { |
171 | Set<String> clientKeys = toKeys(ctx, queryElements, "clientKeys"); | 171 | Set<String> clientKeys = toKeys(ctx, queryElements, "clientKeys"); |
172 | Set<String> sharedKeys = toKeys(ctx, queryElements, "sharedKeys"); | 172 | Set<String> sharedKeys = toKeys(ctx, queryElements, "sharedKeys"); |
173 | return new BasicGetAttributesRequest(0, clientKeys, sharedKeys); | 173 | return new BasicGetAttributesRequest(0, clientKeys, sharedKeys); |
@@ -184,7 +184,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | @@ -184,7 +184,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | ||
184 | keys = queryItem[1]; | 184 | keys = queryItem[1]; |
185 | } | 185 | } |
186 | } | 186 | } |
187 | - if (!StringUtils.isEmpty(keys)) { | 187 | + if (keys != null && !StringUtils.isEmpty(keys)) { |
188 | return new HashSet<>(Arrays.asList(keys.split(","))); | 188 | return new HashSet<>(Arrays.asList(keys.split(","))); |
189 | } else { | 189 | } else { |
190 | return null; | 190 | return null; |
@@ -202,14 +202,14 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | @@ -202,14 +202,14 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | ||
202 | 202 | ||
203 | private Response convertStatusCodeResponse(StatusCodeResponse msg) { | 203 | private Response convertStatusCodeResponse(StatusCodeResponse msg) { |
204 | if (msg.isSuccess()) { | 204 | if (msg.isSuccess()) { |
205 | - Integer code = msg.getData().get(); | ||
206 | - if (code == 200) { | 205 | + Optional<Integer> code = msg.getData(); |
206 | + if (code.isPresent() && code.get() == 200) { | ||
207 | return new Response(ResponseCode.VALID); | 207 | return new Response(ResponseCode.VALID); |
208 | } else { | 208 | } else { |
209 | return new Response(ResponseCode.CREATED); | 209 | return new Response(ResponseCode.CREATED); |
210 | } | 210 | } |
211 | } else { | 211 | } else { |
212 | - return convertError(msg.getError().get()); | 212 | + return convertError(msg.getError()); |
213 | } | 213 | } |
214 | } | 214 | } |
215 | 215 | ||
@@ -229,30 +229,34 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | @@ -229,30 +229,34 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { | ||
229 | response.setPayload(result.toString()); | 229 | response.setPayload(result.toString()); |
230 | return response; | 230 | return response; |
231 | } else { | 231 | } else { |
232 | - return convertError(new RuntimeException("Server RPC response is empty!")); | 232 | + return convertError(Optional.of(new RuntimeException("Server RPC response is empty!"))); |
233 | } | 233 | } |
234 | } | 234 | } |
235 | 235 | ||
236 | private Response convertGetAttributesResponse(GetAttributesResponse msg) { | 236 | private Response convertGetAttributesResponse(GetAttributesResponse msg) { |
237 | if (msg.isSuccess()) { | 237 | if (msg.isSuccess()) { |
238 | - AttributesKVMsg payload = msg.getData().get(); | ||
239 | - if (payload.getClientAttributes().isEmpty() && payload.getSharedAttributes().isEmpty()) { | 238 | + Optional<AttributesKVMsg> payload = msg.getData(); |
239 | + if (!payload.isPresent() || (payload.get().getClientAttributes().isEmpty() && payload.get().getSharedAttributes().isEmpty())) { | ||
240 | return new Response(ResponseCode.NOT_FOUND); | 240 | return new Response(ResponseCode.NOT_FOUND); |
241 | } else { | 241 | } else { |
242 | Response response = new Response(ResponseCode.CONTENT); | 242 | Response response = new Response(ResponseCode.CONTENT); |
243 | - JsonObject result = JsonConverter.toJson(payload, false); | 243 | + JsonObject result = JsonConverter.toJson(payload.get(), false); |
244 | response.setPayload(result.toString()); | 244 | response.setPayload(result.toString()); |
245 | return response; | 245 | return response; |
246 | } | 246 | } |
247 | } else { | 247 | } else { |
248 | - return convertError(msg.getError().get()); | 248 | + return convertError(msg.getError()); |
249 | } | 249 | } |
250 | } | 250 | } |
251 | 251 | ||
252 | - private Response convertError(Exception exception) { | ||
253 | - log.warn("Converting exception: {}", exception.getMessage(), exception); | ||
254 | - if (exception instanceof ProcessingTimeoutException) { | ||
255 | - return new Response(ResponseCode.SERVICE_UNAVAILABLE); | 252 | + private Response convertError(Optional<Exception> exception) { |
253 | + if (exception.isPresent()) { | ||
254 | + log.warn("Converting exception: {}", exception.get().getMessage(), exception.get()); | ||
255 | + if (exception.get() instanceof ProcessingTimeoutException) { | ||
256 | + return new Response(ResponseCode.SERVICE_UNAVAILABLE); | ||
257 | + } else { | ||
258 | + return new Response(ResponseCode.INTERNAL_SERVER_ERROR); | ||
259 | + } | ||
256 | } else { | 260 | } else { |
257 | return new Response(ResponseCode.INTERNAL_SERVER_ERROR); | 261 | return new Response(ResponseCode.INTERNAL_SERVER_ERROR); |
258 | } | 262 | } |
@@ -80,7 +80,7 @@ public class DeviceEmulator { | @@ -80,7 +80,7 @@ public class DeviceEmulator { | ||
80 | Thread.sleep(1000); | 80 | Thread.sleep(1000); |
81 | } | 81 | } |
82 | } catch (Exception e) { | 82 | } catch (Exception e) { |
83 | - e.printStackTrace(); | 83 | + log.error("Error occurred while sending COAP requests", e); |
84 | } | 84 | } |
85 | } | 85 | } |
86 | 86 | ||
@@ -118,7 +118,7 @@ public class DeviceEmulator { | @@ -118,7 +118,7 @@ public class DeviceEmulator { | ||
118 | }, mapper.writeValueAsString(response), MediaTypeRegistry.APPLICATION_JSON); | 118 | }, mapper.writeValueAsString(response), MediaTypeRegistry.APPLICATION_JSON); |
119 | 119 | ||
120 | } catch (IOException e) { | 120 | } catch (IOException e) { |
121 | - e.printStackTrace(); | 121 | + log.error("Error occurred while processing COAP response", e); |
122 | } | 122 | } |
123 | } | 123 | } |
124 | 124 |
@@ -29,6 +29,7 @@ import org.thingsboard.server.common.transport.adaptor.JsonConverter; | @@ -29,6 +29,7 @@ import org.thingsboard.server.common.transport.adaptor.JsonConverter; | ||
29 | import org.thingsboard.server.common.transport.auth.DeviceAuthService; | 29 | import org.thingsboard.server.common.transport.auth.DeviceAuthService; |
30 | import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; | 30 | import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; |
31 | 31 | ||
32 | +import java.util.Optional; | ||
32 | import java.util.function.Consumer; | 33 | import java.util.function.Consumer; |
33 | 34 | ||
34 | /** | 35 | /** |
@@ -94,10 +95,14 @@ public class HttpSessionCtx extends DeviceAwareSessionContext { | @@ -94,10 +95,14 @@ public class HttpSessionCtx extends DeviceAwareSessionContext { | ||
94 | } | 95 | } |
95 | 96 | ||
96 | private <T> void reply(ResponseMsg<? extends T> msg, Consumer<T> f) { | 97 | private <T> void reply(ResponseMsg<? extends T> msg, Consumer<T> f) { |
97 | - if (!msg.getError().isPresent()) { | ||
98 | - f.accept(msg.getData().get()); | 98 | + Optional<Exception> msgError = msg.getError(); |
99 | + if (!msgError.isPresent()) { | ||
100 | + Optional<? extends T> msgData = msg.getData(); | ||
101 | + if (msgData.isPresent()) { | ||
102 | + f.accept(msgData.get()); | ||
103 | + } | ||
99 | } else { | 104 | } else { |
100 | - Exception e = msg.getError().get(); | 105 | + Exception e = msgError.get(); |
101 | responseWriter.setResult(new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR)); | 106 | responseWriter.setResult(new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR)); |
102 | } | 107 | } |
103 | } | 108 | } |
@@ -32,6 +32,7 @@ import javax.net.ssl.*; | @@ -32,6 +32,7 @@ import javax.net.ssl.*; | ||
32 | import java.io.File; | 32 | import java.io.File; |
33 | import java.io.FileInputStream; | 33 | import java.io.FileInputStream; |
34 | import java.io.IOException; | 34 | import java.io.IOException; |
35 | +import java.io.InputStream; | ||
35 | import java.net.URL; | 36 | import java.net.URL; |
36 | import java.security.KeyStore; | 37 | import java.security.KeyStore; |
37 | import java.security.cert.CertificateException; | 38 | import java.security.cert.CertificateException; |
@@ -69,12 +70,15 @@ public class MqttSslHandlerProvider { | @@ -69,12 +70,15 @@ public class MqttSslHandlerProvider { | ||
69 | 70 | ||
70 | TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); | 71 | TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); |
71 | KeyStore trustStore = KeyStore.getInstance(keyStoreType); | 72 | KeyStore trustStore = KeyStore.getInstance(keyStoreType); |
72 | - trustStore.load(new FileInputStream(tsFile), keyStorePassword.toCharArray()); | 73 | + try (InputStream tsFileInputStream = new FileInputStream(tsFile)) { |
74 | + trustStore.load(tsFileInputStream, keyStorePassword.toCharArray()); | ||
75 | + } | ||
73 | tmFactory.init(trustStore); | 76 | tmFactory.init(trustStore); |
74 | 77 | ||
75 | KeyStore ks = KeyStore.getInstance(keyStoreType); | 78 | KeyStore ks = KeyStore.getInstance(keyStoreType); |
76 | - | ||
77 | - ks.load(new FileInputStream(ksFile), keyStorePassword.toCharArray()); | 79 | + try (InputStream ksFileInputStream = new FileInputStream(ksFile)) { |
80 | + ks.load(ksFileInputStream, keyStorePassword.toCharArray()); | ||
81 | + } | ||
78 | KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); | 82 | KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); |
79 | kmf.init(ks, keyPassword.toCharArray()); | 83 | kmf.init(ks, keyPassword.toCharArray()); |
80 | 84 |
@@ -98,6 +98,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { | @@ -98,6 +98,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { | ||
98 | case STATUS_CODE_RESPONSE: | 98 | case STATUS_CODE_RESPONSE: |
99 | case GET_ATTRIBUTES_RESPONSE: | 99 | case GET_ATTRIBUTES_RESPONSE: |
100 | ResponseMsg<?> responseMsg = (ResponseMsg) msg; | 100 | ResponseMsg<?> responseMsg = (ResponseMsg) msg; |
101 | + Optional<Exception> responseError = responseMsg.getError(); | ||
101 | if (responseMsg.isSuccess()) { | 102 | if (responseMsg.isSuccess()) { |
102 | MsgType requestMsgType = responseMsg.getRequestMsgType(); | 103 | MsgType requestMsgType = responseMsg.getRequestMsgType(); |
103 | Integer requestId = responseMsg.getRequestId(); | 104 | Integer requestId = responseMsg.getRequestId(); |
@@ -106,18 +107,21 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { | @@ -106,18 +107,21 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor { | ||
106 | result = MqttTransportHandler.createMqttPubAckMsg(requestId); | 107 | result = MqttTransportHandler.createMqttPubAckMsg(requestId); |
107 | } else if (requestMsgType == MsgType.GET_ATTRIBUTES_REQUEST) { | 108 | } else if (requestMsgType == MsgType.GET_ATTRIBUTES_REQUEST) { |
108 | GetAttributesResponse response = (GetAttributesResponse) msg; | 109 | GetAttributesResponse response = (GetAttributesResponse) msg; |
109 | - if (response.isSuccess()) { | 110 | + Optional<AttributesKVMsg> responseData = response.getData(); |
111 | + if (response.isSuccess() && responseData.isPresent()) { | ||
110 | result = createMqttPublishMsg(ctx, | 112 | result = createMqttPublishMsg(ctx, |
111 | MqttTopics.DEVICE_ATTRIBUTES_RESPONSE_TOPIC_PREFIX + requestId, | 113 | MqttTopics.DEVICE_ATTRIBUTES_RESPONSE_TOPIC_PREFIX + requestId, |
112 | - response.getData().get(), true); | 114 | + responseData.get(), true); |
113 | } else { | 115 | } else { |
114 | - throw new AdaptorException(response.getError().get()); | 116 | + if (responseError.isPresent()) { |
117 | + throw new AdaptorException(responseError.get()); | ||
118 | + } | ||
115 | } | 119 | } |
116 | } | 120 | } |
117 | } | 121 | } |
118 | } else { | 122 | } else { |
119 | - if (responseMsg.getError().isPresent()) { | ||
120 | - throw new AdaptorException(responseMsg.getError().get()); | 123 | + if (responseError.isPresent()) { |
124 | + throw new AdaptorException(responseError.get()); | ||
121 | } | 125 | } |
122 | } | 126 | } |
123 | break; | 127 | break; |
@@ -128,8 +128,9 @@ public class GatewayDeviceSessionCtx extends DeviceAwareSessionContext { | @@ -128,8 +128,9 @@ public class GatewayDeviceSessionCtx extends DeviceAwareSessionContext { | ||
128 | JsonObject result = new JsonObject(); | 128 | JsonObject result = new JsonObject(); |
129 | result.addProperty("id", response.getRequestId()); | 129 | result.addProperty("id", response.getRequestId()); |
130 | result.addProperty("device", device.getName()); | 130 | result.addProperty("device", device.getName()); |
131 | - if (response.getData().isPresent()) { | ||
132 | - AttributesKVMsg msg = response.getData().get(); | 131 | + Optional<AttributesKVMsg> responseData = response.getData(); |
132 | + if (responseData.isPresent()) { | ||
133 | + AttributesKVMsg msg = responseData.get(); | ||
133 | if (msg.getClientAttributes() != null) { | 134 | if (msg.getClientAttributes() != null) { |
134 | msg.getClientAttributes().forEach(v -> addValueToJson(result, "value", v)); | 135 | msg.getClientAttributes().forEach(v -> addValueToJson(result, "value", v)); |
135 | } | 136 | } |
@@ -143,16 +144,28 @@ public class GatewayDeviceSessionCtx extends DeviceAwareSessionContext { | @@ -143,16 +144,28 @@ public class GatewayDeviceSessionCtx extends DeviceAwareSessionContext { | ||
143 | private void addValueToJson(JsonObject json, String name, KvEntry entry) { | 144 | private void addValueToJson(JsonObject json, String name, KvEntry entry) { |
144 | switch (entry.getDataType()) { | 145 | switch (entry.getDataType()) { |
145 | case BOOLEAN: | 146 | case BOOLEAN: |
146 | - json.addProperty(name, entry.getBooleanValue().get()); | 147 | + Optional<Boolean> booleanValue = entry.getBooleanValue(); |
148 | + if (booleanValue.isPresent()) { | ||
149 | + json.addProperty(name, booleanValue.get()); | ||
150 | + } | ||
147 | break; | 151 | break; |
148 | case STRING: | 152 | case STRING: |
149 | - json.addProperty(name, entry.getStrValue().get()); | 153 | + Optional<String> stringValue = entry.getStrValue(); |
154 | + if (stringValue.isPresent()) { | ||
155 | + json.addProperty(name, stringValue.get()); | ||
156 | + } | ||
150 | break; | 157 | break; |
151 | case DOUBLE: | 158 | case DOUBLE: |
152 | - json.addProperty(name, entry.getDoubleValue().get()); | 159 | + Optional<Double> doubleValue = entry.getDoubleValue(); |
160 | + if (doubleValue.isPresent()) { | ||
161 | + json.addProperty(name, doubleValue.get()); | ||
162 | + } | ||
153 | break; | 163 | break; |
154 | case LONG: | 164 | case LONG: |
155 | - json.addProperty(name, entry.getLongValue().get()); | 165 | + Optional<Long> longValue = entry.getLongValue(); |
166 | + if (longValue.isPresent()) { | ||
167 | + json.addProperty(name, longValue.get()); | ||
168 | + } | ||
156 | break; | 169 | break; |
157 | } | 170 | } |
158 | } | 171 | } |