committed by
GitHub
138 changed files with 4933 additions and 229 deletions
@ -0,0 +1,197 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.controller; |
|||
|
|||
import com.google.common.hash.Hashing; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.springframework.core.io.ByteArrayResource; |
|||
import org.springframework.http.HttpHeaders; |
|||
import org.springframework.http.ResponseEntity; |
|||
import org.springframework.security.access.prepost.PreAuthorize; |
|||
import org.springframework.web.bind.annotation.PathVariable; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestMethod; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.ResponseBody; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
import org.thingsboard.server.common.data.Firmware; |
|||
import org.thingsboard.server.common.data.FirmwareInfo; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.FirmwareId; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageLink; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.security.permission.Operation; |
|||
import org.thingsboard.server.service.security.permission.Resource; |
|||
|
|||
import java.nio.ByteBuffer; |
|||
|
|||
@Slf4j |
|||
@RestController |
|||
@TbCoreComponent |
|||
@RequestMapping("/api") |
|||
public class FirmwareController extends BaseController { |
|||
|
|||
public static final String FIRMWARE_ID = "firmwareId"; |
|||
|
|||
@PreAuthorize("hasAnyAuthority( 'TENANT_ADMIN')") |
|||
@RequestMapping(value = "/firmware/{firmwareId}/download", method = RequestMethod.GET) |
|||
@ResponseBody |
|||
public ResponseEntity<org.springframework.core.io.Resource> downloadFirmware(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException { |
|||
checkParameter(FIRMWARE_ID, strFirmwareId); |
|||
try { |
|||
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId)); |
|||
Firmware firmware = checkFirmwareId(firmwareId, Operation.READ); |
|||
|
|||
ByteArrayResource resource = new ByteArrayResource(firmware.getData().array()); |
|||
return ResponseEntity.ok() |
|||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + firmware.getFileName()) |
|||
.header("x-filename", firmware.getFileName()) |
|||
.contentLength(resource.contentLength()) |
|||
.contentType(parseMediaType(firmware.getContentType())) |
|||
.body(resource); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/firmware/info/{firmwareId}", method = RequestMethod.GET) |
|||
@ResponseBody |
|||
public FirmwareInfo getFirmwareInfoById(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException { |
|||
checkParameter(FIRMWARE_ID, strFirmwareId); |
|||
try { |
|||
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId)); |
|||
return checkFirmwareInfoId(firmwareId, Operation.READ); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.GET) |
|||
@ResponseBody |
|||
public Firmware getFirmwareById(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException { |
|||
checkParameter(FIRMWARE_ID, strFirmwareId); |
|||
try { |
|||
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId)); |
|||
return checkFirmwareId(firmwareId, Operation.READ); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/firmware", method = RequestMethod.POST) |
|||
@ResponseBody |
|||
public FirmwareInfo saveFirmwareInfo(@RequestBody FirmwareInfo firmwareInfo) throws ThingsboardException { |
|||
firmwareInfo.setTenantId(getTenantId()); |
|||
checkEntity(firmwareInfo.getId(), firmwareInfo, Resource.FIRMWARE); |
|||
try { |
|||
return firmwareService.saveFirmwareInfo(firmwareInfo); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.POST) |
|||
@ResponseBody |
|||
public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId, |
|||
@RequestParam(required = false) String checksum, |
|||
@RequestParam(required = false) String checksumAlgorithm, |
|||
@RequestBody MultipartFile file) throws ThingsboardException { |
|||
checkParameter(FIRMWARE_ID, strFirmwareId); |
|||
try { |
|||
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId)); |
|||
FirmwareInfo info = checkFirmwareInfoId(firmwareId, Operation.READ); |
|||
|
|||
Firmware firmware = new Firmware(firmwareId); |
|||
firmware.setCreatedTime(info.getCreatedTime()); |
|||
firmware.setTenantId(getTenantId()); |
|||
firmware.setTitle(info.getTitle()); |
|||
firmware.setVersion(info.getVersion()); |
|||
firmware.setAdditionalInfo(info.getAdditionalInfo()); |
|||
|
|||
byte[] data = file.getBytes(); |
|||
if (StringUtils.isEmpty(checksumAlgorithm)) { |
|||
checksumAlgorithm = "sha256"; |
|||
checksum = Hashing.sha256().hashBytes(data).toString(); |
|||
} |
|||
|
|||
firmware.setChecksumAlgorithm(checksumAlgorithm); |
|||
firmware.setChecksum(checksum); |
|||
firmware.setFileName(file.getOriginalFilename()); |
|||
firmware.setContentType(file.getContentType()); |
|||
firmware.setData(ByteBuffer.wrap(data)); |
|||
firmware.setDataSize((long) data.length); |
|||
return firmwareService.saveFirmware(firmware); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/firmwares", method = RequestMethod.GET) |
|||
@ResponseBody |
|||
public PageData<FirmwareInfo> getFirmwares(@RequestParam int pageSize, |
|||
@RequestParam int page, |
|||
@RequestParam(required = false) String textSearch, |
|||
@RequestParam(required = false) String sortProperty, |
|||
@RequestParam(required = false) String sortOrder) throws ThingsboardException { |
|||
try { |
|||
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
|||
return checkNotNull(firmwareService.findTenantFirmwaresByTenantId(getTenantId(), pageLink)); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/firmwares/{hasData}", method = RequestMethod.GET) |
|||
@ResponseBody |
|||
public PageData<FirmwareInfo> getFirmwares(@PathVariable("hasData") boolean hasData, |
|||
@RequestParam int pageSize, |
|||
@RequestParam int page, |
|||
@RequestParam(required = false) String textSearch, |
|||
@RequestParam(required = false) String sortProperty, |
|||
@RequestParam(required = false) String sortOrder) throws ThingsboardException { |
|||
try { |
|||
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
|||
return checkNotNull(firmwareService.findTenantFirmwaresByTenantIdAndHasData(getTenantId(), hasData, pageLink)); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
|||
@RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.DELETE) |
|||
@ResponseBody |
|||
public void deleteResource(@PathVariable("firmwareId") String strFirmwareId) throws ThingsboardException { |
|||
checkParameter(FIRMWARE_ID, strFirmwareId); |
|||
try { |
|||
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId)); |
|||
checkFirmwareInfoId(firmwareId, Operation.DELETE); |
|||
firmwareService.deleteFirmware(getTenantId(), firmwareId); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,260 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.service.firmware; |
|||
|
|||
import com.google.common.util.concurrent.FutureCallback; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; |
|||
import org.thingsboard.server.common.data.DataConstants; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.DeviceProfile; |
|||
import org.thingsboard.server.common.data.Firmware; |
|||
import org.thingsboard.server.common.data.FirmwareInfo; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.FirmwareId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
|||
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
|||
import org.thingsboard.server.common.data.kv.BasicTsKvEntry; |
|||
import org.thingsboard.server.common.data.kv.LongDataEntry; |
|||
import org.thingsboard.server.common.data.kv.StringDataEntry; |
|||
import org.thingsboard.server.common.data.kv.TsKvEntry; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageLink; |
|||
import org.thingsboard.server.common.msg.queue.TbCallback; |
|||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|||
import org.thingsboard.server.dao.device.DeviceProfileService; |
|||
import org.thingsboard.server.dao.device.DeviceService; |
|||
import org.thingsboard.server.dao.firmware.FirmwareService; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg; |
|||
import org.thingsboard.server.queue.TbQueueProducer; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.queue.provider.TbCoreQueueFactory; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
|
|||
import javax.annotation.Nullable; |
|||
import java.util.ArrayList; |
|||
import java.util.Arrays; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
import java.util.function.Consumer; |
|||
|
|||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_CHECKSUM; |
|||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_CHECKSUM_ALGORITHM; |
|||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_SIZE; |
|||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_TITLE; |
|||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_VERSION; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
@TbCoreComponent |
|||
public class DefaultFirmwareStateService implements FirmwareStateService { |
|||
|
|||
private final FirmwareService firmwareService; |
|||
private final DeviceService deviceService; |
|||
private final DeviceProfileService deviceProfileService; |
|||
private final RuleEngineTelemetryService telemetryService; |
|||
private final TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> fwStateMsgProducer; |
|||
|
|||
public DefaultFirmwareStateService(FirmwareService firmwareService, |
|||
DeviceService deviceService, |
|||
DeviceProfileService deviceProfileService, |
|||
RuleEngineTelemetryService telemetryService, |
|||
TbCoreQueueFactory coreQueueFactory) { |
|||
this.firmwareService = firmwareService; |
|||
this.deviceService = deviceService; |
|||
this.deviceProfileService = deviceProfileService; |
|||
this.telemetryService = telemetryService; |
|||
this.fwStateMsgProducer = coreQueueFactory.createToFirmwareStateServiceMsgProducer(); |
|||
} |
|||
|
|||
@Override |
|||
public void update(Device device, Device oldDevice) { |
|||
FirmwareId newFirmwareId = device.getFirmwareId(); |
|||
if (newFirmwareId == null) { |
|||
DeviceProfile newDeviceProfile = deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId()); |
|||
newFirmwareId = newDeviceProfile.getFirmwareId(); |
|||
} |
|||
if (oldDevice != null) { |
|||
if (newFirmwareId != null) { |
|||
FirmwareId oldFirmwareId = oldDevice.getFirmwareId(); |
|||
if (oldFirmwareId == null) { |
|||
DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(oldDevice.getTenantId(), oldDevice.getDeviceProfileId()); |
|||
oldFirmwareId = oldDeviceProfile.getFirmwareId(); |
|||
} |
|||
if (!newFirmwareId.equals(oldFirmwareId)) { |
|||
// Device was updated and new firmware is different from previous firmware.
|
|||
send(device.getTenantId(), device.getId(), newFirmwareId, System.currentTimeMillis()); |
|||
} |
|||
} else { |
|||
// Device was updated and new firmware is not set.
|
|||
remove(device); |
|||
} |
|||
} else if (newFirmwareId != null) { |
|||
// Device was created and firmware is defined.
|
|||
send(device.getTenantId(), device.getId(), newFirmwareId, System.currentTimeMillis()); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void update(DeviceProfile deviceProfile) { |
|||
TenantId tenantId = deviceProfile.getTenantId(); |
|||
|
|||
Consumer<Device> updateConsumer; |
|||
if (deviceProfile.getFirmwareId() != null) { |
|||
long ts = System.currentTimeMillis(); |
|||
updateConsumer = d -> send(d.getTenantId(), d.getId(), deviceProfile.getFirmwareId(), ts); |
|||
} else { |
|||
updateConsumer = this::remove; |
|||
} |
|||
|
|||
PageLink pageLink = new PageLink(100); |
|||
PageData<Device> pageData; |
|||
do { |
|||
pageData = deviceService.findDevicesByTenantIdAndTypeAndEmptyFirmware(tenantId, deviceProfile.getName(), pageLink); |
|||
|
|||
pageData.getData().forEach(updateConsumer); |
|||
|
|||
if (pageData.hasNext()) { |
|||
pageLink = pageLink.nextPageLink(); |
|||
} |
|||
} while (pageData.hasNext()); |
|||
} |
|||
|
|||
@Override |
|||
public boolean process(ToFirmwareStateServiceMsg msg) { |
|||
boolean isSuccess = false; |
|||
FirmwareId targetFirmwareId = new FirmwareId(new UUID(msg.getFirmwareIdMSB(), msg.getFirmwareIdLSB())); |
|||
DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB())); |
|||
TenantId tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); |
|||
long ts = msg.getTs(); |
|||
|
|||
Device device = deviceService.findDeviceById(tenantId, deviceId); |
|||
if (device == null) { |
|||
log.warn("[{}] [{}] Device was removed during firmware update msg was queued!", tenantId, deviceId); |
|||
} else { |
|||
FirmwareId currentFirmwareId = device.getFirmwareId(); |
|||
|
|||
if (currentFirmwareId == null) { |
|||
currentFirmwareId = deviceProfileService.findDeviceProfileById(tenantId, device.getDeviceProfileId()).getFirmwareId(); |
|||
} |
|||
|
|||
if (targetFirmwareId.equals(currentFirmwareId)) { |
|||
update(device, firmwareService.findFirmwareById(device.getTenantId(), targetFirmwareId), ts); |
|||
isSuccess = true; |
|||
} else { |
|||
log.warn("[{}] [{}] Can`t update firmware for the device, target firmwareId: [{}], current firmwareId: [{}]!", tenantId, deviceId, targetFirmwareId, currentFirmwareId); |
|||
} |
|||
} |
|||
return isSuccess; |
|||
} |
|||
|
|||
private void send(TenantId tenantId, DeviceId deviceId, FirmwareId firmwareId, long ts) { |
|||
ToFirmwareStateServiceMsg msg = ToFirmwareStateServiceMsg.newBuilder() |
|||
.setTenantIdMSB(tenantId.getId().getMostSignificantBits()) |
|||
.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) |
|||
.setDeviceIdMSB(deviceId.getId().getMostSignificantBits()) |
|||
.setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) |
|||
.setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits()) |
|||
.setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits()) |
|||
.setTs(ts) |
|||
.build(); |
|||
|
|||
FirmwareInfo firmware = firmwareService.findFirmwareInfoById(tenantId, firmwareId); |
|||
if (firmware == null) { |
|||
log.warn("[{}] Failed to send firmware update because firmware was already deleted", firmwareId); |
|||
return; |
|||
} |
|||
|
|||
TopicPartitionInfo tpi = new TopicPartitionInfo(fwStateMsgProducer.getDefaultTopic(), null, null, false); |
|||
fwStateMsgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null); |
|||
|
|||
List<TsKvEntry> telemetry = new ArrayList<>(); |
|||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_FIRMWARE_TITLE, firmware.getTitle()))); |
|||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_FIRMWARE_VERSION, firmware.getVersion()))); |
|||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_STATE, FirmwareUpdateStatus.QUEUED.name()))); |
|||
|
|||
telemetryService.saveAndNotify(tenantId, deviceId, telemetry, new FutureCallback<>() { |
|||
@Override |
|||
public void onSuccess(@Nullable Void tmp) { |
|||
log.trace("[{}] Success save firmware status!", deviceId); |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(Throwable t) { |
|||
log.error("[{}] Failed to save firmware status!", deviceId, t); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
|
|||
private void update(Device device, FirmwareInfo firmware, long ts) { |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
|
|||
BasicTsKvEntry status = new BasicTsKvEntry(System.currentTimeMillis(), new StringDataEntry(DataConstants.FIRMWARE_STATE, FirmwareUpdateStatus.INITIATED.name())); |
|||
|
|||
telemetryService.saveAndNotify(tenantId, deviceId, Collections.singletonList(status), new FutureCallback<>() { |
|||
@Override |
|||
public void onSuccess(@Nullable Void tmp) { |
|||
log.trace("[{}] Success save telemetry with target firmware for device!", deviceId); |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(Throwable t) { |
|||
log.error("[{}] Failed to save telemetry with target firmware for device!", deviceId, t); |
|||
} |
|||
}); |
|||
|
|||
List<AttributeKvEntry> attributes = new ArrayList<>(); |
|||
|
|||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_TITLE, firmware.getTitle()))); |
|||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_VERSION, firmware.getVersion()))); |
|||
|
|||
attributes.add(new BaseAttributeKvEntry(ts, new LongDataEntry(FIRMWARE_SIZE, firmware.getDataSize()))); |
|||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM_ALGORITHM, firmware.getChecksumAlgorithm()))); |
|||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM, firmware.getChecksum()))); |
|||
telemetryService.saveAndNotify(tenantId, deviceId, DataConstants.SHARED_SCOPE, attributes, new FutureCallback<>() { |
|||
@Override |
|||
public void onSuccess(@Nullable Void tmp) { |
|||
log.trace("[{}] Success save attributes with target firmware!", deviceId); |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(Throwable t) { |
|||
log.error("[{}] Failed to save attributes with target firmware!", deviceId, t); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private void remove(Device device) { |
|||
telemetryService.deleteAndNotify(device.getTenantId(), device.getId(), DataConstants.SHARED_SCOPE, |
|||
Arrays.asList(FIRMWARE_TITLE, FIRMWARE_VERSION, FIRMWARE_SIZE, FIRMWARE_CHECKSUM_ALGORITHM, FIRMWARE_CHECKSUM), |
|||
new FutureCallback<>() { |
|||
@Override |
|||
public void onSuccess(@Nullable Void tmp) { |
|||
log.trace("[{}] Success remove target firmware attributes!", device.getId()); |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(Throwable t) { |
|||
log.error("[{}] Failed to remove target firmware attributes!", device.getId(), t); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.service.firmware; |
|||
|
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.DeviceProfile; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg; |
|||
|
|||
public interface FirmwareStateService { |
|||
|
|||
void update(Device device, Device oldDevice); |
|||
|
|||
void update(DeviceProfile deviceProfile); |
|||
|
|||
boolean process(ToFirmwareStateServiceMsg msg); |
|||
|
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.service.firmware; |
|||
|
|||
public enum FirmwareUpdateStatus { |
|||
QUEUED, INITIATED, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED |
|||
} |
|||
@ -0,0 +1,302 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.controller; |
|||
|
|||
import com.fasterxml.jackson.core.type.TypeReference; |
|||
import org.junit.After; |
|||
import org.junit.Assert; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.springframework.mock.web.MockMultipartFile; |
|||
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; |
|||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; |
|||
import org.thingsboard.common.util.JacksonUtil; |
|||
import org.thingsboard.server.common.data.Firmware; |
|||
import org.thingsboard.server.common.data.FirmwareInfo; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.User; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageLink; |
|||
import org.thingsboard.server.common.data.security.Authority; |
|||
|
|||
import java.nio.ByteBuffer; |
|||
import java.util.ArrayList; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
|
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
public abstract class BaseFirmwareControllerTest extends AbstractControllerTest { |
|||
|
|||
private IdComparator<FirmwareInfo> idComparator = new IdComparator<>(); |
|||
|
|||
public static final String TITLE = "My firmware"; |
|||
private static final String FILE_NAME = "filename.txt"; |
|||
private static final String VERSION = "v1.0"; |
|||
private static final String CONTENT_TYPE = "text/plain"; |
|||
private static final String CHECKSUM_ALGORITHM = "sha256"; |
|||
private static final String CHECKSUM = "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a"; |
|||
private static final ByteBuffer DATA = ByteBuffer.wrap(new byte[]{1}); |
|||
|
|||
private Tenant savedTenant; |
|||
private User tenantAdmin; |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
loginSysAdmin(); |
|||
|
|||
Tenant tenant = new Tenant(); |
|||
tenant.setTitle("My tenant"); |
|||
savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
|||
Assert.assertNotNull(savedTenant); |
|||
|
|||
tenantAdmin = new User(); |
|||
tenantAdmin.setAuthority(Authority.TENANT_ADMIN); |
|||
tenantAdmin.setTenantId(savedTenant.getId()); |
|||
tenantAdmin.setEmail("tenant2@thingsboard.org"); |
|||
tenantAdmin.setFirstName("Joe"); |
|||
tenantAdmin.setLastName("Downs"); |
|||
|
|||
tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
loginSysAdmin(); |
|||
|
|||
doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) |
|||
.andExpect(status().isOk()); |
|||
} |
|||
|
|||
@Test |
|||
public void testSaveFirmware() throws Exception { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION); |
|||
|
|||
FirmwareInfo savedFirmwareInfo = save(firmwareInfo); |
|||
|
|||
Assert.assertNotNull(savedFirmwareInfo); |
|||
Assert.assertNotNull(savedFirmwareInfo.getId()); |
|||
Assert.assertTrue(savedFirmwareInfo.getCreatedTime() > 0); |
|||
Assert.assertEquals(savedTenant.getId(), savedFirmwareInfo.getTenantId()); |
|||
Assert.assertEquals(firmwareInfo.getTitle(), savedFirmwareInfo.getTitle()); |
|||
Assert.assertEquals(firmwareInfo.getVersion(), savedFirmwareInfo.getVersion()); |
|||
|
|||
savedFirmwareInfo.setAdditionalInfo(JacksonUtil.newObjectNode()); |
|||
|
|||
save(savedFirmwareInfo); |
|||
|
|||
FirmwareInfo foundFirmwareInfo = doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString(), FirmwareInfo.class); |
|||
Assert.assertEquals(foundFirmwareInfo.getTitle(), savedFirmwareInfo.getTitle()); |
|||
} |
|||
|
|||
@Test |
|||
public void testSaveFirmwareData() throws Exception { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION); |
|||
|
|||
FirmwareInfo savedFirmwareInfo = save(firmwareInfo); |
|||
|
|||
Assert.assertNotNull(savedFirmwareInfo); |
|||
Assert.assertNotNull(savedFirmwareInfo.getId()); |
|||
Assert.assertTrue(savedFirmwareInfo.getCreatedTime() > 0); |
|||
Assert.assertEquals(savedTenant.getId(), savedFirmwareInfo.getTenantId()); |
|||
Assert.assertEquals(firmwareInfo.getTitle(), savedFirmwareInfo.getTitle()); |
|||
Assert.assertEquals(firmwareInfo.getVersion(), savedFirmwareInfo.getVersion()); |
|||
|
|||
savedFirmwareInfo.setAdditionalInfo(JacksonUtil.newObjectNode()); |
|||
|
|||
save(savedFirmwareInfo); |
|||
|
|||
FirmwareInfo foundFirmwareInfo = doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString(), FirmwareInfo.class); |
|||
Assert.assertEquals(foundFirmwareInfo.getTitle(), savedFirmwareInfo.getTitle()); |
|||
|
|||
MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array()); |
|||
|
|||
Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM); |
|||
|
|||
Assert.assertEquals(FILE_NAME, savedFirmware.getFileName()); |
|||
Assert.assertEquals(CONTENT_TYPE, savedFirmware.getContentType()); |
|||
} |
|||
|
|||
@Test |
|||
public void testUpdateFirmwareFromDifferentTenant() throws Exception { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION); |
|||
|
|||
FirmwareInfo savedFirmwareInfo = save(firmwareInfo); |
|||
|
|||
loginDifferentTenant(); |
|||
doPost("/api/firmware", savedFirmwareInfo, FirmwareInfo.class, status().isForbidden()); |
|||
deleteDifferentTenant(); |
|||
} |
|||
|
|||
@Test |
|||
public void testFindFirmwareInfoById() throws Exception { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION); |
|||
|
|||
FirmwareInfo savedFirmwareInfo = save(firmwareInfo); |
|||
|
|||
FirmwareInfo foundFirmware = doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString(), FirmwareInfo.class); |
|||
Assert.assertNotNull(foundFirmware); |
|||
Assert.assertEquals(savedFirmwareInfo, foundFirmware); |
|||
} |
|||
|
|||
@Test |
|||
public void testFindFirmwareById() throws Exception { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION); |
|||
|
|||
FirmwareInfo savedFirmwareInfo = save(firmwareInfo); |
|||
|
|||
MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array()); |
|||
|
|||
Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM); |
|||
|
|||
Firmware foundFirmware = doGet("/api/firmware/" + savedFirmwareInfo.getId().getId().toString(), Firmware.class); |
|||
Assert.assertNotNull(foundFirmware); |
|||
Assert.assertEquals(savedFirmware, foundFirmware); |
|||
} |
|||
|
|||
@Test |
|||
public void testDeleteFirmware() throws Exception { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION); |
|||
|
|||
FirmwareInfo savedFirmwareInfo = save(firmwareInfo); |
|||
|
|||
doDelete("/api/firmware/" + savedFirmwareInfo.getId().getId().toString()) |
|||
.andExpect(status().isOk()); |
|||
|
|||
doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString()) |
|||
.andExpect(status().isNotFound()); |
|||
} |
|||
|
|||
@Test |
|||
public void testFindTenantFirmwares() throws Exception { |
|||
List<FirmwareInfo> firmwares = new ArrayList<>(); |
|||
for (int i = 0; i < 165; i++) { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION + i); |
|||
|
|||
FirmwareInfo savedFirmwareInfo = save(firmwareInfo); |
|||
|
|||
if (i > 100) { |
|||
MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array()); |
|||
|
|||
Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM); |
|||
firmwares.add(new FirmwareInfo(savedFirmware)); |
|||
} else { |
|||
firmwares.add(savedFirmwareInfo); |
|||
} |
|||
} |
|||
|
|||
List<FirmwareInfo> loadedFirmwares = new ArrayList<>(); |
|||
PageLink pageLink = new PageLink(24); |
|||
PageData<FirmwareInfo> pageData; |
|||
do { |
|||
pageData = doGetTypedWithPageLink("/api/firmwares?", |
|||
new TypeReference<>() { |
|||
}, pageLink); |
|||
loadedFirmwares.addAll(pageData.getData()); |
|||
if (pageData.hasNext()) { |
|||
pageLink = pageLink.nextPageLink(); |
|||
} |
|||
} while (pageData.hasNext()); |
|||
|
|||
Collections.sort(firmwares, idComparator); |
|||
Collections.sort(loadedFirmwares, idComparator); |
|||
|
|||
Assert.assertEquals(firmwares, loadedFirmwares); |
|||
} |
|||
|
|||
@Test |
|||
public void testFindTenantFirmwaresByHasData() throws Exception { |
|||
List<FirmwareInfo> firmwaresWithData = new ArrayList<>(); |
|||
List<FirmwareInfo> firmwaresWithoutData = new ArrayList<>(); |
|||
|
|||
for (int i = 0; i < 165; i++) { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION + i); |
|||
|
|||
FirmwareInfo savedFirmwareInfo = save(firmwareInfo); |
|||
|
|||
if (i > 100) { |
|||
MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array()); |
|||
|
|||
Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM); |
|||
firmwaresWithData.add(new FirmwareInfo(savedFirmware)); |
|||
} else { |
|||
firmwaresWithoutData.add(savedFirmwareInfo); |
|||
} |
|||
} |
|||
|
|||
List<FirmwareInfo> loadedFirmwaresWithData = new ArrayList<>(); |
|||
PageLink pageLink = new PageLink(24); |
|||
PageData<FirmwareInfo> pageData; |
|||
do { |
|||
pageData = doGetTypedWithPageLink("/api/firmwares/true?", |
|||
new TypeReference<>() { |
|||
}, pageLink); |
|||
loadedFirmwaresWithData.addAll(pageData.getData()); |
|||
if (pageData.hasNext()) { |
|||
pageLink = pageLink.nextPageLink(); |
|||
} |
|||
} while (pageData.hasNext()); |
|||
|
|||
List<FirmwareInfo> loadedFirmwaresWithoutData = new ArrayList<>(); |
|||
pageLink = new PageLink(24); |
|||
do { |
|||
pageData = doGetTypedWithPageLink("/api/firmwares/false?", |
|||
new TypeReference<>() { |
|||
}, pageLink); |
|||
loadedFirmwaresWithoutData.addAll(pageData.getData()); |
|||
if (pageData.hasNext()) { |
|||
pageLink = pageLink.nextPageLink(); |
|||
} |
|||
} while (pageData.hasNext()); |
|||
|
|||
Collections.sort(firmwaresWithData, idComparator); |
|||
Collections.sort(firmwaresWithoutData, idComparator); |
|||
Collections.sort(loadedFirmwaresWithData, idComparator); |
|||
Collections.sort(loadedFirmwaresWithoutData, idComparator); |
|||
|
|||
Assert.assertEquals(firmwaresWithData, loadedFirmwaresWithData); |
|||
Assert.assertEquals(firmwaresWithoutData, loadedFirmwaresWithoutData); |
|||
} |
|||
|
|||
|
|||
private FirmwareInfo save(FirmwareInfo firmwareInfo) throws Exception { |
|||
return doPost("/api/firmware", firmwareInfo, FirmwareInfo.class); |
|||
} |
|||
|
|||
protected Firmware savaData(String urlTemplate, MockMultipartFile content, String... params) throws Exception { |
|||
MockMultipartHttpServletRequestBuilder postRequest = MockMvcRequestBuilders.multipart(urlTemplate, params); |
|||
postRequest.file(content); |
|||
setJwtToken(postRequest); |
|||
return readResponse(mockMvc.perform(postRequest).andExpect(status().isOk()), Firmware.class); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.controller.sql; |
|||
|
|||
import org.thingsboard.server.controller.BaseFirmwareControllerTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class FirmwareControllerSqlTest extends BaseFirmwareControllerTest { |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.cache.firmware; |
|||
|
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
|
|||
import static org.thingsboard.server.common.data.CacheConstants.FIRMWARE_CACHE; |
|||
|
|||
public abstract class AbstractRedisFirmwareCache { |
|||
|
|||
protected final RedisConnectionFactory redisConnectionFactory; |
|||
|
|||
protected AbstractRedisFirmwareCache(RedisConnectionFactory redisConnectionFactory) { |
|||
this.redisConnectionFactory = redisConnectionFactory; |
|||
} |
|||
|
|||
protected byte[] toFirmwareCacheKey(String key) { |
|||
return String.format("%s::%s", FIRMWARE_CACHE, key).getBytes(); |
|||
} |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.cache.firmware; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import static org.thingsboard.server.common.data.CacheConstants.FIRMWARE_CACHE; |
|||
|
|||
@Service |
|||
@ConditionalOnExpression("(('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport') && ('${cache.type:null}'=='caffeine' || '${cache.type:null}'=='null')") |
|||
public class CaffeineFirmwareCacheReader implements FirmwareCacheReader { |
|||
|
|||
private final CacheManager cacheManager; |
|||
|
|||
public CaffeineFirmwareCacheReader(CacheManager cacheManager) { |
|||
this.cacheManager = cacheManager; |
|||
} |
|||
|
|||
@Override |
|||
public byte[] get(String key) { |
|||
return get(key, 0, 0); |
|||
} |
|||
|
|||
@Override |
|||
public byte[] get(String key, int chunkSize, int chunk) { |
|||
byte[] data = cacheManager.getCache(FIRMWARE_CACHE).get(key, byte[].class); |
|||
|
|||
if (chunkSize < 1) { |
|||
return data; |
|||
} |
|||
|
|||
if (data != null && data.length > 0) { |
|||
int startIndex = chunkSize * chunk; |
|||
|
|||
int size = Math.min(data.length - startIndex, chunkSize); |
|||
|
|||
if (startIndex < data.length && size > 0) { |
|||
byte[] result = new byte[size]; |
|||
System.arraycopy(data, startIndex, result, 0, size); |
|||
return result; |
|||
} |
|||
} |
|||
return new byte[0]; |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.cache.firmware; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import static org.thingsboard.server.common.data.CacheConstants.FIRMWARE_CACHE; |
|||
|
|||
@Service |
|||
@ConditionalOnExpression("('${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core') && ('${cache.type:null}'=='caffeine' || '${cache.type:null}'=='null')") |
|||
public class CaffeineFirmwareCacheWriter implements FirmwareCacheWriter { |
|||
|
|||
private final CacheManager cacheManager; |
|||
|
|||
public CaffeineFirmwareCacheWriter(CacheManager cacheManager) { |
|||
this.cacheManager = cacheManager; |
|||
} |
|||
|
|||
@Override |
|||
public void put(String key, byte[] value) { |
|||
cacheManager.getCache(FIRMWARE_CACHE).putIfAbsent(key, value); |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.cache.firmware; |
|||
|
|||
public interface FirmwareCacheReader { |
|||
byte[] get(String key); |
|||
|
|||
byte[] get(String key, int chunkSize, int chunk); |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.cache.firmware; |
|||
|
|||
public interface FirmwareCacheWriter { |
|||
void put(String key, byte[] value); |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.cache.firmware; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.data.redis.connection.RedisConnection; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
@Service |
|||
@ConditionalOnExpression("(('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport') && '${cache.type:null}'=='redis'") |
|||
public class RedisFirmwareCacheReader extends AbstractRedisFirmwareCache implements FirmwareCacheReader { |
|||
|
|||
public RedisFirmwareCacheReader(RedisConnectionFactory redisConnectionFactory) { |
|||
super(redisConnectionFactory); |
|||
} |
|||
|
|||
@Override |
|||
public byte[] get(String key) { |
|||
return get(key, 0, 0); |
|||
} |
|||
|
|||
@Override |
|||
public byte[] get(String key, int chunkSize, int chunk) { |
|||
try (RedisConnection connection = redisConnectionFactory.getConnection()) { |
|||
if (chunkSize == 0) { |
|||
return connection.get(toFirmwareCacheKey(key)); |
|||
} |
|||
|
|||
int startIndex = chunkSize * chunk; |
|||
int endIndex = startIndex + chunkSize - 1; |
|||
return connection.getRange(toFirmwareCacheKey(key), startIndex, endIndex); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.cache.firmware; |
|||
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|||
import org.springframework.data.redis.connection.RedisConnection; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
@Service |
|||
@ConditionalOnExpression("('${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core') && '${cache.type:null}'=='redis'") |
|||
public class RedisFirmwareCacheWriter extends AbstractRedisFirmwareCache implements FirmwareCacheWriter { |
|||
|
|||
public RedisFirmwareCacheWriter(RedisConnectionFactory redisConnectionFactory) { |
|||
super(redisConnectionFactory); |
|||
} |
|||
|
|||
@Override |
|||
public void put(String key, byte[] value) { |
|||
try (RedisConnection connection = redisConnectionFactory.getConnection()) { |
|||
connection.set(toFirmwareCacheKey(key), value); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.firmware; |
|||
|
|||
import org.thingsboard.server.common.data.Firmware; |
|||
import org.thingsboard.server.common.data.FirmwareInfo; |
|||
import org.thingsboard.server.common.data.id.FirmwareId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageLink; |
|||
|
|||
public interface FirmwareService { |
|||
|
|||
FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo); |
|||
|
|||
Firmware saveFirmware(Firmware firmware); |
|||
|
|||
Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId); |
|||
|
|||
FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId); |
|||
|
|||
PageData<FirmwareInfo> findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink); |
|||
|
|||
PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink); |
|||
|
|||
void deleteFirmware(TenantId tenantId, FirmwareId firmwareId); |
|||
|
|||
void deleteFirmwaresByTenantId(TenantId tenantId); |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.common.data; |
|||
|
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
import org.thingsboard.server.common.data.id.FirmwareId; |
|||
|
|||
import java.nio.ByteBuffer; |
|||
|
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
public class Firmware extends FirmwareInfo { |
|||
|
|||
private static final long serialVersionUID = 3091601761339422546L; |
|||
|
|||
private transient ByteBuffer data; |
|||
|
|||
public Firmware() { |
|||
super(); |
|||
} |
|||
|
|||
public Firmware(FirmwareId id) { |
|||
super(id); |
|||
} |
|||
|
|||
public Firmware(Firmware firmware) { |
|||
super(firmware); |
|||
this.data = firmware.getData(); |
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.common.data; |
|||
|
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.common.data.id.FirmwareId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
@Slf4j |
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId> implements HasTenantId { |
|||
|
|||
private static final long serialVersionUID = 3168391583570815419L; |
|||
|
|||
private TenantId tenantId; |
|||
private String title; |
|||
private String version; |
|||
private boolean hasData; |
|||
private String fileName; |
|||
private String contentType; |
|||
private String checksumAlgorithm; |
|||
private String checksum; |
|||
private Long dataSize; |
|||
|
|||
|
|||
public FirmwareInfo() { |
|||
super(); |
|||
} |
|||
|
|||
public FirmwareInfo(FirmwareId id) { |
|||
super(id); |
|||
} |
|||
|
|||
public FirmwareInfo(FirmwareInfo firmwareInfo) { |
|||
super(firmwareInfo); |
|||
this.tenantId = firmwareInfo.getTenantId(); |
|||
this.title = firmwareInfo.getTitle(); |
|||
this.version = firmwareInfo.getVersion(); |
|||
this.hasData = firmwareInfo.isHasData(); |
|||
this.fileName = firmwareInfo.getFileName(); |
|||
this.contentType = firmwareInfo.getContentType(); |
|||
this.checksumAlgorithm = firmwareInfo.getChecksumAlgorithm(); |
|||
this.checksum = firmwareInfo.getChecksum(); |
|||
this.dataSize = firmwareInfo.getDataSize(); |
|||
} |
|||
|
|||
@Override |
|||
public String getSearchText() { |
|||
return title; |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.common.data.id; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonCreator; |
|||
import com.fasterxml.jackson.annotation.JsonIgnore; |
|||
import com.fasterxml.jackson.annotation.JsonProperty; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
public class FirmwareId extends UUIDBased implements EntityId { |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
@JsonCreator |
|||
public FirmwareId(@JsonProperty("id") UUID id) { |
|||
super(id); |
|||
} |
|||
|
|||
public static FirmwareId fromString(String firmwareId) { |
|||
return new FirmwareId(UUID.fromString(firmwareId)); |
|||
} |
|||
|
|||
@JsonIgnore |
|||
@Override |
|||
public EntityType getEntityType() { |
|||
return EntityType.FIRMWARE; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,319 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.firmware; |
|||
|
|||
import com.google.common.hash.HashFunction; |
|||
import com.google.common.hash.Hashing; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.hibernate.exception.ConstraintViolationException; |
|||
import org.springframework.cache.Cache; |
|||
import org.springframework.cache.CacheManager; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Firmware; |
|||
import org.thingsboard.server.common.data.FirmwareInfo; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.id.FirmwareId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageLink; |
|||
import org.thingsboard.server.dao.exception.DataValidationException; |
|||
import org.thingsboard.server.dao.service.DataValidator; |
|||
import org.thingsboard.server.dao.service.PaginatedRemover; |
|||
import org.thingsboard.server.dao.tenant.TenantDao; |
|||
|
|||
import java.nio.ByteBuffer; |
|||
import java.util.Collections; |
|||
import java.util.Optional; |
|||
|
|||
import static org.thingsboard.server.common.data.CacheConstants.FIRMWARE_CACHE; |
|||
import static org.thingsboard.server.dao.service.Validator.validateId; |
|||
import static org.thingsboard.server.dao.service.Validator.validatePageLink; |
|||
|
|||
@Service |
|||
@Slf4j |
|||
public class BaseFirmwareService implements FirmwareService { |
|||
public static final String INCORRECT_FIRMWARE_ID = "Incorrect firmwareId "; |
|||
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; |
|||
|
|||
private final TenantDao tenantDao; |
|||
private final FirmwareDao firmwareDao; |
|||
private final FirmwareInfoDao firmwareInfoDao; |
|||
private final CacheManager cacheManager; |
|||
|
|||
public BaseFirmwareService(TenantDao tenantDao, FirmwareDao firmwareDao, FirmwareInfoDao firmwareInfoDao, CacheManager cacheManager) { |
|||
this.tenantDao = tenantDao; |
|||
this.firmwareDao = firmwareDao; |
|||
this.firmwareInfoDao = firmwareInfoDao; |
|||
this.cacheManager = cacheManager; |
|||
} |
|||
|
|||
@Override |
|||
public FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo) { |
|||
log.trace("Executing saveFirmwareInfo [{}]", firmwareInfo); |
|||
firmwareInfoValidator.validate(firmwareInfo, FirmwareInfo::getTenantId); |
|||
try { |
|||
FirmwareId firmwareId = firmwareInfo.getId(); |
|||
if (firmwareId != null) { |
|||
cacheManager.getCache(FIRMWARE_CACHE).evict(firmwareId.toString()); |
|||
} |
|||
return firmwareInfoDao.save(firmwareInfo.getTenantId(), firmwareInfo); |
|||
} catch (Exception t) { |
|||
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); |
|||
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("firmware_tenant_title_version_unq_key")) { |
|||
throw new DataValidationException("Firmware with such title and version already exists!"); |
|||
} else { |
|||
throw t; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Firmware saveFirmware(Firmware firmware) { |
|||
log.trace("Executing saveFirmware [{}]", firmware); |
|||
firmwareValidator.validate(firmware, FirmwareInfo::getTenantId); |
|||
try { |
|||
FirmwareId firmwareId = firmware.getId(); |
|||
if (firmwareId != null) { |
|||
cacheManager.getCache(FIRMWARE_CACHE).evict(firmwareId.toString()); |
|||
} |
|||
return firmwareDao.save(firmware.getTenantId(), firmware); |
|||
} catch (Exception t) { |
|||
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); |
|||
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("firmware_tenant_title_version_unq_key")) { |
|||
throw new DataValidationException("Firmware with such title and version already exists!"); |
|||
} else { |
|||
throw t; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId) { |
|||
log.trace("Executing findFirmwareById [{}]", firmwareId); |
|||
validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); |
|||
return firmwareDao.findById(tenantId, firmwareId.getId()); |
|||
} |
|||
|
|||
@Override |
|||
public FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId) { |
|||
log.trace("Executing findFirmwareInfoById [{}]", firmwareId); |
|||
validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); |
|||
return firmwareInfoDao.findById(tenantId, firmwareId.getId()); |
|||
} |
|||
|
|||
@Override |
|||
public PageData<FirmwareInfo> findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink) { |
|||
log.trace("Executing findTenantFirmwaresByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); |
|||
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
|||
validatePageLink(pageLink); |
|||
return firmwareInfoDao.findFirmwareInfoByTenantId(tenantId, pageLink); |
|||
} |
|||
|
|||
@Override |
|||
public PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink) { |
|||
log.trace("Executing findTenantFirmwaresByTenantIdAndHasData, tenantId [{}], hasData [{}] pageLink [{}]", tenantId, hasData, pageLink); |
|||
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
|||
validatePageLink(pageLink); |
|||
return firmwareInfoDao.findFirmwareInfoByTenantIdAndHasData(tenantId, hasData, pageLink); |
|||
} |
|||
|
|||
@Override |
|||
public void deleteFirmware(TenantId tenantId, FirmwareId firmwareId) { |
|||
log.trace("Executing deleteFirmware [{}]", firmwareId); |
|||
validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); |
|||
try { |
|||
Cache cache = cacheManager.getCache(FIRMWARE_CACHE); |
|||
cache.evict(Collections.singletonList(firmwareId)); |
|||
firmwareDao.removeById(tenantId, firmwareId.getId()); |
|||
} catch (Exception t) { |
|||
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); |
|||
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device")) { |
|||
throw new DataValidationException("The firmware referenced by the devices cannot be deleted!"); |
|||
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device_profile")) { |
|||
throw new DataValidationException("The firmware referenced by the device profile cannot be deleted!"); |
|||
} else { |
|||
throw t; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void deleteFirmwaresByTenantId(TenantId tenantId) { |
|||
log.trace("Executing deleteFirmwaresByTenantId, tenantId [{}]", tenantId); |
|||
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
|||
tenantFirmwareRemover.removeEntities(tenantId, tenantId); |
|||
} |
|||
|
|||
private DataValidator<FirmwareInfo> firmwareInfoValidator = new DataValidator<>() { |
|||
|
|||
@Override |
|||
protected void validateDataImpl(TenantId tenantId, FirmwareInfo firmware) { |
|||
if (firmware.getTenantId() == null) { |
|||
throw new DataValidationException("Firmware should be assigned to tenant!"); |
|||
} else { |
|||
Tenant tenant = tenantDao.findById(firmware.getTenantId(), firmware.getTenantId().getId()); |
|||
if (tenant == null) { |
|||
throw new DataValidationException("Firmware is referencing to non-existent tenant!"); |
|||
} |
|||
} |
|||
|
|||
if (StringUtils.isEmpty(firmware.getTitle())) { |
|||
throw new DataValidationException("Firmware title should be specified!"); |
|||
} |
|||
|
|||
if (StringUtils.isEmpty(firmware.getVersion())) { |
|||
throw new DataValidationException("Firmware version should be specified!"); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
protected void validateUpdate(TenantId tenantId, FirmwareInfo firmware) { |
|||
FirmwareInfo firmwareOld = firmwareInfoDao.findById(tenantId, firmware.getUuidId()); |
|||
|
|||
BaseFirmwareService.validateUpdate(firmware, firmwareOld); |
|||
} |
|||
}; |
|||
|
|||
private DataValidator<Firmware> firmwareValidator = new DataValidator<>() { |
|||
|
|||
@Override |
|||
protected void validateDataImpl(TenantId tenantId, Firmware firmware) { |
|||
if (firmware.getTenantId() == null) { |
|||
throw new DataValidationException("Firmware should be assigned to tenant!"); |
|||
} else { |
|||
Tenant tenant = tenantDao.findById(firmware.getTenantId(), firmware.getTenantId().getId()); |
|||
if (tenant == null) { |
|||
throw new DataValidationException("Firmware is referencing to non-existent tenant!"); |
|||
} |
|||
} |
|||
|
|||
if (StringUtils.isEmpty(firmware.getTitle())) { |
|||
throw new DataValidationException("Firmware title should be specified!"); |
|||
} |
|||
|
|||
if (StringUtils.isEmpty(firmware.getVersion())) { |
|||
throw new DataValidationException("Firmware version should be specified!"); |
|||
} |
|||
|
|||
if (StringUtils.isEmpty(firmware.getFileName())) { |
|||
throw new DataValidationException("Firmware file name should be specified!"); |
|||
} |
|||
|
|||
if (StringUtils.isEmpty(firmware.getContentType())) { |
|||
throw new DataValidationException("Firmware content type should be specified!"); |
|||
} |
|||
|
|||
ByteBuffer data = firmware.getData(); |
|||
if (data == null || !data.hasArray() || data.array().length == 0) { |
|||
throw new DataValidationException("Firmware data should be specified!"); |
|||
} |
|||
|
|||
if (StringUtils.isEmpty(firmware.getChecksumAlgorithm())) { |
|||
throw new DataValidationException("Firmware checksum algorithm should be specified!"); |
|||
} |
|||
if (StringUtils.isEmpty(firmware.getChecksum())) { |
|||
throw new DataValidationException("Firmware checksum should be specified!"); |
|||
} |
|||
|
|||
HashFunction hashFunction; |
|||
switch (firmware.getChecksumAlgorithm()) { |
|||
case "sha256": |
|||
hashFunction = Hashing.sha256(); |
|||
break; |
|||
case "md5": |
|||
hashFunction = Hashing.md5(); |
|||
break; |
|||
case "crc32": |
|||
hashFunction = Hashing.crc32(); |
|||
break; |
|||
default: |
|||
throw new DataValidationException("Unknown checksum algorithm!"); |
|||
} |
|||
|
|||
String currentChecksum = hashFunction.hashBytes(data.array()).toString(); |
|||
|
|||
if (!currentChecksum.equals(firmware.getChecksum())) { |
|||
throw new DataValidationException("Wrong firmware file!"); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
protected void validateUpdate(TenantId tenantId, Firmware firmware) { |
|||
Firmware firmwareOld = firmwareDao.findById(tenantId, firmware.getUuidId()); |
|||
|
|||
BaseFirmwareService.validateUpdate(firmware, firmwareOld); |
|||
|
|||
if (firmwareOld.getData() != null && !firmwareOld.getData().equals(firmware.getData())) { |
|||
throw new DataValidationException("Updating firmware data is prohibited!"); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
private static void validateUpdate(FirmwareInfo firmware, FirmwareInfo firmwareOld) { |
|||
if (!firmwareOld.getTitle().equals(firmware.getTitle())) { |
|||
throw new DataValidationException("Updating firmware title is prohibited!"); |
|||
} |
|||
|
|||
if (!firmwareOld.getVersion().equals(firmware.getVersion())) { |
|||
throw new DataValidationException("Updating firmware version is prohibited!"); |
|||
} |
|||
|
|||
if (firmwareOld.getFileName() != null && !firmwareOld.getFileName().equals(firmware.getFileName())) { |
|||
throw new DataValidationException("Updating firmware file name is prohibited!"); |
|||
} |
|||
|
|||
if (firmwareOld.getContentType() != null && !firmwareOld.getContentType().equals(firmware.getContentType())) { |
|||
throw new DataValidationException("Updating firmware content type is prohibited!"); |
|||
} |
|||
|
|||
if (firmwareOld.getChecksumAlgorithm() != null && !firmwareOld.getChecksumAlgorithm().equals(firmware.getChecksumAlgorithm())) { |
|||
throw new DataValidationException("Updating firmware content type is prohibited!"); |
|||
} |
|||
|
|||
if (firmwareOld.getChecksum() != null && !firmwareOld.getChecksum().equals(firmware.getChecksum())) { |
|||
throw new DataValidationException("Updating firmware content type is prohibited!"); |
|||
} |
|||
|
|||
if (firmwareOld.getDataSize() != null && !firmwareOld.getDataSize().equals(firmware.getDataSize())) { |
|||
throw new DataValidationException("Updating firmware data size is prohibited!"); |
|||
} |
|||
} |
|||
|
|||
private PaginatedRemover<TenantId, FirmwareInfo> tenantFirmwareRemover = |
|||
new PaginatedRemover<>() { |
|||
|
|||
@Override |
|||
protected PageData<FirmwareInfo> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) { |
|||
return firmwareInfoDao.findFirmwareInfoByTenantId(id, pageLink); |
|||
} |
|||
|
|||
@Override |
|||
protected void removeEntity(TenantId tenantId, FirmwareInfo entity) { |
|||
deleteFirmware(tenantId, entity.getId()); |
|||
} |
|||
}; |
|||
|
|||
protected Optional<ConstraintViolationException> extractConstraintViolationException(Exception t) { |
|||
if (t instanceof ConstraintViolationException) { |
|||
return Optional.of((ConstraintViolationException) t); |
|||
} else if (t.getCause() instanceof ConstraintViolationException) { |
|||
return Optional.of((ConstraintViolationException) (t.getCause())); |
|||
} else { |
|||
return Optional.empty(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.firmware; |
|||
|
|||
import org.thingsboard.server.common.data.Firmware; |
|||
import org.thingsboard.server.dao.Dao; |
|||
|
|||
public interface FirmwareDao extends Dao<Firmware> { |
|||
|
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.firmware; |
|||
|
|||
import org.thingsboard.server.common.data.FirmwareInfo; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageLink; |
|||
import org.thingsboard.server.dao.Dao; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
public interface FirmwareInfoDao extends Dao<FirmwareInfo> { |
|||
|
|||
PageData<FirmwareInfo> findFirmwareInfoByTenantId(TenantId tenantId, PageLink pageLink); |
|||
|
|||
PageData<FirmwareInfo> findFirmwareInfoByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink); |
|||
|
|||
} |
|||
@ -0,0 +1,138 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.model.sql; |
|||
|
|||
import com.fasterxml.jackson.databind.JsonNode; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
import org.hibernate.annotations.Type; |
|||
import org.hibernate.annotations.TypeDef; |
|||
import org.thingsboard.server.common.data.Firmware; |
|||
import org.thingsboard.server.common.data.id.FirmwareId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.dao.model.BaseSqlEntity; |
|||
import org.thingsboard.server.dao.model.ModelConstants; |
|||
import org.thingsboard.server.dao.model.SearchTextEntity; |
|||
import org.thingsboard.server.dao.util.mapping.JsonStringType; |
|||
|
|||
import javax.persistence.Column; |
|||
import javax.persistence.Entity; |
|||
import javax.persistence.Table; |
|||
import java.nio.ByteBuffer; |
|||
import java.util.UUID; |
|||
|
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_ALGORITHM_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CONTENT_TYPE_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_SIZE_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_VERSION_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY; |
|||
|
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@Entity |
|||
@TypeDef(name = "json", typeClass = JsonStringType.class) |
|||
@Table(name = FIRMWARE_TABLE_NAME) |
|||
public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTextEntity<Firmware> { |
|||
|
|||
@Column(name = FIRMWARE_TENANT_ID_COLUMN) |
|||
private UUID tenantId; |
|||
|
|||
@Column(name = FIRMWARE_TITLE_COLUMN) |
|||
private String title; |
|||
|
|||
@Column(name = FIRMWARE_VERSION_COLUMN) |
|||
private String version; |
|||
|
|||
@Column(name = FIRMWARE_FILE_NAME_COLUMN) |
|||
private String fileName; |
|||
|
|||
@Column(name = FIRMWARE_CONTENT_TYPE_COLUMN) |
|||
private String contentType; |
|||
|
|||
@Column(name = FIRMWARE_CHECKSUM_ALGORITHM_COLUMN) |
|||
private String checksumAlgorithm; |
|||
|
|||
@Column(name = FIRMWARE_CHECKSUM_COLUMN) |
|||
private String checksum; |
|||
|
|||
@Column(name = FIRMWARE_DATA_COLUMN, columnDefinition = "BINARY") |
|||
private byte[] data; |
|||
|
|||
@Column(name = FIRMWARE_DATA_SIZE_COLUMN) |
|||
private Long dataSize; |
|||
|
|||
@Type(type = "json") |
|||
@Column(name = ModelConstants.FIRMWARE_ADDITIONAL_INFO_COLUMN) |
|||
private JsonNode additionalInfo; |
|||
|
|||
@Column(name = SEARCH_TEXT_PROPERTY) |
|||
private String searchText; |
|||
|
|||
public FirmwareEntity() { |
|||
super(); |
|||
} |
|||
|
|||
public FirmwareEntity(Firmware firmware) { |
|||
this.createdTime = firmware.getCreatedTime(); |
|||
this.setUuid(firmware.getUuidId()); |
|||
this.tenantId = firmware.getTenantId().getId(); |
|||
this.title = firmware.getTitle(); |
|||
this.version = firmware.getVersion(); |
|||
this.fileName = firmware.getFileName(); |
|||
this.contentType = firmware.getContentType(); |
|||
this.checksumAlgorithm = firmware.getChecksumAlgorithm(); |
|||
this.checksum = firmware.getChecksum(); |
|||
this.data = firmware.getData().array(); |
|||
this.dataSize = firmware.getDataSize(); |
|||
this.additionalInfo = firmware.getAdditionalInfo(); |
|||
} |
|||
|
|||
@Override |
|||
public String getSearchTextSource() { |
|||
return title; |
|||
} |
|||
|
|||
@Override |
|||
public void setSearchText(String searchText) { |
|||
this.searchText = searchText; |
|||
} |
|||
|
|||
@Override |
|||
public Firmware toData() { |
|||
Firmware firmware = new Firmware(new FirmwareId(id)); |
|||
firmware.setCreatedTime(createdTime); |
|||
firmware.setTenantId(new TenantId(tenantId)); |
|||
firmware.setTitle(title); |
|||
firmware.setVersion(version); |
|||
firmware.setFileName(fileName); |
|||
firmware.setContentType(contentType); |
|||
firmware.setChecksumAlgorithm(checksumAlgorithm); |
|||
firmware.setChecksum(checksum); |
|||
firmware.setDataSize(dataSize); |
|||
if (data != null) { |
|||
firmware.setData(ByteBuffer.wrap(data)); |
|||
firmware.setHasData(true); |
|||
} |
|||
firmware.setAdditionalInfo(additionalInfo); |
|||
return firmware; |
|||
} |
|||
} |
|||
@ -0,0 +1,153 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.model.sql; |
|||
|
|||
import com.fasterxml.jackson.databind.JsonNode; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
import org.hibernate.annotations.Type; |
|||
import org.hibernate.annotations.TypeDef; |
|||
import org.thingsboard.common.util.JacksonUtil; |
|||
import org.thingsboard.server.common.data.FirmwareInfo; |
|||
import org.thingsboard.server.common.data.id.FirmwareId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.dao.model.BaseSqlEntity; |
|||
import org.thingsboard.server.dao.model.ModelConstants; |
|||
import org.thingsboard.server.dao.model.SearchTextEntity; |
|||
import org.thingsboard.server.dao.util.mapping.JsonStringType; |
|||
|
|||
import javax.persistence.Column; |
|||
import javax.persistence.Entity; |
|||
import javax.persistence.Table; |
|||
import javax.persistence.Transient; |
|||
import java.util.UUID; |
|||
|
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_ALGORITHM_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CONTENT_TYPE_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_SIZE_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_HAS_DATA_PROPERTY; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_VERSION_COLUMN; |
|||
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY; |
|||
|
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@Entity |
|||
@TypeDef(name = "json", typeClass = JsonStringType.class) |
|||
@Table(name = FIRMWARE_TABLE_NAME) |
|||
public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements SearchTextEntity<FirmwareInfo> { |
|||
|
|||
@Column(name = FIRMWARE_TENANT_ID_COLUMN) |
|||
private UUID tenantId; |
|||
|
|||
@Column(name = FIRMWARE_TITLE_COLUMN) |
|||
private String title; |
|||
|
|||
@Column(name = FIRMWARE_VERSION_COLUMN) |
|||
private String version; |
|||
|
|||
@Column(name = FIRMWARE_FILE_NAME_COLUMN) |
|||
private String fileName; |
|||
|
|||
@Column(name = FIRMWARE_CONTENT_TYPE_COLUMN) |
|||
private String contentType; |
|||
|
|||
@Column(name = FIRMWARE_CHECKSUM_ALGORITHM_COLUMN) |
|||
private String checksumAlgorithm; |
|||
|
|||
@Column(name = FIRMWARE_CHECKSUM_COLUMN) |
|||
private String checksum; |
|||
|
|||
@Column(name = FIRMWARE_DATA_SIZE_COLUMN) |
|||
private Long dataSize; |
|||
|
|||
@Type(type = "json") |
|||
@Column(name = ModelConstants.FIRMWARE_ADDITIONAL_INFO_COLUMN) |
|||
private JsonNode additionalInfo; |
|||
|
|||
@Column(name = SEARCH_TEXT_PROPERTY) |
|||
private String searchText; |
|||
|
|||
@Transient |
|||
private boolean hasData; |
|||
|
|||
public FirmwareInfoEntity() { |
|||
super(); |
|||
} |
|||
|
|||
public FirmwareInfoEntity(FirmwareInfo firmware) { |
|||
this.createdTime = firmware.getCreatedTime(); |
|||
this.setUuid(firmware.getUuidId()); |
|||
this.tenantId = firmware.getTenantId().getId(); |
|||
this.title = firmware.getTitle(); |
|||
this.version = firmware.getVersion(); |
|||
this.fileName = firmware.getFileName(); |
|||
this.contentType = firmware.getContentType(); |
|||
this.checksumAlgorithm = firmware.getChecksumAlgorithm(); |
|||
this.checksum = firmware.getChecksum(); |
|||
this.dataSize = firmware.getDataSize(); |
|||
this.additionalInfo = firmware.getAdditionalInfo(); |
|||
} |
|||
|
|||
public FirmwareInfoEntity(UUID id, long createdTime, UUID tenantId, String title, String version, |
|||
String fileName, String contentType, String checksumAlgorithm, String checksum, Long dataSize, |
|||
Object additionalInfo, boolean hasData) { |
|||
this.id = id; |
|||
this.createdTime = createdTime; |
|||
this.tenantId = tenantId; |
|||
this.title = title; |
|||
this.version = version; |
|||
this.fileName = fileName; |
|||
this.contentType = contentType; |
|||
this.checksumAlgorithm = checksumAlgorithm; |
|||
this.checksum = checksum; |
|||
this.dataSize = dataSize; |
|||
this.hasData = hasData; |
|||
this.additionalInfo = JacksonUtil.convertValue(additionalInfo, JsonNode.class); |
|||
} |
|||
|
|||
@Override |
|||
public String getSearchTextSource() { |
|||
return title; |
|||
} |
|||
|
|||
@Override |
|||
public void setSearchText(String searchText) { |
|||
this.searchText = searchText; |
|||
} |
|||
|
|||
@Override |
|||
public FirmwareInfo toData() { |
|||
FirmwareInfo firmware = new FirmwareInfo(new FirmwareId(id)); |
|||
firmware.setCreatedTime(createdTime); |
|||
firmware.setTenantId(new TenantId(tenantId)); |
|||
firmware.setTitle(title); |
|||
firmware.setVersion(version); |
|||
firmware.setFileName(fileName); |
|||
firmware.setContentType(contentType); |
|||
firmware.setChecksumAlgorithm(checksumAlgorithm); |
|||
firmware.setChecksum(checksum); |
|||
firmware.setDataSize(dataSize); |
|||
firmware.setAdditionalInfo(additionalInfo); |
|||
firmware.setHasData(hasData); |
|||
return firmware; |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.sql.firmware; |
|||
|
|||
import org.springframework.data.domain.Page; |
|||
import org.springframework.data.domain.Pageable; |
|||
import org.springframework.data.jpa.repository.Query; |
|||
import org.springframework.data.repository.CrudRepository; |
|||
import org.springframework.data.repository.query.Param; |
|||
import org.thingsboard.server.dao.model.sql.FirmwareInfoEntity; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
public interface FirmwareInfoRepository extends CrudRepository<FirmwareInfoEntity, UUID> { |
|||
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " + |
|||
"f.tenantId = :tenantId " + |
|||
"AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") |
|||
Page<FirmwareInfoEntity> findAllByTenantId(@Param("tenantId") UUID tenantId, |
|||
@Param("searchText") String searchText, |
|||
Pageable pageable); |
|||
|
|||
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " + |
|||
"f.tenantId = :tenantId " + |
|||
"AND ((f.data IS NOT NULL AND :hasData = true) OR (f.data IS NULL AND :hasData = false ))" + |
|||
"AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") |
|||
Page<FirmwareInfoEntity> findAllByTenantIdAndHasData(@Param("tenantId") UUID tenantId, |
|||
@Param("hasData") boolean hasData, |
|||
@Param("searchText") String searchText, |
|||
Pageable pageable); |
|||
|
|||
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE f.id = :id") |
|||
FirmwareInfoEntity findFirmwareInfoById(@Param("id") UUID id); |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.sql.firmware; |
|||
|
|||
import org.springframework.data.repository.CrudRepository; |
|||
import org.thingsboard.server.dao.model.sql.FirmwareEntity; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
public interface FirmwareRepository extends CrudRepository<FirmwareEntity, UUID> { |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.sql.firmware; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.data.repository.CrudRepository; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.Firmware; |
|||
import org.thingsboard.server.dao.firmware.FirmwareDao; |
|||
import org.thingsboard.server.dao.model.sql.FirmwareEntity; |
|||
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
@Slf4j |
|||
@Component |
|||
public class JpaFirmwareDao extends JpaAbstractSearchTextDao<FirmwareEntity, Firmware> implements FirmwareDao { |
|||
|
|||
@Autowired |
|||
private FirmwareRepository firmwareRepository; |
|||
|
|||
@Override |
|||
protected Class<FirmwareEntity> getEntityClass() { |
|||
return FirmwareEntity.class; |
|||
} |
|||
|
|||
@Override |
|||
protected CrudRepository<FirmwareEntity, UUID> getCrudRepository() { |
|||
return firmwareRepository; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.sql.firmware; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.data.repository.CrudRepository; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.common.data.FirmwareInfo; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageLink; |
|||
import org.thingsboard.server.dao.DaoUtil; |
|||
import org.thingsboard.server.dao.firmware.FirmwareInfoDao; |
|||
import org.thingsboard.server.dao.model.sql.FirmwareInfoEntity; |
|||
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; |
|||
|
|||
import java.util.Objects; |
|||
import java.util.UUID; |
|||
|
|||
@Slf4j |
|||
@Component |
|||
public class JpaFirmwareInfoDao extends JpaAbstractSearchTextDao<FirmwareInfoEntity, FirmwareInfo> implements FirmwareInfoDao { |
|||
|
|||
@Autowired |
|||
private FirmwareInfoRepository firmwareInfoRepository; |
|||
|
|||
@Override |
|||
protected Class<FirmwareInfoEntity> getEntityClass() { |
|||
return FirmwareInfoEntity.class; |
|||
} |
|||
|
|||
@Override |
|||
protected CrudRepository<FirmwareInfoEntity, UUID> getCrudRepository() { |
|||
return firmwareInfoRepository; |
|||
} |
|||
|
|||
@Override |
|||
public FirmwareInfo findById(TenantId tenantId, UUID id) { |
|||
return DaoUtil.getData(firmwareInfoRepository.findFirmwareInfoById(id)); |
|||
} |
|||
|
|||
@Override |
|||
public FirmwareInfo save(TenantId tenantId, FirmwareInfo firmwareInfo) { |
|||
FirmwareInfo savedFirmware = super.save(tenantId, firmwareInfo); |
|||
if (firmwareInfo.getId() == null) { |
|||
return savedFirmware; |
|||
} else { |
|||
return findById(tenantId, savedFirmware.getId().getId()); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public PageData<FirmwareInfo> findFirmwareInfoByTenantId(TenantId tenantId, PageLink pageLink) { |
|||
return DaoUtil.toPageData(firmwareInfoRepository |
|||
.findAllByTenantId( |
|||
tenantId.getId(), |
|||
Objects.toString(pageLink.getTextSearch(), ""), |
|||
DaoUtil.toPageable(pageLink))); |
|||
} |
|||
|
|||
@Override |
|||
public PageData<FirmwareInfo> findFirmwareInfoByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink) { |
|||
return DaoUtil.toPageData(firmwareInfoRepository |
|||
.findAllByTenantIdAndHasData( |
|||
tenantId.getId(), |
|||
hasData, |
|||
Objects.toString(pageLink.getTextSearch(), ""), |
|||
DaoUtil.toPageable(pageLink))); |
|||
} |
|||
} |
|||
@ -0,0 +1,488 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.service; |
|||
|
|||
import com.datastax.oss.driver.api.core.uuid.Uuids; |
|||
import org.junit.After; |
|||
import org.junit.Assert; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.common.util.JacksonUtil; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.DeviceProfile; |
|||
import org.thingsboard.server.common.data.Firmware; |
|||
import org.thingsboard.server.common.data.FirmwareInfo; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageLink; |
|||
import org.thingsboard.server.dao.exception.DataValidationException; |
|||
|
|||
import java.nio.ByteBuffer; |
|||
import java.util.ArrayList; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
|
|||
public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { |
|||
|
|||
public static final String TITLE = "My firmware"; |
|||
private static final String FILE_NAME = "filename.txt"; |
|||
private static final String VERSION = "v1.0"; |
|||
private static final String CONTENT_TYPE = "text/plain"; |
|||
private static final String CHECKSUM_ALGORITHM = "sha256"; |
|||
private static final String CHECKSUM = "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a"; |
|||
private static final ByteBuffer DATA = ByteBuffer.wrap(new byte[]{1}); |
|||
|
|||
private IdComparator<FirmwareInfo> idComparator = new IdComparator<>(); |
|||
|
|||
private TenantId tenantId; |
|||
|
|||
@Before |
|||
public void before() { |
|||
Tenant tenant = new Tenant(); |
|||
tenant.setTitle("My tenant"); |
|||
Tenant savedTenant = tenantService.saveTenant(tenant); |
|||
Assert.assertNotNull(savedTenant); |
|||
tenantId = savedTenant.getId(); |
|||
} |
|||
|
|||
@After |
|||
public void after() { |
|||
tenantService.deleteTenant(tenantId); |
|||
} |
|||
|
|||
@Test |
|||
public void testSaveFirmware() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
Firmware savedFirmware = firmwareService.saveFirmware(firmware); |
|||
|
|||
Assert.assertNotNull(savedFirmware); |
|||
Assert.assertNotNull(savedFirmware.getId()); |
|||
Assert.assertTrue(savedFirmware.getCreatedTime() > 0); |
|||
Assert.assertEquals(firmware.getTenantId(), savedFirmware.getTenantId()); |
|||
Assert.assertEquals(firmware.getTitle(), savedFirmware.getTitle()); |
|||
Assert.assertEquals(firmware.getFileName(), savedFirmware.getFileName()); |
|||
Assert.assertEquals(firmware.getContentType(), savedFirmware.getContentType()); |
|||
Assert.assertEquals(firmware.getData(), savedFirmware.getData()); |
|||
|
|||
savedFirmware.setAdditionalInfo(JacksonUtil.newObjectNode()); |
|||
firmwareService.saveFirmware(savedFirmware); |
|||
|
|||
Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId()); |
|||
Assert.assertEquals(foundFirmware.getTitle(), savedFirmware.getTitle()); |
|||
|
|||
firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
|||
} |
|||
|
|||
@Test |
|||
public void testSaveFirmwareInfoAndUpdateWithData() { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTenantId(tenantId); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION); |
|||
FirmwareInfo savedFirmwareInfo = firmwareService.saveFirmwareInfo(firmwareInfo); |
|||
|
|||
Assert.assertNotNull(savedFirmwareInfo); |
|||
Assert.assertNotNull(savedFirmwareInfo.getId()); |
|||
Assert.assertTrue(savedFirmwareInfo.getCreatedTime() > 0); |
|||
Assert.assertEquals(firmwareInfo.getTenantId(), savedFirmwareInfo.getTenantId()); |
|||
Assert.assertEquals(firmwareInfo.getTitle(), savedFirmwareInfo.getTitle()); |
|||
|
|||
Firmware firmware = new Firmware(savedFirmwareInfo.getId()); |
|||
firmware.setCreatedTime(firmwareInfo.getCreatedTime()); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
|
|||
firmwareService.saveFirmware(firmware); |
|||
|
|||
savedFirmwareInfo = firmwareService.findFirmwareInfoById(tenantId, savedFirmwareInfo.getId()); |
|||
savedFirmwareInfo.setAdditionalInfo(JacksonUtil.newObjectNode()); |
|||
firmwareService.saveFirmwareInfo(savedFirmwareInfo); |
|||
|
|||
Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, firmware.getId()); |
|||
firmware.setAdditionalInfo(JacksonUtil.newObjectNode()); |
|||
|
|||
Assert.assertEquals(foundFirmware.getTitle(), firmware.getTitle()); |
|||
Assert.assertTrue(foundFirmware.isHasData()); |
|||
|
|||
firmwareService.deleteFirmware(tenantId, savedFirmwareInfo.getId()); |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testSaveFirmwareWithEmptyTenant() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
firmwareService.saveFirmware(firmware); |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testSaveFirmwareWithEmptyTitle() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
firmwareService.saveFirmware(firmware); |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testSaveFirmwareWithEmptyFileName() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
firmwareService.saveFirmware(firmware); |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testSaveFirmwareWithEmptyContentType() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
firmwareService.saveFirmware(firmware); |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testSaveFirmwareWithEmptyData() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmwareService.saveFirmware(firmware); |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testSaveFirmwareWithInvalidTenant() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(new TenantId(Uuids.timeBased())); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
firmwareService.saveFirmware(firmware); |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testSaveFirmwareWithEmptyChecksum() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(new TenantId(Uuids.timeBased())); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setData(DATA); |
|||
firmwareService.saveFirmware(firmware); |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testSaveFirmwareInfoWithExistingTitleAndVersion() { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTenantId(tenantId); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION); |
|||
firmwareService.saveFirmwareInfo(firmwareInfo); |
|||
|
|||
FirmwareInfo newFirmwareInfo = new FirmwareInfo(); |
|||
newFirmwareInfo.setTenantId(tenantId); |
|||
newFirmwareInfo.setTitle(TITLE); |
|||
newFirmwareInfo.setVersion(VERSION); |
|||
firmwareService.saveFirmwareInfo(newFirmwareInfo); |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testSaveFirmwareWithExistingTitleAndVersion() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
firmwareService.saveFirmware(firmware); |
|||
|
|||
Firmware newFirmware = new Firmware(); |
|||
newFirmware.setTenantId(tenantId); |
|||
newFirmware.setTitle(TITLE); |
|||
newFirmware.setVersion(VERSION); |
|||
newFirmware.setFileName(FILE_NAME); |
|||
newFirmware.setContentType(CONTENT_TYPE); |
|||
newFirmware.setData(DATA); |
|||
firmwareService.saveFirmware(newFirmware); |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testDeleteFirmwareWithReferenceByDevice() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
Firmware savedFirmware = firmwareService.saveFirmware(firmware); |
|||
|
|||
Device device = new Device(); |
|||
device.setTenantId(tenantId); |
|||
device.setName("My device"); |
|||
device.setType("default"); |
|||
device.setFirmwareId(savedFirmware.getId()); |
|||
Device savedDevice = deviceService.saveDevice(device); |
|||
|
|||
try { |
|||
firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
|||
} finally { |
|||
deviceService.deleteDevice(tenantId, savedDevice.getId()); |
|||
firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
|||
} |
|||
} |
|||
|
|||
@Test(expected = DataValidationException.class) |
|||
public void testDeleteFirmwareWithReferenceByDeviceProfile() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
Firmware savedFirmware = firmwareService.saveFirmware(firmware); |
|||
|
|||
DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile"); |
|||
deviceProfile.setFirmwareId(savedFirmware.getId()); |
|||
DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile); |
|||
|
|||
try { |
|||
firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
|||
} finally { |
|||
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId()); |
|||
firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
|||
} |
|||
} |
|||
|
|||
@Test |
|||
public void testFindFirmwareById() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
Firmware savedFirmware = firmwareService.saveFirmware(firmware); |
|||
|
|||
Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId()); |
|||
Assert.assertNotNull(foundFirmware); |
|||
Assert.assertEquals(savedFirmware, foundFirmware); |
|||
firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
|||
} |
|||
|
|||
@Test |
|||
public void testFindFirmwareInfoById() { |
|||
FirmwareInfo firmware = new FirmwareInfo(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
FirmwareInfo savedFirmware = firmwareService.saveFirmwareInfo(firmware); |
|||
|
|||
FirmwareInfo foundFirmware = firmwareService.findFirmwareInfoById(tenantId, savedFirmware.getId()); |
|||
Assert.assertNotNull(foundFirmware); |
|||
Assert.assertEquals(savedFirmware, foundFirmware); |
|||
firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
|||
} |
|||
|
|||
@Test |
|||
public void testDeleteFirmware() { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
Firmware savedFirmware = firmwareService.saveFirmware(firmware); |
|||
|
|||
Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId()); |
|||
Assert.assertNotNull(foundFirmware); |
|||
firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); |
|||
foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId()); |
|||
Assert.assertNull(foundFirmware); |
|||
} |
|||
|
|||
@Test |
|||
public void testFindTenantFirmwaresByTenantId() { |
|||
List<FirmwareInfo> firmwares = new ArrayList<>(); |
|||
for (int i = 0; i < 165; i++) { |
|||
Firmware firmware = new Firmware(); |
|||
firmware.setTenantId(tenantId); |
|||
firmware.setTitle(TITLE); |
|||
firmware.setVersion(VERSION + i); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
|
|||
FirmwareInfo info = new FirmwareInfo(firmwareService.saveFirmware(firmware)); |
|||
info.setHasData(true); |
|||
firmwares.add(info); |
|||
} |
|||
|
|||
List<FirmwareInfo> loadedFirmwares = new ArrayList<>(); |
|||
PageLink pageLink = new PageLink(16); |
|||
PageData<FirmwareInfo> pageData; |
|||
do { |
|||
pageData = firmwareService.findTenantFirmwaresByTenantId(tenantId, pageLink); |
|||
loadedFirmwares.addAll(pageData.getData()); |
|||
if (pageData.hasNext()) { |
|||
pageLink = pageLink.nextPageLink(); |
|||
} |
|||
} while (pageData.hasNext()); |
|||
|
|||
Collections.sort(firmwares, idComparator); |
|||
Collections.sort(loadedFirmwares, idComparator); |
|||
|
|||
Assert.assertEquals(firmwares, loadedFirmwares); |
|||
|
|||
firmwareService.deleteFirmwaresByTenantId(tenantId); |
|||
|
|||
pageLink = new PageLink(31); |
|||
pageData = firmwareService.findTenantFirmwaresByTenantId(tenantId, pageLink); |
|||
Assert.assertFalse(pageData.hasNext()); |
|||
Assert.assertTrue(pageData.getData().isEmpty()); |
|||
} |
|||
|
|||
@Test |
|||
public void testFindTenantFirmwaresByTenantIdAndHasData() { |
|||
List<FirmwareInfo> firmwares = new ArrayList<>(); |
|||
for (int i = 0; i < 165; i++) { |
|||
FirmwareInfo firmwareInfo = new FirmwareInfo(); |
|||
firmwareInfo.setTenantId(tenantId); |
|||
firmwareInfo.setTitle(TITLE); |
|||
firmwareInfo.setVersion(VERSION + i); |
|||
firmwareInfo.setFileName(FILE_NAME); |
|||
firmwareInfo.setContentType(CONTENT_TYPE); |
|||
firmwareInfo.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmwareInfo.setChecksum(CHECKSUM); |
|||
firmwareInfo.setDataSize((long) DATA.array().length); |
|||
firmwares.add(firmwareService.saveFirmwareInfo(firmwareInfo)); |
|||
} |
|||
|
|||
List<FirmwareInfo> loadedFirmwares = new ArrayList<>(); |
|||
PageLink pageLink = new PageLink(16); |
|||
PageData<FirmwareInfo> pageData; |
|||
do { |
|||
pageData = firmwareService.findTenantFirmwaresByTenantIdAndHasData(tenantId, false, pageLink); |
|||
loadedFirmwares.addAll(pageData.getData()); |
|||
if (pageData.hasNext()) { |
|||
pageLink = pageLink.nextPageLink(); |
|||
} |
|||
} while (pageData.hasNext()); |
|||
|
|||
Collections.sort(firmwares, idComparator); |
|||
Collections.sort(loadedFirmwares, idComparator); |
|||
|
|||
Assert.assertEquals(firmwares, loadedFirmwares); |
|||
|
|||
firmwares.forEach(f -> { |
|||
Firmware firmware = new Firmware(f.getId()); |
|||
firmware.setCreatedTime(f.getCreatedTime()); |
|||
firmware.setTenantId(f.getTenantId()); |
|||
firmware.setTitle(f.getTitle()); |
|||
firmware.setVersion(f.getVersion()); |
|||
firmware.setFileName(FILE_NAME); |
|||
firmware.setContentType(CONTENT_TYPE); |
|||
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); |
|||
firmware.setChecksum(CHECKSUM); |
|||
firmware.setData(DATA); |
|||
firmware.setDataSize((long) DATA.array().length); |
|||
firmwareService.saveFirmware(firmware); |
|||
f.setHasData(true); |
|||
}); |
|||
|
|||
loadedFirmwares = new ArrayList<>(); |
|||
pageLink = new PageLink(16); |
|||
do { |
|||
pageData = firmwareService.findTenantFirmwaresByTenantIdAndHasData(tenantId, true, pageLink); |
|||
loadedFirmwares.addAll(pageData.getData()); |
|||
if (pageData.hasNext()) { |
|||
pageLink = pageLink.nextPageLink(); |
|||
} |
|||
} while (pageData.hasNext()); |
|||
|
|||
Collections.sort(firmwares, idComparator); |
|||
Collections.sort(loadedFirmwares, idComparator); |
|||
|
|||
Assert.assertEquals(firmwares, loadedFirmwares); |
|||
|
|||
firmwareService.deleteFirmwaresByTenantId(tenantId); |
|||
|
|||
pageLink = new PageLink(31); |
|||
pageData = firmwareService.findTenantFirmwaresByTenantId(tenantId, pageLink); |
|||
Assert.assertFalse(pageData.hasNext()); |
|||
Assert.assertTrue(pageData.getData().isEmpty()); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.service.sql; |
|||
|
|||
import org.thingsboard.server.dao.service.BaseFirmwareServiceTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class FirmwareServiceSqlTest extends BaseFirmwareServiceTest { |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue