Browse Source

Merge branch 'feature/image-resources' of github.com:thingsboard/thingsboard into feature/image-resources

pull/9542/head
Igor Kulikov 3 years ago
parent
commit
410cfa2fc9
  1. 7
      application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ResourceMsgConstructor.java
  2. 3
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/resource/BaseResourceProcessor.java
  3. 35
      application/src/main/java/org/thingsboard/server/service/install/update/ImagesUpdater.java
  4. 4
      common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ImageService.java
  5. 2
      common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java
  6. 8
      common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java
  7. 2
      common/edge-api/src/main/proto/edge.proto
  8. 14
      dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java
  9. 6
      dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java

7
application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ResourceMsgConstructor.java

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.service.edge.rpc.constructor; package org.thingsboard.server.service.edge.rpc.constructor;
import com.google.protobuf.ByteString;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.id.TbResourceId; import org.thingsboard.server.common.data.id.TbResourceId;
@ -42,6 +43,12 @@ public class ResourceMsgConstructor {
if (tbResource.getEtag() != null) { if (tbResource.getEtag() != null) {
builder.setEtag(tbResource.getEtag()); builder.setEtag(tbResource.getEtag());
} }
if (tbResource.getDescriptor() != null) {
builder.setDescriptorJson(tbResource.getDescriptor().toString());
}
if (tbResource.getPreview() != null) {
builder.setPreview(ByteString.copyFrom(tbResource.getPreview()));
}
if (tbResource.getTenantId().equals(TenantId.SYS_TENANT_ID)) { if (tbResource.getTenantId().equals(TenantId.SYS_TENANT_ID)) {
builder.setIsSystem(true); builder.setIsSystem(true);
} }

3
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/resource/BaseResourceProcessor.java

@ -17,6 +17,7 @@ package org.thingsboard.server.service.edge.rpc.processor.resource;
import com.datastax.oss.driver.api.core.uuid.Uuids; import com.datastax.oss.driver.api.core.uuid.Uuids;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.ResourceType; import org.thingsboard.server.common.data.ResourceType;
import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.TbResource;
@ -61,7 +62,9 @@ public abstract class BaseResourceProcessor extends BaseEdgeProcessor {
resource.setResourceKey(resourceKey); resource.setResourceKey(resourceKey);
resource.setResourceType(resourceType); resource.setResourceType(resourceType);
resource.setFileName(resourceUpdateMsg.getFileName()); resource.setFileName(resourceUpdateMsg.getFileName());
resource.setDescriptor(resourceUpdateMsg.hasDescriptorJson() ? JacksonUtil.toJsonNode(resourceUpdateMsg.getDescriptorJson()) : null);
resource.setEncodedData(resourceUpdateMsg.hasData() ? resourceUpdateMsg.getData() : null); resource.setEncodedData(resourceUpdateMsg.hasData() ? resourceUpdateMsg.getData() : null);
resource.setPreview(resourceUpdateMsg.hasPreview() ? resourceUpdateMsg.getPreview().toByteArray() : null);
resource.setEtag(resourceUpdateMsg.hasEtag() ? resourceUpdateMsg.getEtag() : null); resource.setEtag(resourceUpdateMsg.hasEtag() ? resourceUpdateMsg.getEtag() : null);
resourceValidator.validate(resource, TbResourceInfo::getTenantId); resourceValidator.validate(resource, TbResourceInfo::getTenantId);
if (created) { if (created) {

35
application/src/main/java/org/thingsboard/server/service/install/update/ImagesUpdater.java

@ -30,14 +30,15 @@ import org.thingsboard.server.common.data.ResourceType;
import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TbResourceInfo; import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.util.ImageUtils;
import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.resource.ImageService; import org.thingsboard.server.dao.resource.ImageService;
import org.thingsboard.server.dao.util.ImageUtils;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Base64; import java.util.Base64;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -58,10 +59,10 @@ public class ImagesUpdater {
@SneakyThrows @SneakyThrows
public void updateSystemImage(Path imageFile, Map<String, String> imageNames) { public void updateSystemImage(Path imageFile, Map<String, String> imageNames) {
String imageKey = imageFile.getFileName().toString(); String imageKey = imageFile.getFileName().toString(); // TODO: add subdir to image key
String imageName = imageNames.get(imageKey); String imageName = imageNames.get(imageKey);
if (imageName == null) { if (imageName == null) {
throw new IllegalArgumentException("Image name is missing for " + imageKey + ". Please add it to names.json file"); imageName = imageKey;
} }
byte[] imageData = Files.readAllBytes(imageFile); byte[] imageData = Files.readAllBytes(imageFile);
String mediaType = ImageUtils.fileExtensionToMediaType("image", StringUtils.substringAfterLast(imageKey, ".")); String mediaType = ImageUtils.fileExtensionToMediaType("image", StringUtils.substringAfterLast(imageKey, "."));
@ -203,17 +204,19 @@ public class ImagesUpdater {
String existingImageQuery) { String existingImageQuery) {
TbResourceInfo imageInfo = imageService.getImageInfoByTenantIdAndKey(tenantId, key); TbResourceInfo imageInfo = imageService.getImageInfoByTenantIdAndKey(tenantId, key);
if (imageInfo == null && !tenantId.isSysTenantId() && existingImageQuery != null) { if (imageInfo == null && !tenantId.isSysTenantId() && existingImageQuery != null) {
// TODO: need to search among tenant images too (custom widgets) List<TbResourceInfo> similarImages = imageService.findSimilarImagesByTenantIdAndKeyStartingWith(TenantId.SYS_TENANT_ID, imageData, existingImageQuery);
// List<TbResourceInfo> existingSystemImages = imageService.findByTenantIdAndDataAndKeyStartingWith(TenantId.SYS_TENANT_ID, imageData, existingImageQuery); if (similarImages.isEmpty()) {
// if (!existingSystemImages.isEmpty()) { similarImages = imageService.findSimilarImagesByTenantIdAndKeyStartingWith(tenantId, imageData, existingImageQuery);
// imageInfo = existingSystemImages.get(0); }
// if (existingSystemImages.size() > 1) { if (!similarImages.isEmpty()) {
// log.warn("Found more than one system image resources for key {}", existingImageQuery); imageInfo = similarImages.get(0);
// } if (similarImages.size() > 1) {
// String link = imageService.getImageLink(imageInfo); log.debug("Found more than one image resources for key {}: {}", existingImageQuery, similarImages);
// log.info("Using system image {} for {}", link, key); }
// return link; String link = imageInfo.getLink();
// } log.info("[{}] Using image {} for {}", tenantId, link, key);
return link;
}
} }
TbResource image; TbResource image;
if (imageInfo == null) { if (imageInfo == null) {
@ -224,7 +227,7 @@ public class ImagesUpdater {
} else if (tenantId.isSysTenantId()) { } else if (tenantId.isSysTenantId()) {
image = new TbResource(imageInfo); image = new TbResource(imageInfo);
} else { } else {
return imageService.getImageLink(imageInfo); return imageInfo.getLink();
} }
image.setTitle(name); image.setTitle(name);
image.setFileName(key); image.setFileName(key);
@ -235,7 +238,7 @@ public class ImagesUpdater {
TbResourceInfo savedImage = imageService.saveImage(image); TbResourceInfo savedImage = imageService.saveImage(image);
log.info("[{}] {} image '{}' ({})", tenantId, imageInfo == null ? "Created" : "Updated", log.info("[{}] {} image '{}' ({})", tenantId, imageInfo == null ? "Created" : "Updated",
image.getTitle(), image.getResourceKey()); image.getTitle(), image.getResourceKey());
return imageService.getImageLink(savedImage); return savedImage.getLink();
} }
private String getText(JsonNode jsonNode, String field) { private String getText(JsonNode jsonNode, String field) {

4
common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ImageService.java

@ -22,6 +22,8 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import java.util.List;
public interface ImageService { public interface ImageService {
TbResourceInfo saveImage(TbResource image) throws Exception; TbResourceInfo saveImage(TbResource image) throws Exception;
@ -40,6 +42,6 @@ public interface ImageService {
void deleteImage(TenantId tenantId, TbResourceId imageId); void deleteImage(TenantId tenantId, TbResourceId imageId);
String getImageLink(TbResourceInfo imageInfo); List<TbResourceInfo> findSimilarImagesByTenantIdAndKeyStartingWith(TenantId tenantId, byte[] data, String imageKeyStartingWith);
} }

2
common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java

@ -60,6 +60,4 @@ public interface ResourceService extends EntityDaoService {
long sumDataSizeByTenantId(TenantId tenantId); long sumDataSizeByTenantId(TenantId tenantId);
List<TbResourceInfo> findByTenantIdAndDataAndKeyStartingWith(TenantId tenantId, byte[] data, String query);
} }

8
common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java

@ -106,6 +106,14 @@ public class TbResourceInfo extends BaseData<TbResourceId> implements HasName, H
return title; return title;
} }
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getLink() {
if (resourceType == ResourceType.IMAGE) {
return "/api/images/" + (tenantId.isSysTenantId() ? "system" : "tenant") + "/" + resourceKey;
}
return null;
}
@JsonIgnore @JsonIgnore
public String getSearchText() { public String getSearchText() {
return searchText != null ? searchText : title; return searchText != null ? searchText : title;

2
common/edge-api/src/main/proto/edge.proto

@ -436,6 +436,8 @@ message ResourceUpdateMsg {
optional string data = 8; optional string data = 8;
optional string etag = 9; optional string etag = 9;
bool isSystem = 10; bool isSystem = 10;
optional string descriptorJson = 11;
optional bytes preview = 12;
} }
message RuleChainMetadataRequestMsg { message RuleChainMetadataRequestMsg {

14
dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java

@ -20,7 +20,6 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.common.util.RegexUtils; import org.thingsboard.common.util.RegexUtils;
import org.thingsboard.server.common.data.ImageDescriptor; import org.thingsboard.server.common.data.ImageDescriptor;
import org.thingsboard.server.common.data.ResourceType; import org.thingsboard.server.common.data.ResourceType;
@ -35,6 +34,7 @@ import org.thingsboard.server.dao.service.validator.ResourceDataValidator;
import org.thingsboard.server.dao.util.ImageUtils; import org.thingsboard.server.dao.util.ImageUtils;
import org.thingsboard.server.dao.util.ImageUtils.ProcessedImage; import org.thingsboard.server.dao.util.ImageUtils.ProcessedImage;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -152,15 +152,9 @@ public class BaseImageService extends BaseResourceService implements ImageServic
} }
@Override @Override
public String getImageLink(TbResourceInfo imageInfo) { public List<TbResourceInfo> findSimilarImagesByTenantIdAndKeyStartingWith(TenantId tenantId, byte[] data, String imageKeyStartingWith) {
String link = "/api/images/"; String etag = calculateEtag(data);
if (imageInfo.getTenantId().isSysTenantId()) { return resourceInfoDao.findByTenantIdAndEtagAndKeyStartingWith(tenantId, etag, imageKeyStartingWith);
link += "system/";
} else {
link += "tenant/";
}
link += imageInfo.getResourceKey();
return link;
} }
} }

6
dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java

@ -216,12 +216,6 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
return resourceDao.sumDataSizeByTenantId(tenantId); return resourceDao.sumDataSizeByTenantId(tenantId);
} }
@Override
public List<TbResourceInfo> findByTenantIdAndDataAndKeyStartingWith(TenantId tenantId, byte[] data, String query) {
String etag = calculateEtag(data);
return resourceInfoDao.findByTenantIdAndEtagAndKeyStartingWith(tenantId, etag, query);
}
protected String calculateEtag(byte[] data) { protected String calculateEtag(byte[] data) {
return Hashing.sha256().hashBytes(data).toString(); return Hashing.sha256().hashBytes(data).toString();
} }

Loading…
Cancel
Save