Commit 935aab753506e2e5d46718ae458588ef1439e0a7

Authored by YevhenBondarenko
1 parent 7954f91f

added checksum and checksum algorithm for firmware

... ... @@ -32,10 +32,15 @@ CREATE TABLE IF NOT EXISTS firmware (
32 32 created_time bigint NOT NULL,
33 33 tenant_id uuid NOT NULL,
34 34 title varchar(255) NOT NULL,
  35 + version varchar(255) NOT NULL,
  36 + file_name varchar(255),
  37 + content_type varchar(255),
  38 + checksum_algorithm varchar(32),
  39 + checksum varchar(1020),
  40 + data binary,
  41 + additional_info varchar,
35 42 search_text varchar(255),
36   - file_name varchar(255) NOT NULL,
37   - content_type varchar(255) NOT NULL,
38   - data bytea
  43 + CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
39 44 );
40 45
41 46 ALTER TABLE device_profile
... ...
... ... @@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.page.PageData;
36 36 import org.thingsboard.server.common.data.page.PageLink;
37 37 import org.thingsboard.server.queue.util.TbCoreComponent;
38 38 import org.thingsboard.server.service.security.permission.Operation;
  39 +import org.thingsboard.server.service.security.permission.Resource;
39 40
40 41 import java.nio.ByteBuffer;
41 42
... ... @@ -97,14 +98,36 @@ public class FirmwareController extends BaseController {
97 98 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
98 99 @RequestMapping(value = "/firmware", method = RequestMethod.POST)
99 100 @ResponseBody
100   - public Firmware saveFirmware(@RequestParam("title") String title,
101   - @RequestBody MultipartFile firmwareFile) throws ThingsboardException {
102   - checkParameter("title", title);
  101 + public FirmwareInfo saveFirmwareInfo(@RequestParam("title") FirmwareInfo firmwareInfo) throws ThingsboardException {
  102 + checkEntity(firmwareInfo.getId(), firmwareInfo, Resource.FIRMWARE);
103 103 try {
104   - checkNotNull(firmwareFile);
105   - Firmware firmware = new Firmware();
  104 + return firmwareService.saveFirmwareInfo(firmwareInfo);
  105 + } catch (Exception e) {
  106 + throw handleException(e);
  107 + }
  108 + }
  109 +
  110 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
  111 + @RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.POST)
  112 + @ResponseBody
  113 + public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId,
  114 + @RequestParam String checksum,
  115 + @RequestParam String checksumAlgorithm,
  116 + @RequestBody MultipartFile firmwareFile) throws ThingsboardException {
  117 + checkParameter(FIRMWARE_ID, strFirmwareId);
  118 + checkParameter("checksum", checksum);
  119 + try {
  120 + FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
  121 + FirmwareInfo info = checkFirmwareInfoId(firmwareId, Operation.READ);
  122 +
  123 + Firmware firmware = new Firmware(firmwareId);
  124 + firmware.setCreatedTime(info.getCreatedTime());
106 125 firmware.setTenantId(getTenantId());
107   - firmware.setTitle(title);
  126 + firmware.setVersion(info.getVersion());
  127 + firmware.setAdditionalInfo(info.getAdditionalInfo());
  128 +
  129 + firmware.setChecksumAlgorithm(checksumAlgorithm);
  130 + firmware.setChecksum(checksum);
108 131 firmware.setFileName(firmwareFile.getOriginalFilename());
109 132 firmware.setContentType(firmwareFile.getContentType());
110 133 firmware.setData(ByteBuffer.wrap(firmwareFile.getBytes()));
... ...
... ... @@ -230,7 +230,6 @@ public class ThingsboardInstallService {
230 230 systemDataLoaderService.createAdminSettings();
231 231 systemDataLoaderService.loadSystemWidgets();
232 232 systemDataLoaderService.createOAuth2Templates();
233   - systemDataLoaderService.loadSystemLwm2mResources();
234 233 // systemDataLoaderService.loadSystemPlugins();
235 234 // systemDataLoaderService.loadSystemRules();
236 235
... ...
... ... @@ -22,9 +22,10 @@ import org.thingsboard.server.common.data.id.TenantId;
22 22 import org.thingsboard.server.common.data.page.PageData;
23 23 import org.thingsboard.server.common.data.page.PageLink;
24 24
25   -
26 25 public interface FirmwareService {
27 26
  27 + FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo);
  28 +
28 29 Firmware saveFirmware(Firmware firmware);
29 30
30 31 Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId);
... ...
... ... @@ -27,6 +27,14 @@ public class Firmware extends FirmwareInfo {
27 27
28 28 private static final long serialVersionUID = 3091601761339422546L;
29 29
  30 + private String fileName;
  31 +
  32 + private String contentType;
  33 +
  34 + private String checksumAlgorithm;
  35 +
  36 + private String checksum;
  37 +
30 38 private transient ByteBuffer data;
31 39
32 40 public Firmware() {
... ... @@ -39,6 +47,10 @@ public class Firmware extends FirmwareInfo {
39 47
40 48 public Firmware(Firmware firmware) {
41 49 super(firmware);
  50 + this.fileName = firmware.getFileName();
  51 + this.contentType = firmware.getContentType();
42 52 this.data = firmware.getData();
  53 + this.checksumAlgorithm = firmware.getChecksumAlgorithm();
  54 + this.checksum = firmware.getChecksum();
43 55 }
44 56 }
... ...
... ... @@ -24,14 +24,13 @@ import org.thingsboard.server.common.data.id.TenantId;
24 24 @Slf4j
25 25 @Data
26 26 @EqualsAndHashCode(callSuper = true)
27   -public class FirmwareInfo extends SearchTextBased<FirmwareId> implements HasTenantId {
  27 +public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId> implements HasTenantId {
28 28
29 29 private static final long serialVersionUID = 3168391583570815419L;
30 30
31 31 private TenantId tenantId;
32 32 private String title;
33   - private String fileName;
34   - private String contentType;
  33 + private String version;
35 34
36 35 public FirmwareInfo() {
37 36 super();
... ... @@ -45,8 +44,7 @@ public class FirmwareInfo extends SearchTextBased<FirmwareId> implements HasTena
45 44 super(firmwareInfo);
46 45 this.tenantId = firmwareInfo.getTenantId();
47 46 this.title = firmwareInfo.getTitle();
48   - this.fileName = firmwareInfo.getFileName();
49   - this.contentType = firmwareInfo.getContentType();
  47 + this.version = firmwareInfo.getVersion();
50 48 }
51 49
52 50 @Override
... ...
... ... @@ -40,6 +40,7 @@ import org.thingsboard.server.common.data.DeviceProfileInfo;
40 40 import org.thingsboard.server.common.data.DeviceProfileProvisionType;
41 41 import org.thingsboard.server.common.data.DeviceProfileType;
42 42 import org.thingsboard.server.common.data.DeviceTransportType;
  43 +import org.thingsboard.server.common.data.Firmware;
43 44 import org.thingsboard.server.common.data.Tenant;
44 45 import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration;
45 46 import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration;
... ... @@ -59,6 +60,7 @@ import org.thingsboard.server.common.data.page.PageData;
59 60 import org.thingsboard.server.common.data.page.PageLink;
60 61 import org.thingsboard.server.dao.entity.AbstractEntityService;
61 62 import org.thingsboard.server.dao.exception.DataValidationException;
  63 +import org.thingsboard.server.dao.firmware.FirmwareService;
62 64 import org.thingsboard.server.dao.service.DataValidator;
63 65 import org.thingsboard.server.dao.service.PaginatedRemover;
64 66 import org.thingsboard.server.dao.service.Validator;
... ... @@ -107,6 +109,9 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
107 109 @Autowired
108 110 private CacheManager cacheManager;
109 111
  112 + @Autowired
  113 + private FirmwareService firmwareService;
  114 +
110 115 private final Lock findOrCreateLock = new ReentrantLock();
111 116
112 117 @Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{#deviceProfileId.id}")
... ... @@ -389,6 +394,15 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
389 394 }
390 395 }
391 396
  397 + if (deviceProfile.getFirmwareId() != null) {
  398 + Firmware firmware = firmwareService.findFirmwareById(tenantId, deviceProfile.getFirmwareId());
  399 + if (firmware == null) {
  400 + throw new DataValidationException("Can't assign non-existent firmware!");
  401 + }
  402 + if (firmware.getData() == null) {
  403 + throw new DataValidationException("Can't assign firmware with empty data!");
  404 + }
  405 + }
392 406 }
393 407
394 408 @Override
... ...
... ... @@ -39,6 +39,7 @@ import org.thingsboard.server.common.data.DeviceProfile;
39 39 import org.thingsboard.server.common.data.EntitySubtype;
40 40 import org.thingsboard.server.common.data.EntityType;
41 41 import org.thingsboard.server.common.data.EntityView;
  42 +import org.thingsboard.server.common.data.Firmware;
42 43 import org.thingsboard.server.common.data.Tenant;
43 44 import org.thingsboard.server.common.data.device.DeviceSearchQuery;
44 45 import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
... ... @@ -68,6 +69,7 @@ import org.thingsboard.server.dao.entity.AbstractEntityService;
68 69 import org.thingsboard.server.dao.entityview.EntityViewService;
69 70 import org.thingsboard.server.dao.event.EventService;
70 71 import org.thingsboard.server.dao.exception.DataValidationException;
  72 +import org.thingsboard.server.dao.firmware.FirmwareService;
71 73 import org.thingsboard.server.dao.service.DataValidator;
72 74 import org.thingsboard.server.dao.service.PaginatedRemover;
73 75 import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
... ... @@ -128,6 +130,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
128 130 @Lazy
129 131 private TbTenantProfileCache tenantProfileCache;
130 132
  133 + @Autowired
  134 + private FirmwareService firmwareService;
  135 +
131 136 @Override
132 137 public DeviceInfo findDeviceInfoById(TenantId tenantId, DeviceId deviceId) {
133 138 log.trace("Executing findDeviceInfoById [{}]", deviceId);
... ... @@ -598,6 +603,16 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
598 603 throw new DataValidationException("Can't assign device to customer from different tenant!");
599 604 }
600 605 }
  606 +
  607 + if (device.getFirmwareId() != null) {
  608 + Firmware firmware = firmwareService.findFirmwareById(tenantId, device.getFirmwareId());
  609 + if (firmware == null) {
  610 + throw new DataValidationException("Can't assign non-existent firmware!");
  611 + }
  612 + if (firmware.getData() == null) {
  613 + throw new DataValidationException("Can't assign firmware with empty data!");
  614 + }
  615 + }
601 616 }
602 617 };
603 618
... ...
... ... @@ -15,6 +15,8 @@
15 15 */
16 16 package org.thingsboard.server.dao.firmware;
17 17
  18 +import com.google.common.hash.HashFunction;
  19 +import com.google.common.hash.Hashing;
18 20 import lombok.extern.slf4j.Slf4j;
19 21 import org.apache.commons.lang3.StringUtils;
20 22 import org.hibernate.exception.ConstraintViolationException;
... ... @@ -54,10 +56,35 @@ public class BaseFirmwareService implements FirmwareService {
54 56 }
55 57
56 58 @Override
  59 + public FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo) {
  60 + log.trace("Executing saveFirmwareInfo [{}]", firmwareInfo);
  61 + firmwareInfoValidator.validate(firmwareInfo, FirmwareInfo::getTenantId);
  62 + try {
  63 + return firmwareInfoDao.save(firmwareInfo.getTenantId(), firmwareInfo);
  64 + } catch (Exception t) {
  65 + ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
  66 + if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("firmware_tenant_title_version_unq_key")) {
  67 + throw new DataValidationException("Firmware with such title and version already exists!");
  68 + } else {
  69 + throw t;
  70 + }
  71 + }
  72 + }
  73 +
  74 + @Override
57 75 public Firmware saveFirmware(Firmware firmware) {
58 76 log.trace("Executing saveFirmware [{}]", firmware);
59   - firmwareValidator.validate(firmware, Firmware::getTenantId);
60   - return firmwareDao.save(firmware.getTenantId(), firmware);
  77 + firmwareValidator.validate(firmware, FirmwareInfo::getTenantId);
  78 + try {
  79 + return firmwareDao.save(firmware.getTenantId(), firmware);
  80 + } catch (Exception t) {
  81 + ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
  82 + if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("firmware_tenant_title_version_unq_key")) {
  83 + throw new DataValidationException("Firmware with such title and version already exists!");
  84 + } else {
  85 + throw t;
  86 + }
  87 + }
61 88 }
62 89
63 90 @Override
... ... @@ -107,6 +134,42 @@ public class BaseFirmwareService implements FirmwareService {
107 134 tenantFirmwareRemover.removeEntities(tenantId, tenantId);
108 135 }
109 136
  137 + private DataValidator<FirmwareInfo> firmwareInfoValidator = new DataValidator<>() {
  138 +
  139 + @Override
  140 + protected void validateDataImpl(TenantId tenantId, FirmwareInfo firmware) {
  141 + if (firmware.getTenantId() == null) {
  142 + throw new DataValidationException("Firmware should be assigned to tenant!");
  143 + } else {
  144 + Tenant tenant = tenantDao.findById(firmware.getTenantId(), firmware.getTenantId().getId());
  145 + if (tenant == null) {
  146 + throw new DataValidationException("Firmware is referencing to non-existent tenant!");
  147 + }
  148 + }
  149 +
  150 + if (StringUtils.isEmpty(firmware.getTitle())) {
  151 + throw new DataValidationException("Firmware title should be specified!");
  152 + }
  153 +
  154 + if (StringUtils.isEmpty(firmware.getVersion())) {
  155 + throw new DataValidationException("Firmware version should be specified!");
  156 + }
  157 + }
  158 +
  159 + @Override
  160 + protected void validateUpdate(TenantId tenantId, FirmwareInfo firmware) {
  161 + FirmwareInfo firmwareOld = firmwareInfoDao.findById(tenantId, firmware.getUuidId());
  162 +
  163 + if (!firmwareOld.getTitle().equals(firmware.getTitle())) {
  164 + throw new DataValidationException("Updating firmware title is prohibited!");
  165 + }
  166 +
  167 + if (!firmwareOld.getVersion().equals(firmware.getVersion())) {
  168 + throw new DataValidationException("Updating firmware version is prohibited!");
  169 + }
  170 + }
  171 + };
  172 +
110 173 private DataValidator<Firmware> firmwareValidator = new DataValidator<>() {
111 174
112 175 @Override
... ... @@ -123,22 +186,91 @@ public class BaseFirmwareService implements FirmwareService {
123 186 if (StringUtils.isEmpty(firmware.getTitle())) {
124 187 throw new DataValidationException("Firmware title should be specified!");
125 188 }
  189 +
  190 + if (StringUtils.isEmpty(firmware.getVersion())) {
  191 + throw new DataValidationException("Firmware version should be specified!");
  192 + }
  193 +
126 194 if (StringUtils.isEmpty(firmware.getFileName())) {
127 195 throw new DataValidationException("Firmware file name should be specified!");
128 196 }
  197 +
129 198 if (StringUtils.isEmpty(firmware.getContentType())) {
130 199 throw new DataValidationException("Firmware content type should be specified!");
131 200 }
  201 +
  202 + if (StringUtils.isEmpty(firmware.getChecksum())) {
  203 + throw new DataValidationException("Firmware checksum should be specified!");
  204 + }
  205 +
132 206 ByteBuffer data = firmware.getData();
133 207 if (data == null || !data.hasArray() || data.array().length == 0) {
134 208 throw new DataValidationException("Firmware data should be specified!");
135 209 }
  210 +
  211 + if (firmware.getChecksumAlgorithm() != null) {
  212 + HashFunction hashFunction;
  213 + switch (firmware.getChecksumAlgorithm()) {
  214 + case "sha256":
  215 + hashFunction = Hashing.sha256();
  216 + break;
  217 + case "md5":
  218 + hashFunction = Hashing.md5();
  219 + break;
  220 + case "crc32":
  221 + hashFunction = Hashing.crc32();
  222 + break;
  223 + default:
  224 + throw new DataValidationException("Unknown checksum algorithm!");
  225 + }
  226 +
  227 + String currentChecksum = hashFunction.hashBytes(data.array()).toString();
  228 + ;
  229 +
  230 + if (!currentChecksum.equals(firmware.getChecksum())) {
  231 + throw new DataValidationException("Wrong firmware file!");
  232 + }
  233 + }
  234 + }
  235 +
  236 + @Override
  237 + protected void validateUpdate(TenantId tenantId, Firmware firmware) {
  238 + Firmware firmwareOld = firmwareDao.findById(tenantId, firmware.getUuidId());
  239 +
  240 + if (!firmwareOld.getTitle().equals(firmware.getTitle())) {
  241 + throw new DataValidationException("Updating firmware title is prohibited!");
  242 + }
  243 +
  244 + if (!firmwareOld.getVersion().equals(firmware.getVersion())) {
  245 + throw new DataValidationException("Updating firmware version is prohibited!");
  246 + }
  247 +
  248 + if (firmwareOld.getFileName() != null && !firmwareOld.getFileName().equals(firmware.getFileName())) {
  249 + throw new DataValidationException("Updating firmware file name is prohibited!");
  250 + }
  251 +
  252 + if (firmwareOld.getContentType() != null && !firmwareOld.getContentType().equals(firmware.getContentType())) {
  253 + throw new DataValidationException("Updating firmware content type is prohibited!");
  254 + }
  255 +
  256 + if (firmwareOld.getChecksumAlgorithm() != null && !firmwareOld.getChecksumAlgorithm().equals(firmware.getChecksumAlgorithm())) {
  257 + throw new DataValidationException("Updating firmware content type is prohibited!");
  258 + }
  259 +
  260 + if (firmwareOld.getChecksum() != null && !firmwareOld.getChecksum().equals(firmware.getChecksum())) {
  261 + throw new DataValidationException("Updating firmware content type is prohibited!");
  262 + }
  263 +
  264 + if (firmwareOld.getData() != null && !firmwareOld.getData().equals(firmware.getData())) {
  265 + throw new DataValidationException("Updating firmware data is prohibited!");
  266 + }
136 267 }
137 268 };
138 269
139 270 private PaginatedRemover<TenantId, FirmwareInfo> tenantFirmwareRemover =
140 271 new PaginatedRemover<>() {
141 272
  273 +
142 274 @Override
143 275 protected PageData<FirmwareInfo> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {
144 276 return firmwareInfoDao.findFirmwareInfoByTenantId(id, pageLink);
... ...
... ... @@ -475,9 +475,14 @@ public class ModelConstants {
475 475 public static final String FIRMWARE_TABLE_NAME = "firmware";
476 476 public static final String FIRMWARE_TENANT_ID_COLUMN = TENANT_ID_COLUMN;
477 477 public static final String FIRMWARE_TITLE_COLUMN = TITLE_PROPERTY;
  478 + public static final String FIRMWARE_VERSION_COLUMN = "version";
478 479 public static final String FIRMWARE_FILE_NAME_COLUMN = "file_name";
479 480 public static final String FIRMWARE_CONTENT_TYPE_COLUMN = "content_type";
  481 + public static final String FIRMWARE_CHECKSUM_ALGORITHM_COLUMN = "checksum_algorithm";
  482 + public static final String FIRMWARE_CHECKSUM_COLUMN = "checksum";
480 483 public static final String FIRMWARE_DATA_COLUMN = "data";
  484 + public static final String FIRMWARE_ADDITIONAL_INFO_COLUMN = ADDITIONAL_INFO_PROPERTY;
  485 +
481 486
482 487 /**
483 488 * Cassandra attributes and timeseries constants.
... ...
... ... @@ -15,13 +15,18 @@
15 15 */
16 16 package org.thingsboard.server.dao.model.sql;
17 17
  18 +import com.fasterxml.jackson.databind.JsonNode;
18 19 import lombok.Data;
19 20 import lombok.EqualsAndHashCode;
  21 +import org.hibernate.annotations.Type;
  22 +import org.hibernate.annotations.TypeDef;
20 23 import org.thingsboard.server.common.data.Firmware;
21 24 import org.thingsboard.server.common.data.id.FirmwareId;
22 25 import org.thingsboard.server.common.data.id.TenantId;
23 26 import org.thingsboard.server.dao.model.BaseSqlEntity;
  27 +import org.thingsboard.server.dao.model.ModelConstants;
24 28 import org.thingsboard.server.dao.model.SearchTextEntity;
  29 +import org.thingsboard.server.dao.util.mapping.JsonStringType;
25 30
26 31 import javax.persistence.Column;
27 32 import javax.persistence.Entity;
... ... @@ -29,17 +34,21 @@ import javax.persistence.Table;
29 34 import java.nio.ByteBuffer;
30 35 import java.util.UUID;
31 36
  37 +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_ALGORITHM_COLUMN;
  38 +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_COLUMN;
32 39 import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CONTENT_TYPE_COLUMN;
33 40 import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_COLUMN;
34 41 import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME_COLUMN;
35 42 import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME;
36 43 import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN;
37 44 import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN;
  45 +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_VERSION_COLUMN;
38 46 import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY;
39 47
40 48 @Data
41 49 @EqualsAndHashCode(callSuper = true)
42 50 @Entity
  51 +@TypeDef(name = "json", typeClass = JsonStringType.class)
43 52 @Table(name = FIRMWARE_TABLE_NAME)
44 53 public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTextEntity<Firmware> {
45 54
... ... @@ -49,15 +58,28 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex
49 58 @Column(name = FIRMWARE_TITLE_COLUMN)
50 59 private String title;
51 60
  61 + @Column(name = FIRMWARE_VERSION_COLUMN)
  62 + private String version;
  63 +
52 64 @Column(name = FIRMWARE_FILE_NAME_COLUMN)
53 65 private String fileName;
54 66
55 67 @Column(name = FIRMWARE_CONTENT_TYPE_COLUMN)
56 68 private String contentType;
57 69
  70 + @Column(name = FIRMWARE_CHECKSUM_ALGORITHM_COLUMN)
  71 + private String checksumAlgorithm;
  72 +
  73 + @Column(name = FIRMWARE_CHECKSUM_COLUMN)
  74 + private String checksum;
  75 +
58 76 @Column(name = FIRMWARE_DATA_COLUMN, columnDefinition = "BINARY")
59 77 private byte[] data;
60 78
  79 + @Type(type = "json")
  80 + @Column(name = ModelConstants.FIRMWARE_ADDITIONAL_INFO_COLUMN)
  81 + private JsonNode additionalInfo;
  82 +
61 83 @Column(name = SEARCH_TEXT_PROPERTY)
62 84 private String searchText;
63 85
... ... @@ -70,9 +92,13 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex
70 92 this.setUuid(firmware.getUuidId());
71 93 this.tenantId = firmware.getTenantId().getId();
72 94 this.title = firmware.getTitle();
  95 + this.version = firmware.getVersion();
73 96 this.fileName = firmware.getFileName();
74 97 this.contentType = firmware.getContentType();
  98 + this.checksumAlgorithm = firmware.getChecksumAlgorithm();
  99 + this.checksum = firmware.getChecksum();
75 100 this.data = firmware.getData().array();
  101 + this.additionalInfo = firmware.getAdditionalInfo();
76 102 }
77 103
78 104 @Override
... ... @@ -91,9 +117,15 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex
91 117 firmware.setCreatedTime(createdTime);
92 118 firmware.setTenantId(new TenantId(tenantId));
93 119 firmware.setTitle(title);
  120 + firmware.setVersion(version);
94 121 firmware.setFileName(fileName);
95 122 firmware.setContentType(contentType);
96   - firmware.setData(ByteBuffer.wrap(data));
  123 + firmware.setChecksumAlgorithm(checksumAlgorithm);
  124 + firmware.setChecksum(checksum);
  125 + if (data != null) {
  126 + firmware.setData(ByteBuffer.wrap(data));
  127 + }
  128 + firmware.setAdditionalInfo(additionalInfo);
97 129 return firmware;
98 130 }
99 131 }
... ...
... ... @@ -15,29 +15,34 @@
15 15 */
16 16 package org.thingsboard.server.dao.model.sql;
17 17
  18 +import com.fasterxml.jackson.databind.JsonNode;
18 19 import lombok.Data;
19 20 import lombok.EqualsAndHashCode;
  21 +import org.hibernate.annotations.Type;
  22 +import org.hibernate.annotations.TypeDef;
20 23 import org.thingsboard.server.common.data.FirmwareInfo;
21 24 import org.thingsboard.server.common.data.id.FirmwareId;
22 25 import org.thingsboard.server.common.data.id.TenantId;
23 26 import org.thingsboard.server.dao.model.BaseSqlEntity;
  27 +import org.thingsboard.server.dao.model.ModelConstants;
24 28 import org.thingsboard.server.dao.model.SearchTextEntity;
  29 +import org.thingsboard.server.dao.util.mapping.JsonStringType;
25 30
26 31 import javax.persistence.Column;
27 32 import javax.persistence.Entity;
28 33 import javax.persistence.Table;
29 34 import java.util.UUID;
30 35
31   -import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CONTENT_TYPE_COLUMN;
32   -import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME_COLUMN;
33 36 import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME;
34 37 import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN;
35 38 import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN;
  39 +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_VERSION_COLUMN;
36 40 import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY;
37 41
38 42 @Data
39 43 @EqualsAndHashCode(callSuper = true)
40 44 @Entity
  45 +@TypeDef(name = "json", typeClass = JsonStringType.class)
41 46 @Table(name = FIRMWARE_TABLE_NAME)
42 47 public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements SearchTextEntity<FirmwareInfo> {
43 48
... ... @@ -47,11 +52,12 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
47 52 @Column(name = FIRMWARE_TITLE_COLUMN)
48 53 private String title;
49 54
50   - @Column(name = FIRMWARE_FILE_NAME_COLUMN)
51   - private String fileName;
  55 + @Column(name = FIRMWARE_VERSION_COLUMN)
  56 + private String version;
52 57
53   - @Column(name = FIRMWARE_CONTENT_TYPE_COLUMN)
54   - private String contentType;
  58 + @Type(type = "json")
  59 + @Column(name = ModelConstants.FIRMWARE_ADDITIONAL_INFO_COLUMN)
  60 + private JsonNode additionalInfo;
55 61
56 62 @Column(name = SEARCH_TEXT_PROPERTY)
57 63 private String searchText;
... ... @@ -65,8 +71,8 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
65 71 this.setUuid(firmware.getUuidId());
66 72 this.tenantId = firmware.getTenantId().getId();
67 73 this.title = firmware.getTitle();
68   - this.fileName = firmware.getFileName();
69   - this.contentType = firmware.getContentType();
  74 + this.version = firmware.getVersion();
  75 + this.additionalInfo = firmware.getAdditionalInfo();
70 76 }
71 77
72 78 @Override
... ... @@ -85,8 +91,8 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
85 91 firmware.setCreatedTime(createdTime);
86 92 firmware.setTenantId(new TenantId(tenantId));
87 93 firmware.setTitle(title);
88   - firmware.setFileName(fileName);
89   - firmware.setContentType(contentType);
  94 + firmware.setVersion(version);
  95 + firmware.setAdditionalInfo(additionalInfo);
90 96 return firmware;
91 97 }
92 98 }
... ...
... ... @@ -162,10 +162,15 @@ CREATE TABLE IF NOT EXISTS firmware (
162 162 created_time bigint NOT NULL,
163 163 tenant_id uuid NOT NULL,
164 164 title varchar(255) NOT NULL,
  165 + version varchar(255) NOT NULL,
  166 + file_name varchar(255),
  167 + content_type varchar(255),
  168 + checksum_algorithm varchar(32),
  169 + checksum varchar(1020),
  170 + data binary,
  171 + additional_info varchar,
165 172 search_text varchar(255),
166   - file_name varchar(255) NOT NULL,
167   - content_type varchar(255) NOT NULL,
168   - data binary
  173 + CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
169 174 );
170 175
171 176 CREATE TABLE IF NOT EXISTS device_profile (
... ...
... ... @@ -180,10 +180,15 @@ CREATE TABLE IF NOT EXISTS firmware (
180 180 created_time bigint NOT NULL,
181 181 tenant_id uuid NOT NULL,
182 182 title varchar(255) NOT NULL,
  183 + version varchar(255) NOT NULL,
  184 + file_name varchar(255),
  185 + content_type varchar(255),
  186 + checksum_algorithm varchar(32),
  187 + checksum varchar(1020),
  188 + data bytea,
  189 + additional_info varchar,
183 190 search_text varchar(255),
184   - file_name varchar(255) NOT NULL,
185   - content_type varchar(255) NOT NULL,
186   - data bytea
  191 + CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
187 192 );
188 193
189 194 CREATE TABLE IF NOT EXISTS device_profile (
... ...
... ... @@ -24,7 +24,7 @@ import java.util.Arrays;
24 24
25 25 @RunWith(ClasspathSuite.class)
26 26 @ClassnameFilters({
27   - "org.thingsboard.server.dao.service.sql.FirmwareServiceSqlTest"
  27 + "org.thingsboard.server.dao.service.sql.*Test"
28 28 })
29 29 public class SqlDaoServiceTestSuite {
30 30
... ...
... ... @@ -27,19 +27,19 @@ import org.junit.Test;
27 27 import org.thingsboard.server.common.data.Device;
28 28 import org.thingsboard.server.common.data.DeviceProfile;
29 29 import org.thingsboard.server.common.data.DeviceProfileInfo;
30   -import org.thingsboard.server.common.data.DeviceProfileType;
31 30 import org.thingsboard.server.common.data.DeviceTransportType;
  31 +import org.thingsboard.server.common.data.Firmware;
32 32 import org.thingsboard.server.common.data.Tenant;
33 33 import org.thingsboard.server.common.data.id.TenantId;
34 34 import org.thingsboard.server.common.data.page.PageData;
35 35 import org.thingsboard.server.common.data.page.PageLink;
36 36 import org.thingsboard.server.dao.exception.DataValidationException;
37 37
  38 +import java.nio.ByteBuffer;
38 39 import java.util.ArrayList;
39 40 import java.util.Collections;
40 41 import java.util.List;
41 42 import java.util.concurrent.ExecutionException;
42   -import java.util.concurrent.ExecutorService;
43 43 import java.util.concurrent.Executors;
44 44 import java.util.stream.Collectors;
45 45
... ... @@ -83,17 +83,48 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
83 83 }
84 84
85 85 @Test
  86 + public void testSaveDeviceProfileWithFirmware() {
  87 + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile");
  88 + DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
  89 + Assert.assertNotNull(savedDeviceProfile);
  90 + Assert.assertNotNull(savedDeviceProfile.getId());
  91 + Assert.assertTrue(savedDeviceProfile.getCreatedTime() > 0);
  92 + Assert.assertEquals(deviceProfile.getName(), savedDeviceProfile.getName());
  93 + Assert.assertEquals(deviceProfile.getDescription(), savedDeviceProfile.getDescription());
  94 + Assert.assertEquals(deviceProfile.getProfileData(), savedDeviceProfile.getProfileData());
  95 + Assert.assertEquals(deviceProfile.isDefault(), savedDeviceProfile.isDefault());
  96 + Assert.assertEquals(deviceProfile.getDefaultRuleChainId(), savedDeviceProfile.getDefaultRuleChainId());
  97 +
  98 + Firmware firmware = new Firmware();
  99 + firmware.setTenantId(tenantId);
  100 + firmware.setTitle("my firmware");
  101 + firmware.setVersion("v1.0");
  102 + firmware.setFileName("test.txt");
  103 + firmware.setContentType("text/plain");
  104 + firmware.setChecksumAlgorithm("sha256");
  105 + firmware.setChecksum("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a");
  106 + firmware.setData(ByteBuffer.wrap(new byte[]{1}));
  107 + Firmware savedFirmware = firmwareService.saveFirmware(firmware);
  108 +
  109 + deviceProfile.setFirmwareId(savedFirmware.getId());
  110 +
  111 + deviceProfileService.saveDeviceProfile(savedDeviceProfile);
  112 + DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
  113 + Assert.assertEquals(savedDeviceProfile.getName(), foundDeviceProfile.getName());
  114 + }
  115 +
  116 + @Test
86 117 public void testFindDeviceProfileById() {
87   - DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
  118 + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile");
88 119 DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
89 120 DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
90 121 Assert.assertNotNull(foundDeviceProfile);
91 122 Assert.assertEquals(savedDeviceProfile, foundDeviceProfile);
92   - }
  123 + }
93 124
94 125 @Test
95 126 public void testFindDeviceProfileInfoById() {
96   - DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
  127 + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile");
97 128 DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
98 129 DeviceProfileInfo foundDeviceProfileInfo = deviceProfileService.findDeviceProfileInfoById(tenantId, savedDeviceProfile.getId());
99 130 Assert.assertNotNull(foundDeviceProfileInfo);
... ... @@ -124,7 +155,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
124 155 ListeningExecutorService testExecutor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(100));
125 156 try {
126 157 List<ListenableFuture<DeviceProfile>> futures = new ArrayList<>();
127   - for (int i = 0; i < 50; i ++) {
  158 + for (int i = 0; i < 50; i++) {
128 159 futures.add(testExecutor.submit(() -> deviceProfileService.findOrCreateDeviceProfile(tenantId, "Device Profile 1")));
129 160 futures.add(testExecutor.submit(() -> deviceProfileService.findOrCreateDeviceProfile(tenantId, "Device Profile 2")));
130 161 }
... ... @@ -138,8 +169,8 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
138 169
139 170 @Test
140 171 public void testSetDefaultDeviceProfile() {
141   - DeviceProfile deviceProfile1 = this.createDeviceProfile(tenantId,"Device Profile 1");
142   - DeviceProfile deviceProfile2 = this.createDeviceProfile(tenantId,"Device Profile 2");
  172 + DeviceProfile deviceProfile1 = this.createDeviceProfile(tenantId, "Device Profile 1");
  173 + DeviceProfile deviceProfile2 = this.createDeviceProfile(tenantId, "Device Profile 2");
143 174
144 175 DeviceProfile savedDeviceProfile1 = deviceProfileService.saveDeviceProfile(deviceProfile1);
145 176 DeviceProfile savedDeviceProfile2 = deviceProfileService.saveDeviceProfile(deviceProfile2);
... ... @@ -165,16 +196,16 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
165 196
166 197 @Test(expected = DataValidationException.class)
167 198 public void testSaveDeviceProfileWithSameName() {
168   - DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
  199 + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile");
169 200 deviceProfileService.saveDeviceProfile(deviceProfile);
170   - DeviceProfile deviceProfile2 = this.createDeviceProfile(tenantId,"Device Profile");
  201 + DeviceProfile deviceProfile2 = this.createDeviceProfile(tenantId, "Device Profile");
171 202 deviceProfileService.saveDeviceProfile(deviceProfile2);
172 203 }
173 204
174 205 @Ignore
175 206 @Test(expected = DataValidationException.class)
176 207 public void testChangeDeviceProfileTypeWithExistingDevices() {
177   - DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
  208 + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile");
178 209 DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
179 210 Device device = new Device();
180 211 device.setTenantId(tenantId);
... ... @@ -189,7 +220,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
189 220
190 221 @Test(expected = DataValidationException.class)
191 222 public void testChangeDeviceProfileTransportTypeWithExistingDevices() {
192   - DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
  223 + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile");
193 224 DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
194 225 Device device = new Device();
195 226 device.setTenantId(tenantId);
... ... @@ -203,7 +234,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
203 234
204 235 @Test(expected = DataValidationException.class)
205 236 public void testDeleteDeviceProfileWithExistingDevice() {
206   - DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
  237 + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile");
207 238 DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
208 239 Device device = new Device();
209 240 device.setTenantId(tenantId);
... ... @@ -216,7 +247,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
216 247
217 248 @Test
218 249 public void testDeleteDeviceProfile() {
219   - DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
  250 + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile");
220 251 DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
221 252 deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
222 253 DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
... ... @@ -233,8 +264,8 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
233 264 Assert.assertEquals(1, pageData.getTotalElements());
234 265 deviceProfiles.addAll(pageData.getData());
235 266
236   - for (int i=0;i<28;i++) {
237   - DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile"+i);
  267 + for (int i = 0; i < 28; i++) {
  268 + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile" + i);
238 269 deviceProfiles.add(deviceProfileService.saveDeviceProfile(deviceProfile));
239 270 }
240 271
... ... @@ -275,8 +306,8 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
275 306 Assert.assertEquals(1, deviceProfilePageData.getTotalElements());
276 307 deviceProfiles.addAll(deviceProfilePageData.getData());
277 308
278   - for (int i=0;i<28;i++) {
279   - DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile"+i);
  309 + for (int i = 0; i < 28; i++) {
  310 + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile" + i);
280 311 deviceProfiles.add(deviceProfileService.saveDeviceProfile(deviceProfile));
281 312 }
282 313
... ... @@ -297,7 +328,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
297 328
298 329 List<DeviceProfileInfo> deviceProfileInfos = deviceProfiles.stream()
299 330 .map(deviceProfile -> new DeviceProfileInfo(deviceProfile.getId(),
300   - deviceProfile.getName(), deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList());
  331 + deviceProfile.getName(), deviceProfile.getType(), deviceProfile.getTransportType())).collect(Collectors.toList());
301 332
302 333 Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos);
303 334
... ... @@ -312,4 +343,5 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
312 343 Assert.assertFalse(pageData.hasNext());
313 344 Assert.assertEquals(1, pageData.getTotalElements());
314 345 }
  346 +
315 347 }
... ...
... ... @@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials;
30 30 import org.thingsboard.server.common.data.security.DeviceCredentialsType;
31 31 import org.thingsboard.server.dao.exception.DataValidationException;
32 32
  33 +import java.nio.ByteBuffer;
33 34 import java.util.ArrayList;
34 35 import java.util.Collections;
35 36 import java.util.List;
... ... @@ -88,6 +89,49 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest {
88 89
89 90 deviceService.deleteDevice(tenantId, savedDevice.getId());
90 91 }
  92 +
  93 + @Test
  94 + public void testSaveDeviceWithFirmware() {
  95 + Device device = new Device();
  96 + device.setTenantId(tenantId);
  97 + device.setName("My device");
  98 + device.setType("default");
  99 + Device savedDevice = deviceService.saveDevice(device);
  100 +
  101 + Assert.assertNotNull(savedDevice);
  102 + Assert.assertNotNull(savedDevice.getId());
  103 + Assert.assertTrue(savedDevice.getCreatedTime() > 0);
  104 + Assert.assertEquals(device.getTenantId(), savedDevice.getTenantId());
  105 + Assert.assertNotNull(savedDevice.getCustomerId());
  106 + Assert.assertEquals(NULL_UUID, savedDevice.getCustomerId().getId());
  107 + Assert.assertEquals(device.getName(), savedDevice.getName());
  108 +
  109 + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, savedDevice.getId());
  110 + Assert.assertNotNull(deviceCredentials);
  111 + Assert.assertNotNull(deviceCredentials.getId());
  112 + Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId());
  113 + Assert.assertEquals(DeviceCredentialsType.ACCESS_TOKEN, deviceCredentials.getCredentialsType());
  114 + Assert.assertNotNull(deviceCredentials.getCredentialsId());
  115 + Assert.assertEquals(20, deviceCredentials.getCredentialsId().length());
  116 +
  117 +
  118 + Firmware firmware = new Firmware();
  119 + firmware.setTenantId(tenantId);
  120 + firmware.setTitle("my firmware");
  121 + firmware.setVersion("v1.0");
  122 + firmware.setFileName("test.txt");
  123 + firmware.setContentType("text/plain");
  124 + firmware.setChecksumAlgorithm("sha256");
  125 + firmware.setChecksum("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a");
  126 + firmware.setData(ByteBuffer.wrap(new byte[]{1}));
  127 + Firmware savedFirmware = firmwareService.saveFirmware(firmware);
  128 +
  129 + savedDevice.setFirmwareId(savedFirmware.getId());
  130 +
  131 + deviceService.saveDevice(savedDevice);
  132 + Device foundDevice = deviceService.findDeviceById(tenantId, savedDevice.getId());
  133 + Assert.assertEquals(foundDevice.getName(), savedDevice.getName());
  134 + }
91 135
92 136 @Test(expected = DataValidationException.class)
93 137 public void testSaveDeviceWithEmptyName() {
... ...
... ... @@ -20,6 +20,7 @@ import org.junit.After;
20 20 import org.junit.Assert;
21 21 import org.junit.Before;
22 22 import org.junit.Test;
  23 +import org.thingsboard.common.util.JacksonUtil;
23 24 import org.thingsboard.server.common.data.Device;
24 25 import org.thingsboard.server.common.data.DeviceProfile;
25 26 import org.thingsboard.server.common.data.Firmware;
... ... @@ -39,8 +40,11 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
39 40
40 41 public static final String TITLE = "My firmware";
41 42 private static final String FILE_NAME = "filename.txt";
  43 + private static final String VERSION = "v1.0";
42 44 private static final String CONTENT_TYPE = "text/plain";
43   - private static final ByteBuffer DATA = ByteBuffer.wrap(new byte[]{0});
  45 + private static final String CHECKSUM_ALGORITHM = "sha256";
  46 + private static final String CHECKSUM = "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a";
  47 + private static final ByteBuffer DATA = ByteBuffer.wrap(new byte[]{1});
44 48
45 49 private IdComparator<FirmwareInfo> idComparator = new IdComparator<>();
46 50
... ... @@ -65,8 +69,11 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
65 69 Firmware firmware = new Firmware();
66 70 firmware.setTenantId(tenantId);
67 71 firmware.setTitle(TITLE);
  72 + firmware.setVersion(VERSION);
68 73 firmware.setFileName(FILE_NAME);
69 74 firmware.setContentType(CONTENT_TYPE);
  75 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  76 + firmware.setChecksum(CHECKSUM);
70 77 firmware.setData(DATA);
71 78 Firmware savedFirmware = firmwareService.saveFirmware(firmware);
72 79
... ... @@ -79,7 +86,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
79 86 Assert.assertEquals(firmware.getContentType(), savedFirmware.getContentType());
80 87 Assert.assertEquals(firmware.getData(), savedFirmware.getData());
81 88
82   - savedFirmware.setTitle("My new firmware");
  89 + savedFirmware.setAdditionalInfo(JacksonUtil.newObjectNode());
83 90 firmwareService.saveFirmware(savedFirmware);
84 91
85 92 Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId());
... ... @@ -88,12 +95,52 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
88 95 firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
89 96 }
90 97
  98 + @Test
  99 + public void testSaveFirmwareInfoAndUpdateWithData() {
  100 + FirmwareInfo firmwareInfo = new FirmwareInfo();
  101 + firmwareInfo.setTenantId(tenantId);
  102 + firmwareInfo.setTitle(TITLE);
  103 + firmwareInfo.setVersion(VERSION);
  104 + FirmwareInfo savedFirmwareInfo = firmwareService.saveFirmwareInfo(firmwareInfo);
  105 +
  106 + Assert.assertNotNull(savedFirmwareInfo);
  107 + Assert.assertNotNull(savedFirmwareInfo.getId());
  108 + Assert.assertTrue(savedFirmwareInfo.getCreatedTime() > 0);
  109 + Assert.assertEquals(firmwareInfo.getTenantId(), savedFirmwareInfo.getTenantId());
  110 + Assert.assertEquals(firmwareInfo.getTitle(), savedFirmwareInfo.getTitle());
  111 +
  112 + Firmware firmware = new Firmware(savedFirmwareInfo.getId());
  113 + firmware.setCreatedTime(firmwareInfo.getCreatedTime());
  114 + firmware.setTenantId(tenantId);
  115 + firmware.setTitle(TITLE);
  116 + firmware.setVersion(VERSION);
  117 + firmware.setFileName(FILE_NAME);
  118 + firmware.setContentType(CONTENT_TYPE);
  119 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  120 + firmware.setChecksum(CHECKSUM);
  121 + firmware.setData(DATA);
  122 +
  123 + firmwareService.saveFirmware(firmware);
  124 +
  125 + savedFirmwareInfo.setAdditionalInfo(JacksonUtil.newObjectNode());
  126 + firmwareService.saveFirmwareInfo(savedFirmwareInfo);
  127 +
  128 + Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, firmware.getId());
  129 + firmware.setAdditionalInfo(JacksonUtil.newObjectNode());
  130 + Assert.assertEquals(foundFirmware.getTitle(), firmware.getTitle());
  131 +
  132 + firmwareService.deleteFirmware(tenantId, savedFirmwareInfo.getId());
  133 + }
  134 +
91 135 @Test(expected = DataValidationException.class)
92 136 public void testSaveFirmwareWithEmptyTenant() {
93 137 Firmware firmware = new Firmware();
94 138 firmware.setTitle(TITLE);
  139 + firmware.setVersion(VERSION);
95 140 firmware.setFileName(FILE_NAME);
96 141 firmware.setContentType(CONTENT_TYPE);
  142 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  143 + firmware.setChecksum(CHECKSUM);
97 144 firmware.setData(DATA);
98 145 firmwareService.saveFirmware(firmware);
99 146 }
... ... @@ -102,8 +149,11 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
102 149 public void testSaveFirmwareWithEmptyTitle() {
103 150 Firmware firmware = new Firmware();
104 151 firmware.setTenantId(tenantId);
  152 + firmware.setVersion(VERSION);
105 153 firmware.setFileName(FILE_NAME);
106 154 firmware.setContentType(CONTENT_TYPE);
  155 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  156 + firmware.setChecksum(CHECKSUM);
107 157 firmware.setData(DATA);
108 158 firmwareService.saveFirmware(firmware);
109 159 }
... ... @@ -113,7 +163,10 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
113 163 Firmware firmware = new Firmware();
114 164 firmware.setTenantId(tenantId);
115 165 firmware.setTitle(TITLE);
  166 + firmware.setVersion(VERSION);
116 167 firmware.setContentType(CONTENT_TYPE);
  168 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  169 + firmware.setChecksum(CHECKSUM);
117 170 firmware.setData(DATA);
118 171 firmwareService.saveFirmware(firmware);
119 172 }
... ... @@ -123,7 +176,10 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
123 176 Firmware firmware = new Firmware();
124 177 firmware.setTenantId(tenantId);
125 178 firmware.setTitle(TITLE);
  179 + firmware.setVersion(VERSION);
126 180 firmware.setFileName(FILE_NAME);
  181 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  182 + firmware.setChecksum(CHECKSUM);
127 183 firmware.setData(DATA);
128 184 firmwareService.saveFirmware(firmware);
129 185 }
... ... @@ -133,8 +189,11 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
133 189 Firmware firmware = new Firmware();
134 190 firmware.setTenantId(tenantId);
135 191 firmware.setTitle(TITLE);
  192 + firmware.setVersion(VERSION);
136 193 firmware.setFileName(FILE_NAME);
137 194 firmware.setContentType(CONTENT_TYPE);
  195 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  196 + firmware.setChecksum(CHECKSUM);
138 197 firmwareService.saveFirmware(firmware);
139 198 }
140 199
... ... @@ -143,21 +202,76 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
143 202 Firmware firmware = new Firmware();
144 203 firmware.setTenantId(new TenantId(Uuids.timeBased()));
145 204 firmware.setTitle(TITLE);
  205 + firmware.setVersion(VERSION);
146 206 firmware.setFileName(FILE_NAME);
147 207 firmware.setContentType(CONTENT_TYPE);
  208 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  209 + firmware.setChecksum(CHECKSUM);
148 210 firmware.setData(DATA);
149 211 firmwareService.saveFirmware(firmware);
150 212 }
151 213
  214 + @Test(expected = DataValidationException.class)
  215 + public void testSaveFirmwareWithEmptyChecksum() {
  216 + Firmware firmware = new Firmware();
  217 + firmware.setTenantId(new TenantId(Uuids.timeBased()));
  218 + firmware.setTitle(TITLE);
  219 + firmware.setVersion(VERSION);
  220 + firmware.setFileName(FILE_NAME);
  221 + firmware.setContentType(CONTENT_TYPE);
  222 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  223 + firmware.setData(DATA);
  224 + firmwareService.saveFirmware(firmware);
  225 + }
152 226
  227 + @Test(expected = DataValidationException.class)
  228 + public void testSaveFirmwareInfoWithExistingTitleAndVersion() {
  229 + FirmwareInfo firmwareInfo = new FirmwareInfo();
  230 + firmwareInfo.setTenantId(tenantId);
  231 + firmwareInfo.setTitle(TITLE);
  232 + firmwareInfo.setVersion(VERSION);
  233 + firmwareService.saveFirmwareInfo(firmwareInfo);
  234 +
  235 + FirmwareInfo newFirmwareInfo = new FirmwareInfo();
  236 + newFirmwareInfo.setTenantId(tenantId);
  237 + newFirmwareInfo.setTitle(TITLE);
  238 + newFirmwareInfo.setVersion(VERSION);
  239 + firmwareService.saveFirmwareInfo(newFirmwareInfo);
  240 + }
  241 +
  242 + @Test(expected = DataValidationException.class)
  243 + public void testSaveFirmwareWithExistingTitleAndVersion() {
  244 + Firmware firmware = new Firmware();
  245 + firmware.setTenantId(tenantId);
  246 + firmware.setTitle(TITLE);
  247 + firmware.setVersion(VERSION);
  248 + firmware.setFileName(FILE_NAME);
  249 + firmware.setContentType(CONTENT_TYPE);
  250 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  251 + firmware.setChecksum(CHECKSUM);
  252 + firmware.setData(DATA);
  253 + firmwareService.saveFirmware(firmware);
  254 +
  255 + Firmware newFirmware = new Firmware();
  256 + newFirmware.setTenantId(tenantId);
  257 + newFirmware.setTitle(TITLE);
  258 + newFirmware.setVersion(VERSION);
  259 + newFirmware.setFileName(FILE_NAME);
  260 + newFirmware.setContentType(CONTENT_TYPE);
  261 + newFirmware.setData(DATA);
  262 + firmwareService.saveFirmware(newFirmware);
  263 + }
153 264
154 265 @Test(expected = DataValidationException.class)
155 266 public void testDeleteFirmwareWithReferenceByDevice() {
156 267 Firmware firmware = new Firmware();
157 268 firmware.setTenantId(tenantId);
158 269 firmware.setTitle(TITLE);
  270 + firmware.setVersion(VERSION);
159 271 firmware.setFileName(FILE_NAME);
160 272 firmware.setContentType(CONTENT_TYPE);
  273 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  274 + firmware.setChecksum(CHECKSUM);
161 275 firmware.setData(DATA);
162 276 Firmware savedFirmware = firmwareService.saveFirmware(firmware);
163 277
... ... @@ -181,8 +295,11 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
181 295 Firmware firmware = new Firmware();
182 296 firmware.setTenantId(tenantId);
183 297 firmware.setTitle(TITLE);
  298 + firmware.setVersion(VERSION);
184 299 firmware.setFileName(FILE_NAME);
185 300 firmware.setContentType(CONTENT_TYPE);
  301 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  302 + firmware.setChecksum(CHECKSUM);
186 303 firmware.setData(DATA);
187 304 Firmware savedFirmware = firmwareService.saveFirmware(firmware);
188 305
... ... @@ -203,8 +320,11 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
203 320 Firmware firmware = new Firmware();
204 321 firmware.setTenantId(tenantId);
205 322 firmware.setTitle(TITLE);
  323 + firmware.setVersion(VERSION);
206 324 firmware.setFileName(FILE_NAME);
207 325 firmware.setContentType(CONTENT_TYPE);
  326 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  327 + firmware.setChecksum(CHECKSUM);
208 328 firmware.setData(DATA);
209 329 Firmware savedFirmware = firmwareService.saveFirmware(firmware);
210 330
... ... @@ -219,8 +339,11 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
219 339 Firmware firmware = new Firmware();
220 340 firmware.setTenantId(tenantId);
221 341 firmware.setTitle(TITLE);
  342 + firmware.setVersion(VERSION);
222 343 firmware.setFileName(FILE_NAME);
223 344 firmware.setContentType(CONTENT_TYPE);
  345 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  346 + firmware.setChecksum(CHECKSUM);
224 347 firmware.setData(DATA);
225 348 Firmware savedFirmware = firmwareService.saveFirmware(firmware);
226 349
... ... @@ -238,8 +361,11 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
238 361 Firmware firmware = new Firmware();
239 362 firmware.setTenantId(tenantId);
240 363 firmware.setTitle(TITLE);
  364 + firmware.setVersion(VERSION + i);
241 365 firmware.setFileName(FILE_NAME);
242 366 firmware.setContentType(CONTENT_TYPE);
  367 + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
  368 + firmware.setChecksum(CHECKSUM);
243 369 firmware.setData(DATA);
244 370 firmwares.add(new FirmwareInfo(firmwareService.saveFirmware(firmware)));
245 371 }
... ...