committed by
GitHub
137 changed files with 2466 additions and 2361 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