committed by
GitHub
126 changed files with 2257 additions and 2241 deletions
@ -1,222 +0,0 @@ |
|||||
/** |
|
||||
* 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 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.EntityType; |
|
||||
import org.thingsboard.server.common.data.Firmware; |
|
||||
import org.thingsboard.server.common.data.FirmwareInfo; |
|
||||
import org.thingsboard.server.common.data.audit.ActionType; |
|
||||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|
||||
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm; |
|
||||
import org.thingsboard.server.common.data.firmware.FirmwareType; |
|
||||
import org.thingsboard.server.common.data.id.DeviceProfileId; |
|
||||
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"; |
|
||||
public static final String CHECKSUM_ALGORITHM = "checksumAlgorithm"; |
|
||||
|
|
||||
@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', 'CUSTOMER_USER')") |
|
||||
@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 checkNotNull(firmwareService.findFirmwareInfoById(getTenantId(), firmwareId)); |
|
||||
} 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 { |
|
||||
boolean created = firmwareInfo.getId() == null; |
|
||||
try { |
|
||||
firmwareInfo.setTenantId(getTenantId()); |
|
||||
checkEntity(firmwareInfo.getId(), firmwareInfo, Resource.FIRMWARE); |
|
||||
FirmwareInfo savedFirmwareInfo = firmwareService.saveFirmwareInfo(firmwareInfo); |
|
||||
logEntityAction(savedFirmwareInfo.getId(), savedFirmwareInfo, |
|
||||
null, created ? ActionType.ADDED : ActionType.UPDATED, null); |
|
||||
return savedFirmwareInfo; |
|
||||
} catch (Exception e) { |
|
||||
logEntityAction(emptyId(EntityType.FIRMWARE), firmwareInfo, |
|
||||
null, created ? ActionType.ADDED : ActionType.UPDATED, 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(CHECKSUM_ALGORITHM) String checksumAlgorithmStr, |
|
||||
@RequestBody MultipartFile file) throws ThingsboardException { |
|
||||
checkParameter(FIRMWARE_ID, strFirmwareId); |
|
||||
checkParameter(CHECKSUM_ALGORITHM, checksumAlgorithmStr); |
|
||||
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.setDeviceProfileId(info.getDeviceProfileId()); |
|
||||
firmware.setType(info.getType()); |
|
||||
firmware.setTitle(info.getTitle()); |
|
||||
firmware.setVersion(info.getVersion()); |
|
||||
firmware.setAdditionalInfo(info.getAdditionalInfo()); |
|
||||
|
|
||||
ChecksumAlgorithm checksumAlgorithm = ChecksumAlgorithm.valueOf(checksumAlgorithmStr.toUpperCase()); |
|
||||
|
|
||||
byte[] bytes = file.getBytes(); |
|
||||
if (StringUtils.isEmpty(checksum)) { |
|
||||
checksum = firmwareService.generateChecksum(checksumAlgorithm, ByteBuffer.wrap(bytes)); |
|
||||
} |
|
||||
|
|
||||
firmware.setChecksumAlgorithm(checksumAlgorithm); |
|
||||
firmware.setChecksum(checksum); |
|
||||
firmware.setFileName(file.getOriginalFilename()); |
|
||||
firmware.setContentType(file.getContentType()); |
|
||||
firmware.setData(ByteBuffer.wrap(bytes)); |
|
||||
firmware.setDataSize((long) bytes.length); |
|
||||
Firmware savedFirmware = firmwareService.saveFirmware(firmware); |
|
||||
logEntityAction(savedFirmware.getId(), savedFirmware, null, ActionType.UPDATED, null); |
|
||||
return savedFirmware; |
|
||||
} catch (Exception e) { |
|
||||
logEntityAction(emptyId(EntityType.FIRMWARE), null, null, ActionType.UPDATED, e, strFirmwareId); |
|
||||
throw handleException(e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
|
||||
@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', 'CUSTOMER_USER')") |
|
||||
@RequestMapping(value = "/firmwares/{deviceProfileId}/{type}/{hasData}", method = RequestMethod.GET) |
|
||||
@ResponseBody |
|
||||
public PageData<FirmwareInfo> getFirmwares(@PathVariable("deviceProfileId") String strDeviceProfileId, |
|
||||
@PathVariable("type") String strType, |
|
||||
@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 { |
|
||||
checkParameter("deviceProfileId", strDeviceProfileId); |
|
||||
checkParameter("type", strType); |
|
||||
try { |
|
||||
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
|
||||
return checkNotNull(firmwareService.findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(getTenantId(), |
|
||||
new DeviceProfileId(toUUID(strDeviceProfileId)), FirmwareType.valueOf(strType), hasData, pageLink)); |
|
||||
} catch (Exception e) { |
|
||||
throw handleException(e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
|
||||
@RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.DELETE) |
|
||||
@ResponseBody |
|
||||
public void deleteFirmware(@PathVariable("firmwareId") String strFirmwareId) throws ThingsboardException { |
|
||||
checkParameter(FIRMWARE_ID, strFirmwareId); |
|
||||
try { |
|
||||
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId)); |
|
||||
FirmwareInfo info = checkFirmwareInfoId(firmwareId, Operation.DELETE); |
|
||||
firmwareService.deleteFirmware(getTenantId(), firmwareId); |
|
||||
logEntityAction(firmwareId, info, null, ActionType.DELETED, null, strFirmwareId); |
|
||||
} catch (Exception e) { |
|
||||
logEntityAction(emptyId(EntityType.FIRMWARE), null, null, ActionType.DELETED, e, strFirmwareId); |
|
||||
throw handleException(e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -0,0 +1,222 @@ |
|||||
|
/** |
||||
|
* 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 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.EntityType; |
||||
|
import org.thingsboard.server.common.data.OtaPackage; |
||||
|
import org.thingsboard.server.common.data.OtaPackageInfo; |
||||
|
import org.thingsboard.server.common.data.audit.ActionType; |
||||
|
import org.thingsboard.server.common.data.exception.ThingsboardException; |
||||
|
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; |
||||
|
import org.thingsboard.server.common.data.ota.OtaPackageType; |
||||
|
import org.thingsboard.server.common.data.id.DeviceProfileId; |
||||
|
import org.thingsboard.server.common.data.id.OtaPackageId; |
||||
|
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 OtaPackageController extends BaseController { |
||||
|
|
||||
|
public static final String OTA_PACKAGE_ID = "otaPackageId"; |
||||
|
public static final String CHECKSUM_ALGORITHM = "checksumAlgorithm"; |
||||
|
|
||||
|
@PreAuthorize("hasAnyAuthority( 'TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/otaPackage/{otaPackageId}/download", method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public ResponseEntity<org.springframework.core.io.Resource> downloadOtaPackage(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { |
||||
|
checkParameter(OTA_PACKAGE_ID, strOtaPackageId); |
||||
|
try { |
||||
|
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); |
||||
|
OtaPackage otaPackage = checkOtaPackageId(otaPackageId, Operation.READ); |
||||
|
|
||||
|
ByteArrayResource resource = new ByteArrayResource(otaPackage.getData().array()); |
||||
|
return ResponseEntity.ok() |
||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + otaPackage.getFileName()) |
||||
|
.header("x-filename", otaPackage.getFileName()) |
||||
|
.contentLength(resource.contentLength()) |
||||
|
.contentType(parseMediaType(otaPackage.getContentType())) |
||||
|
.body(resource); |
||||
|
} catch (Exception e) { |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
||||
|
@RequestMapping(value = "/otaPackage/info/{otaPackageId}", method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public OtaPackageInfo getOtaPackageInfoById(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { |
||||
|
checkParameter(OTA_PACKAGE_ID, strOtaPackageId); |
||||
|
try { |
||||
|
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); |
||||
|
return checkNotNull(otaPackageService.findOtaPackageInfoById(getTenantId(), otaPackageId)); |
||||
|
} catch (Exception e) { |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public OtaPackage getOtaPackageById(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { |
||||
|
checkParameter(OTA_PACKAGE_ID, strOtaPackageId); |
||||
|
try { |
||||
|
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); |
||||
|
return checkOtaPackageId(otaPackageId, Operation.READ); |
||||
|
} catch (Exception e) { |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/otaPackage", method = RequestMethod.POST) |
||||
|
@ResponseBody |
||||
|
public OtaPackageInfo saveOtaPackageInfo(@RequestBody OtaPackageInfo otaPackageInfo) throws ThingsboardException { |
||||
|
boolean created = otaPackageInfo.getId() == null; |
||||
|
try { |
||||
|
otaPackageInfo.setTenantId(getTenantId()); |
||||
|
checkEntity(otaPackageInfo.getId(), otaPackageInfo, Resource.OTA_PACKAGE); |
||||
|
OtaPackageInfo savedOtaPackageInfo = otaPackageService.saveOtaPackageInfo(otaPackageInfo); |
||||
|
logEntityAction(savedOtaPackageInfo.getId(), savedOtaPackageInfo, |
||||
|
null, created ? ActionType.ADDED : ActionType.UPDATED, null); |
||||
|
return savedOtaPackageInfo; |
||||
|
} catch (Exception e) { |
||||
|
logEntityAction(emptyId(EntityType.OTA_PACKAGE), otaPackageInfo, |
||||
|
null, created ? ActionType.ADDED : ActionType.UPDATED, e); |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.POST) |
||||
|
@ResponseBody |
||||
|
public OtaPackage saveOtaPackageData(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId, |
||||
|
@RequestParam(required = false) String checksum, |
||||
|
@RequestParam(CHECKSUM_ALGORITHM) String checksumAlgorithmStr, |
||||
|
@RequestBody MultipartFile file) throws ThingsboardException { |
||||
|
checkParameter(OTA_PACKAGE_ID, strOtaPackageId); |
||||
|
checkParameter(CHECKSUM_ALGORITHM, checksumAlgorithmStr); |
||||
|
try { |
||||
|
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); |
||||
|
OtaPackageInfo info = checkOtaPackageInfoId(otaPackageId, Operation.READ); |
||||
|
|
||||
|
OtaPackage otaPackage = new OtaPackage(otaPackageId); |
||||
|
otaPackage.setCreatedTime(info.getCreatedTime()); |
||||
|
otaPackage.setTenantId(getTenantId()); |
||||
|
otaPackage.setDeviceProfileId(info.getDeviceProfileId()); |
||||
|
otaPackage.setType(info.getType()); |
||||
|
otaPackage.setTitle(info.getTitle()); |
||||
|
otaPackage.setVersion(info.getVersion()); |
||||
|
otaPackage.setAdditionalInfo(info.getAdditionalInfo()); |
||||
|
|
||||
|
ChecksumAlgorithm checksumAlgorithm = ChecksumAlgorithm.valueOf(checksumAlgorithmStr.toUpperCase()); |
||||
|
|
||||
|
byte[] bytes = file.getBytes(); |
||||
|
if (StringUtils.isEmpty(checksum)) { |
||||
|
checksum = otaPackageService.generateChecksum(checksumAlgorithm, ByteBuffer.wrap(bytes)); |
||||
|
} |
||||
|
|
||||
|
otaPackage.setChecksumAlgorithm(checksumAlgorithm); |
||||
|
otaPackage.setChecksum(checksum); |
||||
|
otaPackage.setFileName(file.getOriginalFilename()); |
||||
|
otaPackage.setContentType(file.getContentType()); |
||||
|
otaPackage.setData(ByteBuffer.wrap(bytes)); |
||||
|
otaPackage.setDataSize((long) bytes.length); |
||||
|
OtaPackage savedOtaPackage = otaPackageService.saveOtaPackage(otaPackage); |
||||
|
logEntityAction(savedOtaPackage.getId(), savedOtaPackage, null, ActionType.UPDATED, null); |
||||
|
return savedOtaPackage; |
||||
|
} catch (Exception e) { |
||||
|
logEntityAction(emptyId(EntityType.OTA_PACKAGE), null, null, ActionType.UPDATED, e, strOtaPackageId); |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
||||
|
@RequestMapping(value = "/otaPackages", method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public PageData<OtaPackageInfo> getOtaPackages(@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(otaPackageService.findTenantOtaPackagesByTenantId(getTenantId(), pageLink)); |
||||
|
} catch (Exception e) { |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
||||
|
@RequestMapping(value = "/otaPackages/{deviceProfileId}/{type}/{hasData}", method = RequestMethod.GET) |
||||
|
@ResponseBody |
||||
|
public PageData<OtaPackageInfo> getOtaPackages(@PathVariable("deviceProfileId") String strDeviceProfileId, |
||||
|
@PathVariable("type") String strType, |
||||
|
@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 { |
||||
|
checkParameter("deviceProfileId", strDeviceProfileId); |
||||
|
checkParameter("type", strType); |
||||
|
try { |
||||
|
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
||||
|
return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(getTenantId(), |
||||
|
new DeviceProfileId(toUUID(strDeviceProfileId)), OtaPackageType.valueOf(strType), hasData, pageLink)); |
||||
|
} catch (Exception e) { |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
||||
|
@RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.DELETE) |
||||
|
@ResponseBody |
||||
|
public void deleteOtaPackage(@PathVariable("otaPackageId") String strOtaPackageId) throws ThingsboardException { |
||||
|
checkParameter(OTA_PACKAGE_ID, strOtaPackageId); |
||||
|
try { |
||||
|
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); |
||||
|
OtaPackageInfo info = checkOtaPackageInfoId(otaPackageId, Operation.DELETE); |
||||
|
otaPackageService.deleteOtaPackage(getTenantId(), otaPackageId); |
||||
|
logEntityAction(otaPackageId, info, null, ActionType.DELETED, null, strOtaPackageId); |
||||
|
} catch (Exception e) { |
||||
|
logEntityAction(emptyId(EntityType.OTA_PACKAGE), null, null, ActionType.DELETED, e, strOtaPackageId); |
||||
|
throw handleException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -1,52 +0,0 @@ |
|||||
/** |
|
||||
* 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.util.concurrent.ListenableFuture; |
|
||||
import org.thingsboard.server.common.data.Firmware; |
|
||||
import org.thingsboard.server.common.data.FirmwareInfo; |
|
||||
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm; |
|
||||
import org.thingsboard.server.common.data.firmware.FirmwareType; |
|
||||
import org.thingsboard.server.common.data.id.DeviceProfileId; |
|
||||
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 java.nio.ByteBuffer; |
|
||||
|
|
||||
public interface FirmwareService { |
|
||||
|
|
||||
FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo); |
|
||||
|
|
||||
Firmware saveFirmware(Firmware firmware); |
|
||||
|
|
||||
String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data); |
|
||||
|
|
||||
Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId); |
|
||||
|
|
||||
FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId); |
|
||||
|
|
||||
ListenableFuture<FirmwareInfo> findFirmwareInfoByIdAsync(TenantId tenantId, FirmwareId firmwareId); |
|
||||
|
|
||||
PageData<FirmwareInfo> findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink); |
|
||||
|
|
||||
PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink); |
|
||||
|
|
||||
void deleteFirmware(TenantId tenantId, FirmwareId firmwareId); |
|
||||
|
|
||||
void deleteFirmwaresByTenantId(TenantId tenantId); |
|
||||
} |
|
||||
@ -0,0 +1,52 @@ |
|||||
|
/** |
||||
|
* 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.ota; |
||||
|
|
||||
|
import com.google.common.util.concurrent.ListenableFuture; |
||||
|
import org.thingsboard.server.common.data.OtaPackage; |
||||
|
import org.thingsboard.server.common.data.OtaPackageInfo; |
||||
|
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; |
||||
|
import org.thingsboard.server.common.data.ota.OtaPackageType; |
||||
|
import org.thingsboard.server.common.data.id.DeviceProfileId; |
||||
|
import org.thingsboard.server.common.data.id.OtaPackageId; |
||||
|
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 java.nio.ByteBuffer; |
||||
|
|
||||
|
public interface OtaPackageService { |
||||
|
|
||||
|
OtaPackageInfo saveOtaPackageInfo(OtaPackageInfo otaPackageInfo); |
||||
|
|
||||
|
OtaPackage saveOtaPackage(OtaPackage otaPackage); |
||||
|
|
||||
|
String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data); |
||||
|
|
||||
|
OtaPackage findOtaPackageById(TenantId tenantId, OtaPackageId otaPackageId); |
||||
|
|
||||
|
OtaPackageInfo findOtaPackageInfoById(TenantId tenantId, OtaPackageId otaPackageId); |
||||
|
|
||||
|
ListenableFuture<OtaPackageInfo> findOtaPackageInfoByIdAsync(TenantId tenantId, OtaPackageId otaPackageId); |
||||
|
|
||||
|
PageData<OtaPackageInfo> findTenantOtaPackagesByTenantId(TenantId tenantId, PageLink pageLink); |
||||
|
|
||||
|
PageData<OtaPackageInfo> findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType, boolean hasData, PageLink pageLink); |
||||
|
|
||||
|
void deleteOtaPackage(TenantId tenantId, OtaPackageId otaPackageId); |
||||
|
|
||||
|
void deleteOtaPackagesByTenantId(TenantId tenantId); |
||||
|
} |
||||
@ -1,379 +0,0 @@ |
|||||
/** |
|
||||
* 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 com.google.common.util.concurrent.ListenableFuture; |
|
||||
import lombok.RequiredArgsConstructor; |
|
||||
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.cache.annotation.Cacheable; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
import org.thingsboard.server.cache.firmware.FirmwareDataCache; |
|
||||
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.exception.ThingsboardErrorCode; |
|
||||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|
||||
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm; |
|
||||
import org.thingsboard.server.common.data.firmware.FirmwareType; |
|
||||
import org.thingsboard.server.common.data.id.DeviceProfileId; |
|
||||
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.device.DeviceProfileDao; |
|
||||
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.lang.reflect.InvocationTargetException; |
|
||||
import java.lang.reflect.Method; |
|
||||
import java.nio.ByteBuffer; |
|
||||
import java.util.ArrayList; |
|
||||
import java.util.Arrays; |
|
||||
import java.util.Collections; |
|
||||
import java.util.List; |
|
||||
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 |
|
||||
@RequiredArgsConstructor |
|
||||
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 DeviceProfileDao deviceProfileDao; |
|
||||
private final FirmwareDao firmwareDao; |
|
||||
private final FirmwareInfoDao firmwareInfoDao; |
|
||||
private final CacheManager cacheManager; |
|
||||
private final FirmwareDataCache firmwareDataCache; |
|
||||
|
|
||||
@Override |
|
||||
public FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo) { |
|
||||
log.trace("Executing saveFirmwareInfo [{}]", firmwareInfo); |
|
||||
firmwareInfoValidator.validate(firmwareInfo, FirmwareInfo::getTenantId); |
|
||||
try { |
|
||||
FirmwareId firmwareId = firmwareInfo.getId(); |
|
||||
if (firmwareId != null) { |
|
||||
Cache cache = cacheManager.getCache(FIRMWARE_CACHE); |
|
||||
cache.evict(toFirmwareInfoKey(firmwareId)); |
|
||||
firmwareDataCache.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) { |
|
||||
Cache cache = cacheManager.getCache(FIRMWARE_CACHE); |
|
||||
cache.evict(toFirmwareInfoKey(firmwareId)); |
|
||||
firmwareDataCache.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 String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data) { |
|
||||
if (data == null || !data.hasArray() || data.array().length == 0) { |
|
||||
throw new DataValidationException("Firmware data should be specified!"); |
|
||||
} |
|
||||
|
|
||||
return getHashFunction(checksumAlgorithm).hashBytes(data.array()).toString(); |
|
||||
} |
|
||||
|
|
||||
private HashFunction getHashFunction(ChecksumAlgorithm checksumAlgorithm) { |
|
||||
switch (checksumAlgorithm) { |
|
||||
case MD5: |
|
||||
return Hashing.md5(); |
|
||||
case SHA256: |
|
||||
return Hashing.sha256(); |
|
||||
case SHA384: |
|
||||
return Hashing.sha384(); |
|
||||
case SHA512: |
|
||||
return Hashing.sha512(); |
|
||||
case CRC32: |
|
||||
return Hashing.crc32(); |
|
||||
case MURMUR3_32: |
|
||||
return Hashing.murmur3_32(); |
|
||||
case MURMUR3_128: |
|
||||
return Hashing.murmur3_128(); |
|
||||
default: |
|
||||
throw new DataValidationException("Unknown checksum algorithm!"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@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 |
|
||||
@Cacheable(cacheNames = FIRMWARE_CACHE, key = "{#firmwareId}") |
|
||||
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 ListenableFuture<FirmwareInfo> findFirmwareInfoByIdAsync(TenantId tenantId, FirmwareId firmwareId) { |
|
||||
log.trace("Executing findFirmwareInfoByIdAsync [{}]", firmwareId); |
|
||||
validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); |
|
||||
return firmwareInfoDao.findByIdAsync(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> findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink) { |
|
||||
log.trace("Executing findTenantFirmwaresByTenantIdAndHasData, tenantId [{}], hasData [{}] pageLink [{}]", tenantId, hasData, pageLink); |
|
||||
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
|
||||
validatePageLink(pageLink); |
|
||||
return firmwareInfoDao.findFirmwareInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, firmwareType, 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(toFirmwareInfoKey(firmwareId)); |
|
||||
firmwareDataCache.evict(firmwareId.toString()); |
|
||||
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 if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_software_device")) { |
|
||||
throw new DataValidationException("The software referenced by the devices cannot be deleted!"); |
|
||||
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_software_device_profile")) { |
|
||||
throw new DataValidationException("The software 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 firmwareInfo) { |
|
||||
validateImpl(firmwareInfo); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void validateUpdate(TenantId tenantId, FirmwareInfo firmware) { |
|
||||
FirmwareInfo firmwareOld = firmwareInfoDao.findById(tenantId, firmware.getUuidId()); |
|
||||
|
|
||||
validateUpdateDeviceProfile(firmware, firmwareOld); |
|
||||
BaseFirmwareService.validateUpdate(firmware, firmwareOld); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
private DataValidator<Firmware> firmwareValidator = new DataValidator<>() { |
|
||||
|
|
||||
@Override |
|
||||
protected void validateDataImpl(TenantId tenantId, Firmware firmware) { |
|
||||
validateImpl(firmware); |
|
||||
|
|
||||
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!"); |
|
||||
} |
|
||||
|
|
||||
if (firmware.getChecksumAlgorithm() == null) { |
|
||||
throw new DataValidationException("Firmware checksum algorithm should be specified!"); |
|
||||
} |
|
||||
if (StringUtils.isEmpty(firmware.getChecksum())) { |
|
||||
throw new DataValidationException("Firmware checksum should be specified!"); |
|
||||
} |
|
||||
|
|
||||
String currentChecksum; |
|
||||
|
|
||||
currentChecksum = generateChecksum(firmware.getChecksumAlgorithm(), firmware.getData()); |
|
||||
|
|
||||
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()); |
|
||||
|
|
||||
validateUpdateDeviceProfile(firmware, firmwareOld); |
|
||||
BaseFirmwareService.validateUpdate(firmware, firmwareOld); |
|
||||
|
|
||||
if (firmwareOld.getData() != null && !firmwareOld.getData().equals(firmware.getData())) { |
|
||||
throw new DataValidationException("Updating firmware data is prohibited!"); |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
private void validateUpdateDeviceProfile(FirmwareInfo firmware, FirmwareInfo firmwareOld) { |
|
||||
if (firmwareOld.getDeviceProfileId() != null && !firmwareOld.getDeviceProfileId().equals(firmware.getDeviceProfileId())) { |
|
||||
if (firmwareInfoDao.isFirmwareUsed(firmwareOld.getId(), firmware.getType(), firmwareOld.getDeviceProfileId())) { |
|
||||
throw new DataValidationException("Can`t update deviceProfileId because firmware is already in use!"); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static void validateUpdate(FirmwareInfo firmware, FirmwareInfo firmwareOld) { |
|
||||
if (!firmwareOld.getType().equals(firmware.getType())) { |
|
||||
throw new DataValidationException("Updating type is prohibited!"); |
|
||||
} |
|
||||
|
|
||||
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 void validateImpl(FirmwareInfo firmwareInfo) { |
|
||||
if (firmwareInfo.getTenantId() == null) { |
|
||||
throw new DataValidationException("Firmware should be assigned to tenant!"); |
|
||||
} else { |
|
||||
Tenant tenant = tenantDao.findById(firmwareInfo.getTenantId(), firmwareInfo.getTenantId().getId()); |
|
||||
if (tenant == null) { |
|
||||
throw new DataValidationException("Firmware is referencing to non-existent tenant!"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (firmwareInfo.getDeviceProfileId() != null) { |
|
||||
DeviceProfile deviceProfile = deviceProfileDao.findById(firmwareInfo.getTenantId(), firmwareInfo.getDeviceProfileId().getId()); |
|
||||
if (deviceProfile == null) { |
|
||||
throw new DataValidationException("Firmware is referencing to non-existent device profile!"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (firmwareInfo.getType() == null) { |
|
||||
throw new DataValidationException("Type should be specified!"); |
|
||||
} |
|
||||
|
|
||||
if (StringUtils.isEmpty(firmwareInfo.getTitle())) { |
|
||||
throw new DataValidationException("Firmware title should be specified!"); |
|
||||
} |
|
||||
|
|
||||
if (StringUtils.isEmpty(firmwareInfo.getVersion())) { |
|
||||
throw new DataValidationException("Firmware version should be specified!"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
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(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static List<FirmwareId> toFirmwareInfoKey(FirmwareId firmwareId) { |
|
||||
return Collections.singletonList(firmwareId); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -0,0 +1,366 @@ |
|||||
|
/** |
||||
|
* 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.ota; |
||||
|
|
||||
|
import com.google.common.hash.HashFunction; |
||||
|
import com.google.common.hash.Hashing; |
||||
|
import com.google.common.util.concurrent.ListenableFuture; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
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.cache.annotation.Cacheable; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.thingsboard.server.cache.ota.OtaPackageDataCache; |
||||
|
import org.thingsboard.server.common.data.DeviceProfile; |
||||
|
import org.thingsboard.server.common.data.OtaPackage; |
||||
|
import org.thingsboard.server.common.data.OtaPackageInfo; |
||||
|
import org.thingsboard.server.common.data.Tenant; |
||||
|
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; |
||||
|
import org.thingsboard.server.common.data.ota.OtaPackageType; |
||||
|
import org.thingsboard.server.common.data.id.DeviceProfileId; |
||||
|
import org.thingsboard.server.common.data.id.OtaPackageId; |
||||
|
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.device.DeviceProfileDao; |
||||
|
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.List; |
||||
|
import java.util.Optional; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_CACHE; |
||||
|
import static org.thingsboard.server.dao.service.Validator.validateId; |
||||
|
import static org.thingsboard.server.dao.service.Validator.validatePageLink; |
||||
|
|
||||
|
@Service |
||||
|
@Slf4j |
||||
|
@RequiredArgsConstructor |
||||
|
public class BaseOtaPackageService implements OtaPackageService { |
||||
|
public static final String INCORRECT_OTA_PACKAGE_ID = "Incorrect otaPackageId "; |
||||
|
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; |
||||
|
|
||||
|
private final TenantDao tenantDao; |
||||
|
private final DeviceProfileDao deviceProfileDao; |
||||
|
private final OtaPackageDao otaPackageDao; |
||||
|
private final OtaPackageInfoDao otaPackageInfoDao; |
||||
|
private final CacheManager cacheManager; |
||||
|
private final OtaPackageDataCache otaPackageDataCache; |
||||
|
|
||||
|
@Override |
||||
|
public OtaPackageInfo saveOtaPackageInfo(OtaPackageInfo otaPackageInfo) { |
||||
|
log.trace("Executing saveOtaPackageInfo [{}]", otaPackageInfo); |
||||
|
otaPackageInfoValidator.validate(otaPackageInfo, OtaPackageInfo::getTenantId); |
||||
|
try { |
||||
|
OtaPackageId otaPackageId = otaPackageInfo.getId(); |
||||
|
if (otaPackageId != null) { |
||||
|
Cache cache = cacheManager.getCache(OTA_PACKAGE_CACHE); |
||||
|
cache.evict(toOtaPackageInfoKey(otaPackageId)); |
||||
|
otaPackageDataCache.evict(otaPackageId.toString()); |
||||
|
} |
||||
|
return otaPackageInfoDao.save(otaPackageInfo.getTenantId(), otaPackageInfo); |
||||
|
} catch (Exception t) { |
||||
|
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); |
||||
|
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("ota_package_tenant_title_version_unq_key")) { |
||||
|
throw new DataValidationException("OtaPackage with such title and version already exists!"); |
||||
|
} else { |
||||
|
throw t; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public OtaPackage saveOtaPackage(OtaPackage otaPackage) { |
||||
|
log.trace("Executing saveOtaPackage [{}]", otaPackage); |
||||
|
otaPackageValidator.validate(otaPackage, OtaPackageInfo::getTenantId); |
||||
|
try { |
||||
|
OtaPackageId otaPackageId = otaPackage.getId(); |
||||
|
if (otaPackageId != null) { |
||||
|
Cache cache = cacheManager.getCache(OTA_PACKAGE_CACHE); |
||||
|
cache.evict(toOtaPackageInfoKey(otaPackageId)); |
||||
|
otaPackageDataCache.evict(otaPackageId.toString()); |
||||
|
} |
||||
|
return otaPackageDao.save(otaPackage.getTenantId(), otaPackage); |
||||
|
} catch (Exception t) { |
||||
|
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); |
||||
|
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("ota_package_tenant_title_version_unq_key")) { |
||||
|
throw new DataValidationException("OtaPackage with such title and version already exists!"); |
||||
|
} else { |
||||
|
throw t; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data) { |
||||
|
if (data == null || !data.hasArray() || data.array().length == 0) { |
||||
|
throw new DataValidationException("OtaPackage data should be specified!"); |
||||
|
} |
||||
|
|
||||
|
return getHashFunction(checksumAlgorithm).hashBytes(data.array()).toString(); |
||||
|
} |
||||
|
|
||||
|
private HashFunction getHashFunction(ChecksumAlgorithm checksumAlgorithm) { |
||||
|
switch (checksumAlgorithm) { |
||||
|
case MD5: |
||||
|
return Hashing.md5(); |
||||
|
case SHA256: |
||||
|
return Hashing.sha256(); |
||||
|
case SHA384: |
||||
|
return Hashing.sha384(); |
||||
|
case SHA512: |
||||
|
return Hashing.sha512(); |
||||
|
case CRC32: |
||||
|
return Hashing.crc32(); |
||||
|
case MURMUR3_32: |
||||
|
return Hashing.murmur3_32(); |
||||
|
case MURMUR3_128: |
||||
|
return Hashing.murmur3_128(); |
||||
|
default: |
||||
|
throw new DataValidationException("Unknown checksum algorithm!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public OtaPackage findOtaPackageById(TenantId tenantId, OtaPackageId otaPackageId) { |
||||
|
log.trace("Executing findOtaPackageById [{}]", otaPackageId); |
||||
|
validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId); |
||||
|
return otaPackageDao.findById(tenantId, otaPackageId.getId()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
@Cacheable(cacheNames = OTA_PACKAGE_CACHE, key = "{#otaPackageId}") |
||||
|
public OtaPackageInfo findOtaPackageInfoById(TenantId tenantId, OtaPackageId otaPackageId) { |
||||
|
log.trace("Executing findOtaPackageInfoById [{}]", otaPackageId); |
||||
|
validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId); |
||||
|
return otaPackageInfoDao.findById(tenantId, otaPackageId.getId()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ListenableFuture<OtaPackageInfo> findOtaPackageInfoByIdAsync(TenantId tenantId, OtaPackageId otaPackageId) { |
||||
|
log.trace("Executing findOtaPackageInfoByIdAsync [{}]", otaPackageId); |
||||
|
validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId); |
||||
|
return otaPackageInfoDao.findByIdAsync(tenantId, otaPackageId.getId()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageData<OtaPackageInfo> findTenantOtaPackagesByTenantId(TenantId tenantId, PageLink pageLink) { |
||||
|
log.trace("Executing findTenantOtaPackagesByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); |
||||
|
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
||||
|
validatePageLink(pageLink); |
||||
|
return otaPackageInfoDao.findOtaPackageInfoByTenantId(tenantId, pageLink); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageData<OtaPackageInfo> findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType, boolean hasData, PageLink pageLink) { |
||||
|
log.trace("Executing findTenantOtaPackagesByTenantIdAndHasData, tenantId [{}], hasData [{}] pageLink [{}]", tenantId, hasData, pageLink); |
||||
|
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
||||
|
validatePageLink(pageLink); |
||||
|
return otaPackageInfoDao.findOtaPackageInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, otaPackageType, hasData, pageLink); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void deleteOtaPackage(TenantId tenantId, OtaPackageId otaPackageId) { |
||||
|
log.trace("Executing deleteOtaPackage [{}]", otaPackageId); |
||||
|
validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId); |
||||
|
try { |
||||
|
Cache cache = cacheManager.getCache(OTA_PACKAGE_CACHE); |
||||
|
cache.evict(toOtaPackageInfoKey(otaPackageId)); |
||||
|
otaPackageDataCache.evict(otaPackageId.toString()); |
||||
|
otaPackageDao.removeById(tenantId, otaPackageId.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 otaPackage 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 otaPackage referenced by the device profile cannot be deleted!"); |
||||
|
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_software_device")) { |
||||
|
throw new DataValidationException("The software referenced by the devices cannot be deleted!"); |
||||
|
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_software_device_profile")) { |
||||
|
throw new DataValidationException("The software referenced by the device profile cannot be deleted!"); |
||||
|
} else { |
||||
|
throw t; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void deleteOtaPackagesByTenantId(TenantId tenantId) { |
||||
|
log.trace("Executing deleteOtaPackagesByTenantId, tenantId [{}]", tenantId); |
||||
|
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); |
||||
|
tenantOtaPackageRemover.removeEntities(tenantId, tenantId); |
||||
|
} |
||||
|
|
||||
|
private DataValidator<OtaPackageInfo> otaPackageInfoValidator = new DataValidator<>() { |
||||
|
|
||||
|
@Override |
||||
|
protected void validateDataImpl(TenantId tenantId, OtaPackageInfo otaPackageInfo) { |
||||
|
validateImpl(otaPackageInfo); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void validateUpdate(TenantId tenantId, OtaPackageInfo otaPackage) { |
||||
|
OtaPackageInfo otaPackageOld = otaPackageInfoDao.findById(tenantId, otaPackage.getUuidId()); |
||||
|
BaseOtaPackageService.validateUpdate(otaPackage, otaPackageOld); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
private DataValidator<OtaPackage> otaPackageValidator = new DataValidator<>() { |
||||
|
|
||||
|
@Override |
||||
|
protected void validateDataImpl(TenantId tenantId, OtaPackage otaPackage) { |
||||
|
validateImpl(otaPackage); |
||||
|
|
||||
|
if (StringUtils.isEmpty(otaPackage.getFileName())) { |
||||
|
throw new DataValidationException("OtaPackage file name should be specified!"); |
||||
|
} |
||||
|
|
||||
|
if (StringUtils.isEmpty(otaPackage.getContentType())) { |
||||
|
throw new DataValidationException("OtaPackage content type should be specified!"); |
||||
|
} |
||||
|
|
||||
|
if (otaPackage.getChecksumAlgorithm() == null) { |
||||
|
throw new DataValidationException("OtaPackage checksum algorithm should be specified!"); |
||||
|
} |
||||
|
if (StringUtils.isEmpty(otaPackage.getChecksum())) { |
||||
|
throw new DataValidationException("OtaPackage checksum should be specified!"); |
||||
|
} |
||||
|
|
||||
|
String currentChecksum; |
||||
|
|
||||
|
currentChecksum = generateChecksum(otaPackage.getChecksumAlgorithm(), otaPackage.getData()); |
||||
|
|
||||
|
if (!currentChecksum.equals(otaPackage.getChecksum())) { |
||||
|
throw new DataValidationException("Wrong otaPackage file!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void validateUpdate(TenantId tenantId, OtaPackage otaPackage) { |
||||
|
OtaPackage otaPackageOld = otaPackageDao.findById(tenantId, otaPackage.getUuidId()); |
||||
|
|
||||
|
BaseOtaPackageService.validateUpdate(otaPackage, otaPackageOld); |
||||
|
|
||||
|
if (otaPackageOld.getData() != null && !otaPackageOld.getData().equals(otaPackage.getData())) { |
||||
|
throw new DataValidationException("Updating otaPackage data is prohibited!"); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
private static void validateUpdate(OtaPackageInfo otaPackage, OtaPackageInfo otaPackageOld) { |
||||
|
if (!otaPackageOld.getType().equals(otaPackage.getType())) { |
||||
|
throw new DataValidationException("Updating type is prohibited!"); |
||||
|
} |
||||
|
|
||||
|
if (!otaPackageOld.getTitle().equals(otaPackage.getTitle())) { |
||||
|
throw new DataValidationException("Updating otaPackage title is prohibited!"); |
||||
|
} |
||||
|
|
||||
|
if (!otaPackageOld.getVersion().equals(otaPackage.getVersion())) { |
||||
|
throw new DataValidationException("Updating otaPackage version is prohibited!"); |
||||
|
} |
||||
|
|
||||
|
if (!otaPackageOld.getDeviceProfileId().equals(otaPackage.getDeviceProfileId())) { |
||||
|
throw new DataValidationException("Updating otaPackage deviceProfile is prohibited!"); |
||||
|
} |
||||
|
|
||||
|
if (otaPackageOld.getFileName() != null && !otaPackageOld.getFileName().equals(otaPackage.getFileName())) { |
||||
|
throw new DataValidationException("Updating otaPackage file name is prohibited!"); |
||||
|
} |
||||
|
|
||||
|
if (otaPackageOld.getContentType() != null && !otaPackageOld.getContentType().equals(otaPackage.getContentType())) { |
||||
|
throw new DataValidationException("Updating otaPackage content type is prohibited!"); |
||||
|
} |
||||
|
|
||||
|
if (otaPackageOld.getChecksumAlgorithm() != null && !otaPackageOld.getChecksumAlgorithm().equals(otaPackage.getChecksumAlgorithm())) { |
||||
|
throw new DataValidationException("Updating otaPackage content type is prohibited!"); |
||||
|
} |
||||
|
|
||||
|
if (otaPackageOld.getChecksum() != null && !otaPackageOld.getChecksum().equals(otaPackage.getChecksum())) { |
||||
|
throw new DataValidationException("Updating otaPackage content type is prohibited!"); |
||||
|
} |
||||
|
|
||||
|
if (otaPackageOld.getDataSize() != null && !otaPackageOld.getDataSize().equals(otaPackage.getDataSize())) { |
||||
|
throw new DataValidationException("Updating otaPackage data size is prohibited!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void validateImpl(OtaPackageInfo otaPackageInfo) { |
||||
|
if (otaPackageInfo.getTenantId() == null) { |
||||
|
throw new DataValidationException("OtaPackage should be assigned to tenant!"); |
||||
|
} else { |
||||
|
Tenant tenant = tenantDao.findById(otaPackageInfo.getTenantId(), otaPackageInfo.getTenantId().getId()); |
||||
|
if (tenant == null) { |
||||
|
throw new DataValidationException("OtaPackage is referencing to non-existent tenant!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (otaPackageInfo.getDeviceProfileId() != null) { |
||||
|
DeviceProfile deviceProfile = deviceProfileDao.findById(otaPackageInfo.getTenantId(), otaPackageInfo.getDeviceProfileId().getId()); |
||||
|
if (deviceProfile == null) { |
||||
|
throw new DataValidationException("OtaPackage is referencing to non-existent device profile!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (otaPackageInfo.getType() == null) { |
||||
|
throw new DataValidationException("Type should be specified!"); |
||||
|
} |
||||
|
|
||||
|
if (StringUtils.isEmpty(otaPackageInfo.getTitle())) { |
||||
|
throw new DataValidationException("OtaPackage title should be specified!"); |
||||
|
} |
||||
|
|
||||
|
if (StringUtils.isEmpty(otaPackageInfo.getVersion())) { |
||||
|
throw new DataValidationException("OtaPackage version should be specified!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private PaginatedRemover<TenantId, OtaPackageInfo> tenantOtaPackageRemover = |
||||
|
new PaginatedRemover<>() { |
||||
|
|
||||
|
@Override |
||||
|
protected PageData<OtaPackageInfo> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) { |
||||
|
return otaPackageInfoDao.findOtaPackageInfoByTenantId(id, pageLink); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void removeEntity(TenantId tenantId, OtaPackageInfo entity) { |
||||
|
deleteOtaPackage(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(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static List<OtaPackageId> toOtaPackageInfoKey(OtaPackageId otaPackageId) { |
||||
|
return Collections.singletonList(otaPackageId); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -1,60 +0,0 @@ |
|||||
/** |
|
||||
* 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.common.data.firmware.FirmwareType; |
|
||||
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.deviceProfileId, f.type, 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.deviceProfileId, f.type, 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.deviceProfileId = :deviceProfileId " + |
|
||||
"AND f.type = :type " + |
|
||||
"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> findAllByTenantIdAndTypeAndDeviceProfileIdAndHasData(@Param("tenantId") UUID tenantId, |
|
||||
@Param("deviceProfileId") UUID deviceProfileId, |
|
||||
@Param("type") FirmwareType type, |
|
||||
@Param("hasData") boolean hasData, |
|
||||
@Param("searchText") String searchText, |
|
||||
Pageable pageable); |
|
||||
|
|
||||
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, 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); |
|
||||
|
|
||||
@Query(value = "SELECT exists(SELECT * " + |
|
||||
"FROM device_profile AS dp " + |
|
||||
"LEFT JOIN device AS d ON dp.id = d.device_profile_id " + |
|
||||
"WHERE dp.id = :deviceProfileId AND " + |
|
||||
"(('FIRMWARE' = :type AND (dp.firmware_id = :firmwareId OR d.firmware_id = :firmwareId)) " + |
|
||||
"OR ('SOFTWARE' = :type AND (dp.software_id = :firmwareId or d.software_id = :firmwareId))))", nativeQuery = true) |
|
||||
boolean isFirmwareUsed(@Param("firmwareId") UUID firmwareId, @Param("deviceProfileId") UUID deviceProfileId, @Param("type") String type); |
|
||||
|
|
||||
} |
|
||||
@ -1,94 +0,0 @@ |
|||||
/** |
|
||||
* 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.firmware.FirmwareType; |
|
||||
import org.thingsboard.server.common.data.id.DeviceProfileId; |
|
||||
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.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> findFirmwareInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink) { |
|
||||
return DaoUtil.toPageData(firmwareInfoRepository |
|
||||
.findAllByTenantIdAndTypeAndDeviceProfileIdAndHasData( |
|
||||
tenantId.getId(), |
|
||||
deviceProfileId.getId(), |
|
||||
firmwareType, |
|
||||
hasData, |
|
||||
Objects.toString(pageLink.getTextSearch(), ""), |
|
||||
DaoUtil.toPageable(pageLink))); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public boolean isFirmwareUsed(FirmwareId firmwareId, FirmwareType type, DeviceProfileId deviceProfileId) { |
|
||||
return firmwareInfoRepository.isFirmwareUsed(firmwareId.getId(), deviceProfileId.getId(), type.name()); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,94 @@ |
|||||
|
/** |
||||
|
* 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.ota; |
||||
|
|
||||
|
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.OtaPackageInfo; |
||||
|
import org.thingsboard.server.common.data.ota.OtaPackageType; |
||||
|
import org.thingsboard.server.common.data.id.DeviceProfileId; |
||||
|
import org.thingsboard.server.common.data.id.OtaPackageId; |
||||
|
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.ota.OtaPackageInfoDao; |
||||
|
import org.thingsboard.server.dao.model.sql.OtaPackageInfoEntity; |
||||
|
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; |
||||
|
|
||||
|
import java.util.Objects; |
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Component |
||||
|
public class JpaOtaPackageInfoDao extends JpaAbstractSearchTextDao<OtaPackageInfoEntity, OtaPackageInfo> implements OtaPackageInfoDao { |
||||
|
|
||||
|
@Autowired |
||||
|
private OtaPackageInfoRepository otaPackageInfoRepository; |
||||
|
|
||||
|
@Override |
||||
|
protected Class<OtaPackageInfoEntity> getEntityClass() { |
||||
|
return OtaPackageInfoEntity.class; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected CrudRepository<OtaPackageInfoEntity, UUID> getCrudRepository() { |
||||
|
return otaPackageInfoRepository; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public OtaPackageInfo findById(TenantId tenantId, UUID id) { |
||||
|
return DaoUtil.getData(otaPackageInfoRepository.findOtaPackageInfoById(id)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public OtaPackageInfo save(TenantId tenantId, OtaPackageInfo otaPackageInfo) { |
||||
|
OtaPackageInfo savedOtaPackage = super.save(tenantId, otaPackageInfo); |
||||
|
if (otaPackageInfo.getId() == null) { |
||||
|
return savedOtaPackage; |
||||
|
} else { |
||||
|
return findById(tenantId, savedOtaPackage.getId().getId()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageData<OtaPackageInfo> findOtaPackageInfoByTenantId(TenantId tenantId, PageLink pageLink) { |
||||
|
return DaoUtil.toPageData(otaPackageInfoRepository |
||||
|
.findAllByTenantId( |
||||
|
tenantId.getId(), |
||||
|
Objects.toString(pageLink.getTextSearch(), ""), |
||||
|
DaoUtil.toPageable(pageLink))); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageData<OtaPackageInfo> findOtaPackageInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType, boolean hasData, PageLink pageLink) { |
||||
|
return DaoUtil.toPageData(otaPackageInfoRepository |
||||
|
.findAllByTenantIdAndTypeAndDeviceProfileIdAndHasData( |
||||
|
tenantId.getId(), |
||||
|
deviceProfileId.getId(), |
||||
|
otaPackageType, |
||||
|
hasData, |
||||
|
Objects.toString(pageLink.getTextSearch(), ""), |
||||
|
DaoUtil.toPageable(pageLink))); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean isOtaPackageUsed(OtaPackageId otaPackageId, OtaPackageType otaPackageType, DeviceProfileId deviceProfileId) { |
||||
|
return otaPackageInfoRepository.isOtaPackageUsed(otaPackageId.getId(), deviceProfileId.getId(), otaPackageType.name()); |
||||
|
} |
||||
|
} |
||||
@ -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.dao.sql.ota; |
||||
|
|
||||
|
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.common.data.ota.OtaPackageType; |
||||
|
import org.thingsboard.server.dao.model.sql.OtaPackageInfoEntity; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
|
||||
|
public interface OtaPackageInfoRepository extends CrudRepository<OtaPackageInfoEntity, UUID> { |
||||
|
@Query("SELECT new OtaPackageInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM OtaPackageEntity f WHERE " + |
||||
|
"f.tenantId = :tenantId " + |
||||
|
"AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") |
||||
|
Page<OtaPackageInfoEntity> findAllByTenantId(@Param("tenantId") UUID tenantId, |
||||
|
@Param("searchText") String searchText, |
||||
|
Pageable pageable); |
||||
|
|
||||
|
@Query("SELECT new OtaPackageInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM OtaPackageEntity f WHERE " + |
||||
|
"f.tenantId = :tenantId " + |
||||
|
"AND f.deviceProfileId = :deviceProfileId " + |
||||
|
"AND f.type = :type " + |
||||
|
"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<OtaPackageInfoEntity> findAllByTenantIdAndTypeAndDeviceProfileIdAndHasData(@Param("tenantId") UUID tenantId, |
||||
|
@Param("deviceProfileId") UUID deviceProfileId, |
||||
|
@Param("type") OtaPackageType type, |
||||
|
@Param("hasData") boolean hasData, |
||||
|
@Param("searchText") String searchText, |
||||
|
Pageable pageable); |
||||
|
|
||||
|
@Query("SELECT new OtaPackageInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM OtaPackageEntity f WHERE f.id = :id") |
||||
|
OtaPackageInfoEntity findOtaPackageInfoById(@Param("id") UUID id); |
||||
|
|
||||
|
@Query(value = "SELECT exists(SELECT * " + |
||||
|
"FROM device_profile AS dp " + |
||||
|
"LEFT JOIN device AS d ON dp.id = d.device_profile_id " + |
||||
|
"WHERE dp.id = :deviceProfileId AND " + |
||||
|
"(('FIRMWARE' = :type AND (dp.firmware_id = :otaPackageId OR d.firmware_id = :otaPackageId)) " + |
||||
|
"OR ('SOFTWARE' = :type AND (dp.software_id = :otaPackageId or d.software_id = :otaPackageId))))", nativeQuery = true) |
||||
|
boolean isOtaPackageUsed(@Param("otaPackageId") UUID otaPackageId, @Param("deviceProfileId") UUID deviceProfileId, @Param("type") String type); |
||||
|
|
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue