Merge remote-tracking branch 'origin/product_refact' into product_refact

This commit is contained in:
xxq250 2025-01-23 16:48:46 +08:00
commit cc679fed0a
19 changed files with 386 additions and 83 deletions

View File

@ -202,7 +202,7 @@ public class CacheConstants {
/**
* Gitlink组织开通企业是否完成 Key前缀
*/
public final static String GITLINK_ORG_ID_OPEN_ENTERPRISE_KEY = "gitlink_org_id_open_enterprise_key:";
private final static String GITLINK_ORG_ID_OPEN_ENTERPRISE_KEY = "gitlink_org_id_open_enterprise_key:";
public static String getGitlinkOrgIdOpenEnterpriseKey(Long gitlinkOrgId) {
return GITLINK_ORG_ID_OPEN_ENTERPRISE_KEY + gitlinkOrgId;
@ -211,11 +211,11 @@ public class CacheConstants {
/**
* 专区项目Gitlink信息 Key前缀
*/
public final static String ZONE_PROJECT_GITLINK_INFO = "zone_project_gitlink_info:";
private final static String ZONE_PROJECT_GITLINK_INFO = "zone_project_gitlink_info:";
/**
* 专区下项目分数排序 Key前缀
*/
public final static String ZONE_PROJECT_SORT_BY_SCORE = "zone_project_sort_by_score:";
private final static String ZONE_PROJECT_SORT_BY_SCORE = "zone_project_sort_by_score:";
public static String getZoneProjectGitlinkInfo(Long gitlinkProjectId) {
return ZONE_PROJECT_GITLINK_INFO + gitlinkProjectId;
@ -228,4 +228,13 @@ public class CacheConstants {
public static String getAllZoneProjectSortByScore(Long zoneId) {
return ZONE_PROJECT_SORT_BY_SCORE + "*:" + zoneId + ":*";
}
/**
* 文件打包是否完成0代表未完成1代表已完成-1代表打包失败需要重新打包
*/
private final static String PACKAGE_FILE_IS_FINISH = "packageFileIsFinish:";
public static String getPackageFileIsFinish(String fileIdentifier) {
return PACKAGE_FILE_IS_FINISH + fileIdentifier;
}
}

View File

@ -218,7 +218,7 @@ public class ServletUtils {
}
/**
* 内容编码(排除斜杠)
* 内容编码(排除斜杠并且不重复编码)
*
* @param str 内容
* @return 编码后的内容
@ -228,7 +228,11 @@ public class ServletUtils {
StringBuilder stringBuffer = new StringBuilder();
String[] strings = str.split("/");
for (String string : strings) {
stringBuffer.append("/").append(URLEncoder.encode(string, Constants.UTF8));
// 如果url已经进行过urlEncode 不重复进行Encode
if (!isUrlEncoded(string)) {
string = URLEncoder.encode(string, Constants.UTF8);
}
stringBuffer.append("/").append(string);
}
return stringBuffer.toString().replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
@ -236,6 +240,42 @@ public class ServletUtils {
}
}
/**
* 内容编码(排除斜杠并且支持重复编码)
*
* @param str 内容
* @return 编码后的内容
*/
public static String urlEncodeExcludeSlashesApplyDuplicate(String str) {
try {
StringBuilder stringBuffer = new StringBuilder();
String[] strings = str.split("/");
for (String string : strings) {
string = URLEncoder.encode(string, Constants.UTF8);
stringBuffer.append("/").append(string);
}
return stringBuffer.toString().replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
return StringUtils.EMPTY;
}
}
/**
* 判断字符串是否经过URLEncode
* 1. 使用URLDecoder.decode对字符串进行解码
* 2. 再使用URLEncoder.encode对解码后的字符串重新编码
* 3. 如果重新编码后的字符串与原始字符串相同则说明原始字符串是经过URL编码的
*
* @param encodedString 需encode的字符串
* @return 是否经过URLEncode
* @throws UnsupportedEncodingException 编码异常
*/
public static boolean isUrlEncoded(String encodedString) throws UnsupportedEncodingException {
String decodedString = URLDecoder.decode(encodedString, "UTF-8");
String reencodedString = URLEncoder.encode(decodedString, "UTF-8");
return encodedString.equalsIgnoreCase(reencodedString);
}
/**
* 内容解码
*

View File

@ -1,9 +1,11 @@
package com.microservices.file.service.impl;
import com.microservices.common.core.constant.CacheConstants;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.ServletUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.common.redis.service.RedisService;
import com.microservices.file.service.ISysFileInfoAsyncService;
import com.microservices.file.service.ISysFileInfoService;
import com.microservices.file.utils.CustomExecutorFactory;
@ -41,6 +43,8 @@ public class SysFileInfoAsyncServiceImpl implements ISysFileInfoAsyncService {
*/
@Value("${file.path}")
private String localFilePath;
@Autowired
private RedisService redisService;
@Override
public void asyncPackagedFile(String fileIdentifier, HashMap<String, String> packagedStructure, String zipFileName, String type, String hierarchy) {
@ -70,6 +74,7 @@ public class SysFileInfoAsyncServiceImpl implements ISysFileInfoAsyncService {
String filePath = localFilePath + fileInfo.getFilePath();
File file = new File(filePath);
if (!file.exists()) {
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), -1);
throw new IOException("该文件不存在");
}
// 拷贝文件到打包目录
@ -82,6 +87,7 @@ public class SysFileInfoAsyncServiceImpl implements ISysFileInfoAsyncService {
org.apache.commons.io.FileUtils.copyURLToFile(new URL(fileSource), packagedFilePath.toFile());
}
} catch (IOException e) {
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), -1);
logger.error("打包文件时出现异常,需压缩文件处理失败:{}", e.getMessage());
throw new ServiceException("打包文件时出现异常,需压缩文件处理失败!");
}
@ -91,7 +97,8 @@ public class SysFileInfoAsyncServiceImpl implements ISysFileInfoAsyncService {
ZipUtils.toZip(tempPackagedPath.toString(), Files.newOutputStream(zipFilePath), true);
File zipFile = zipFilePath.toFile();
if (!zipFile.exists()) {
throw new ServiceException("打包文件时出现异常:文件压缩失败");
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), -1);
throw new ServiceException("打包文件时出现异常:压缩文件不存在");
}
String filePath = EscapeUtil.removeExtraSlashOfUrl("/" + type + "/" + hierarchy + "/" + datePath + "/" + fullZipFileName);
SysFileInfo sysFileInfo = new SysFileInfo(fileIdentifier, zipFile, filePath);
@ -101,9 +108,11 @@ public class SysFileInfoAsyncServiceImpl implements ISysFileInfoAsyncService {
org.apache.commons.io.FileUtils.deleteDirectory(tempPackagedPath.toFile());
}
} catch (IOException e) {
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), -1);
logger.error("打包文件时出现异常:{}", e.getMessage());
throw new ServiceException("打包文件时出现异常!");
}
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), 1);
});
}
}

View File

@ -4,6 +4,7 @@ package com.microservices.file.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import com.microservices.common.core.constant.CacheConstants;
import com.microservices.common.core.constant.Constants;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
@ -14,6 +15,7 @@ import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.common.core.utils.uuid.IdUtils;
import com.microservices.common.httpClient.domain.GitLinkRequestUrl;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.common.redis.service.RedisService;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.file.mapper.SysFileInfoMapper;
import com.microservices.file.service.ISysFileInfoAsyncService;
@ -84,6 +86,8 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
*/
@Value("${file.domain}")
public String domain;
@Autowired
private RedisService redisService;
@Override
public SysFileInfo selectSysFileInfoByFileObjectName(String fileObjectName) {
@ -492,6 +496,7 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
@Override
public String packagedFile(HashMap<String, String> packagedStructure, String zipFileName, String type, String hierarchy) {
String fileIdentifier = genFileIdentifier();
redisService.setCacheObject(CacheConstants.getPackageFileIsFinish(fileIdentifier), 0);
fileInfoAsyncService.asyncPackagedFile(fileIdentifier, packagedStructure, zipFileName, type, hierarchy);
return fileIdentifier;
}

View File

@ -0,0 +1,141 @@
package com.microservices.pms.enums;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import io.swagger.annotations.ApiModel;
import lombok.Getter;
/**
* @author OTTO
*/
@Getter
@ApiModel("产品库制品路径前缀")
public enum ProductLibraryComponentPathEnum {
ALL("_All", "所有"),
SOFTWARE("Software", "软件包"),
DOC("Document", "文档");
private final String key;
private final String name;
ProductLibraryComponentPathEnum(String key, String name) {
this.key = key;
this.name = name;
}
public static ProductLibraryComponentPathEnum getByKey(String key) {
for (ProductLibraryComponentPathEnum typeEnum : ProductLibraryComponentPathEnum.values()) {
if (typeEnum.key.equals(key)) {
return typeEnum;
}
}
throw new ServiceException("该产品库制品路径前缀不存在(产品库制品路径前缀[%s])", key);
}
public static String getSoftwareFixedPath(String directory) {
return EscapeUtil.removeExtraSlashOfUrl(SOFTWARE.key + "/" + directory);
}
public static String getDocFixedPath(String directory) {
return EscapeUtil.removeExtraSlashOfUrl(DOC.key + "/" + directory);
}
public static String getChineseFixedPath(String path) {
if (path.startsWith(SOFTWARE.key)) {
return path.replaceFirst(SOFTWARE.key, SOFTWARE.name);
}
if (path.startsWith(DOC.key)) {
return path.replaceFirst(DOC.key, DOC.name);
}
return path;
}
public static boolean pathIsNeedPackaged(String node, String path) {
if (StringUtils.isNotEmpty(node)) {
if (node.equals(SOFTWARE.key)) {
return path.startsWith(SOFTWARE.key);
}
if (node.equals(DOC.key)) {
return path.startsWith(DOC.key);
}
}
return true;
}
public static String getPackagedFileJson(String node, String packagedFileIdentifiersJson, String fileIdentifier) {
JSONObject packagedFileIdentifiersJsonObj;
if (StringUtils.isNotEmpty(packagedFileIdentifiersJson) && JSON.isValid(packagedFileIdentifiersJson)) {
packagedFileIdentifiersJsonObj = JSONObject.parseObject(packagedFileIdentifiersJson);
} else {
packagedFileIdentifiersJsonObj = new JSONObject();
}
if (StringUtils.isNotEmpty(node)) {
if (SOFTWARE.key.equals(node)) {
packagedFileIdentifiersJsonObj.put(SOFTWARE.key, fileIdentifier);
return packagedFileIdentifiersJsonObj.toJSONString();
}
if (DOC.key.equals(node)) {
packagedFileIdentifiersJsonObj.put(DOC.key, fileIdentifier);
return packagedFileIdentifiersJsonObj.toJSONString();
}
}
packagedFileIdentifiersJsonObj.put(ALL.key, fileIdentifier);
return packagedFileIdentifiersJsonObj.toJSONString();
}
public static String getPackagedFileIdentifierFromJson(String node, JSONObject packagedFileIdentifiersJsonObj) {
if (StringUtils.isNotEmpty(node)) {
if (SOFTWARE.key.equals(node)) {
return packagedFileIdentifiersJsonObj.getString(SOFTWARE.key);
}
if (DOC.key.equals(node)) {
return packagedFileIdentifiersJsonObj.getString(DOC.key);
}
}
return packagedFileIdentifiersJsonObj.getString(ALL.key);
}
public static String getPackagedFileTag(String node) {
if (StringUtils.isNotEmpty(node)) {
if (SOFTWARE.key.equals(node)) {
return "(" + SOFTWARE.name + ")";
}
if (DOC.key.equals(node)) {
return "(" + DOC.name + ")";
}
}
return "";
}
public static String setPackagedFileIdentifierNull(String node, String packagedFileIdentifiersJson) {
JSONObject packagedFileIdentifiersJsonObj;
if (StringUtils.isNotEmpty(packagedFileIdentifiersJson) && JSON.isValid(packagedFileIdentifiersJson)) {
packagedFileIdentifiersJsonObj = JSONObject.parseObject(packagedFileIdentifiersJson);
} else {
packagedFileIdentifiersJsonObj = new JSONObject();
}
if (StringUtils.isNotEmpty(node)) {
if (SOFTWARE.key.equals(node)) {
if (packagedFileIdentifiersJsonObj.containsKey(SOFTWARE.key)) {
packagedFileIdentifiersJsonObj.remove(SOFTWARE.key);
}
return packagedFileIdentifiersJsonObj.toJSONString();
}
if (DOC.key.equals(node)) {
if (packagedFileIdentifiersJsonObj.containsKey(DOC.key)) {
packagedFileIdentifiersJsonObj.remove(DOC.key);
}
return packagedFileIdentifiersJsonObj.toJSONString();
}
}
if (packagedFileIdentifiersJsonObj.containsKey(ALL.key)) {
packagedFileIdentifiersJsonObj.remove(ALL.key);
}
return packagedFileIdentifiersJsonObj.toJSONString();
}
}

View File

@ -0,0 +1,34 @@
package com.microservices.pms.enums;
import com.microservices.common.core.exception.ServiceException;
import io.swagger.annotations.ApiModel;
import lombok.Getter;
/**
* @author OTTO
*/
@Getter
@ApiModel("来源类型")
public enum ProductLibraryRepoFromTypeEnum {
COMMON("common", "普通类型"),
PIPELINE("pipeline", "流水线类型"),
DOC("doc", "文档类型");
private final String key;
private final String name;
ProductLibraryRepoFromTypeEnum(String key, String name) {
this.key = key;
this.name = name;
}
public static ProductLibraryRepoFromTypeEnum getByKey(String key) {
for (ProductLibraryRepoFromTypeEnum typeEnum : ProductLibraryRepoFromTypeEnum.values()) {
if (typeEnum.key.equals(key)) {
return typeEnum;
}
}
throw new ServiceException("该来源类型不存在(来源类型[%s])", key);
}
}

View File

@ -55,7 +55,7 @@ public class PmsProductLibraryController extends BaseController {
@GetMapping("/byRepoName/{repoName}")
@ApiOperation(value = "获取产品库详情")
public GenericsAjaxResult<PmsProductLibraryDataVo> getByRepoName(@PathVariable String enterpriseIdentifier,
@ApiParam(value = "产品库标识", required = true) @PathVariable String repoName) {
@ApiParam(value = "产品库标识", required = true) @PathVariable String repoName) {
return GenericsAjaxResult.success(pmsProductLibraryService.selectPmsProductLibraryDataByName(enterpriseIdentifier, repoName));
}
@ -113,22 +113,6 @@ public class PmsProductLibraryController extends BaseController {
return toAjax(pmsProductLibraryService.deletePmsProductLibraryByName(enterpriseIdentifier, name));
}
/**
* 上传产品库制品
*/
// @RequiresPermissions("pms:pmsProductLibraryComponent:add")
@Log(title = "产品库制品", businessType = BusinessType.INSERT)
@PostMapping("/{name}")
@ApiOperation(value = "上传知识库文档")
public AjaxResult uploadProductAsset(@PathVariable String enterpriseIdentifier,
@ApiParam(value = "产品库标识", required = true) @PathVariable String name,
@Valid @RequestBody ProductComponentInputVo productComponentInputVo) {
productComponentInputVo.setProductRepoName(name);
productComponentInputVo.setEnterpriseIdentifier(enterpriseIdentifier);
return toAjax(pmsProductLibraryService.uploadProductAsset(productComponentInputVo));
}
/**
* 产品库查询制品列表
*/
@ -259,9 +243,9 @@ public class PmsProductLibraryController extends BaseController {
@GetMapping("/{productRepoName}/{repoName}/keyComponent/list")
@ApiOperation(value = "制品库查询关键制品列表")
public GenericsAjaxResult<NexusComponentResultVo<List<NexusResultDataVo>>> keyComponentList(@PathVariable String enterpriseIdentifier,
@ApiParam(value = "产品库标识", required = true) @PathVariable("productRepoName") String productRepoName,
@ApiParam(value = "制品库标识", required = true) @PathVariable("repoName") String repoName,
@Valid ComponentSearchVo componentSearchVo) {
@ApiParam(value = "产品库标识", required = true) @PathVariable("productRepoName") String productRepoName,
@ApiParam(value = "制品库标识", required = true) @PathVariable("repoName") String repoName,
@Valid ComponentSearchVo componentSearchVo) {
componentSearchVo.setRepositoryName(repoName);
componentSearchVo.setProductRepoName(productRepoName);
NexusComponentResultVo<List<NexusResultDataVo>> result =
@ -317,6 +301,21 @@ public class PmsProductLibraryController extends BaseController {
return toAjax(pmsProductLibraryService.addDockerComponentToProductRepo(dockerComponentAddToProductRepoVo));
}
/**
* 上传产品库制品
*/
// @RequiresPermissions("pms:pmsProductLibraryComponent:add")
@Log(title = "产品库制品", businessType = BusinessType.INSERT)
@PostMapping("/{name}")
@ApiOperation(value = "上传知识库文档")
public AjaxResult uploadProductAsset(@PathVariable String enterpriseIdentifier,
@ApiParam(value = "产品库标识", required = true) @PathVariable String name,
@Valid @RequestBody ProductDocComponentInputVo productDocComponentInputVo) {
productDocComponentInputVo.setProductRepoName(name);
productDocComponentInputVo.setEnterpriseIdentifier(enterpriseIdentifier);
return toAjax(pmsProductLibraryService.uploadProductAsset(productDocComponentInputVo));
}
/**
* 产品库打包
*/
@ -325,8 +324,9 @@ public class PmsProductLibraryController extends BaseController {
@PostMapping("/packaged/{productRepoName}")
@ApiOperation(value = "产品库打包")
public AjaxResult packagedProduct(@PathVariable String enterpriseIdentifier,
@ApiParam(value = "产品库标识", required = true) @PathVariable String productRepoName) {
return toAjax(pmsProductLibraryService.packagedProduct(enterpriseIdentifier, productRepoName));
@ApiParam(value = "产品库标识", required = true) @PathVariable String productRepoName,
@ApiParam(value = "打包节点(Software打包软件包Document打包文档不传或传其他值打包所有)") @RequestParam(required = false) String node) {
return toAjax(pmsProductLibraryService.packagedProduct(enterpriseIdentifier, productRepoName, node));
}
/**
@ -336,7 +336,8 @@ public class PmsProductLibraryController extends BaseController {
@GetMapping("/packaged/{productRepoName}")
@ApiOperation(value = "获取产品库打包下载地址")
public GenericsAjaxResult<ProductPackagedResultVo> getPackagedProduct(@PathVariable String enterpriseIdentifier,
@ApiParam(value = "产品库标识", required = true) @PathVariable String productRepoName) {
return genericsSuccess(pmsProductLibraryService.getPackagedProduct(enterpriseIdentifier, productRepoName));
@ApiParam(value = "产品库标识", required = true) @PathVariable String productRepoName,
@ApiParam(value = "打包节点(Software打包软件包Document打包文档不传或传其他值打包所有)") @RequestParam(required = false) String node) {
return pmsProductLibraryService.getPackagedProduct(enterpriseIdentifier, productRepoName, node);
}
}

View File

@ -119,12 +119,8 @@ public class PmsProductLibraryComponent extends BaseEntity {
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String reservedField2;
/**
* 预留字段3
*/
@ApiModelProperty(value = "预留字段3")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String reservedField3;
@ApiModelProperty(value = "来源类型")
private String fromType;
public void setNexusMavenAssetVo(NexusAssetVo nexusAssetVo) {
String composeId = Base64.base64ToDecoderString(nexusAssetVo.getId());

View File

@ -88,8 +88,8 @@ public class PmsProductLibraryRepositories extends BaseEntity {
private String snapshotName;
@ApiModelProperty(value = "打包的文件标识")
private String packagedFileIdentifier;
@ApiModelProperty(value = "打包的文件标识JSON对象")
private String packagedFileIdentifiersJson;
@ApiModelProperty(value = "关联产品标识")

View File

@ -46,6 +46,8 @@ public class ComponentRawInputVo {
@ApiModelProperty(value = "目录:上传文件的目录(例如/path/to/files/")
@NotNull(message = "目录不能为空")
private String directory;
@NotNull(message = "来源类型")
private String fromType = "common";
public String getNexusRepoName() {
if (ProductLibraryRepositoriesFormatEnum.isProduct(format)) {
@ -87,6 +89,7 @@ public class ComponentRawInputVo {
}
}
pmsProductLibraryComponent.setPmsEnterpriseIdentifier(enterpriseIdentifier);
pmsProductLibraryComponent.setFromType(fromType);
return pmsProductLibraryComponent;
}
}

View File

@ -67,4 +67,7 @@ public class PmsProductLibraryComponentDataVo extends BaseEntityVo {
*/
@ApiModelProperty(value = "制品下载地址")
private String downloadUrl;
@ApiModelProperty(value = "来源类型")
private String fromType;
}

View File

@ -1,6 +1,7 @@
package com.microservices.pms.productLibrary.domain.vo;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.pms.enums.ProductLibraryRepoFromTypeEnum;
import com.microservices.pms.productLibrary.domain.ProductLibraryRepositoriesFormatEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -19,8 +20,8 @@ import java.util.List;
* @date 2024-07-04
*/
@Data
@ApiModel("产品制品输入对象")
public class ProductComponentInputVo {
@ApiModel("文档制品输入对象")
public class ProductDocComponentInputVo {
@ApiModelProperty(value = "产品库标识", hidden = true)
private String productRepoName;
@ApiModelProperty(value = "组织标识", hidden = true)
@ -43,6 +44,7 @@ public class ProductComponentInputVo {
BeanUtils.copyProperties(this, target);
target.setRepoName(productRepoName);
target.setAssetList(assetList);
target.setFromType(ProductLibraryRepoFromTypeEnum.DOC.getKey());
return target;
}

View File

@ -139,4 +139,5 @@ public interface PmsProductLibraryRepositoriesMapper {
* @return 制品库
*/
PmsProductLibraryRepositories selectPmsProductLibraryRepositoriesByAlias(@Param("alias") String alias, @Param("pmsEnterpriseIdentifier") String pmsEnterpriseIdentifier);
}

View File

@ -52,6 +52,7 @@ public interface IPmsProductLibraryAsyncService {
* 打包产品库
*
* @param productRepo 产品库
* @param node
*/
void packagedProduct(PmsProductLibraryRepositories productRepo);
void packagedProduct(PmsProductLibraryRepositories productRepo, String node);
}

View File

@ -1,5 +1,6 @@
package com.microservices.pms.productLibrary.service;
import com.microservices.common.core.web.domain.GenericsAjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.pms.productLibrary.domain.PmsProductLibraryRepositories;
import com.microservices.pms.productLibrary.domain.vo.*;
@ -78,7 +79,7 @@ public interface IPmsProductLibraryService {
boolean addDockerComponentToProductRepo(DockerComponentAddToProductRepoVo dockerComponentAddToProductRepoVo);
boolean packagedProduct(String enterpriseIdentifier, String productRepoName);
boolean packagedProduct(String enterpriseIdentifier, String productRepoName, String node);
int updatePmsProductLibrary(PmsProductLibraryRepositories pmsProductLibraryRepositories);
@ -87,17 +88,18 @@ public interface IPmsProductLibraryService {
*
* @param enterpriseIdentifier 企业标识
* @param productRepoName 产品库名称
* @param node
* @return 产品库打包对象
*/
ProductPackagedResultVo getPackagedProduct(String enterpriseIdentifier, String productRepoName);
GenericsAjaxResult<ProductPackagedResultVo> getPackagedProduct(String enterpriseIdentifier, String productRepoName, String node);
/**
* 上传产品库制品
*
* @param productComponentInputVo 产品库制品输入对象
* @param productDocComponentInputVo 产品库制品输入对象
* @return 结果
*/
Boolean uploadProductAsset(ProductComponentInputVo productComponentInputVo);
Boolean uploadProductAsset(ProductDocComponentInputVo productDocComponentInputVo);
GenericsTableDataInfo<DocResultVo> selectDocList(DocSearchVo docSearchVo);
}

View File

@ -5,6 +5,7 @@ import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.ServletUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.pms.enums.ProductLibraryComponentPathEnum;
import com.microservices.pms.productLibrary.domain.PmsProductLibraryComponent;
import com.microservices.pms.productLibrary.domain.PmsProductLibraryRepositories;
import com.microservices.pms.productLibrary.domain.ProductLibraryRepositoriesFormatEnum;
@ -200,7 +201,7 @@ public class PmsProductLibraryAsyncServiceImpl implements IPmsProductLibraryAsyn
}
@Override
public void packagedProduct(PmsProductLibraryRepositories productRepo) {
public void packagedProduct(PmsProductLibraryRepositories productRepo, String node) {
CustomExecutorFactory.threadPoolExecutor.execute(() -> {
pmsProductLibraryRepositoriesService.lockRepository(productRepo.getPmsEnterpriseIdentifier(), productRepo.getId());
try {
@ -208,21 +209,23 @@ public class PmsProductLibraryAsyncServiceImpl implements IPmsProductLibraryAsyn
pmsProductLibraryComponentService.selectPmsProductLibraryComponentListByDatabase(productRepo.getId());
HashMap<String, String> packagedStructure = new HashMap<>();
for (PmsProductLibraryComponent component : componentList) {
String fileSource = component.getFileIdentifier();
if (StringUtils.isEmpty(fileSource)) {
fileSource = EscapeUtil.removeExtraSlashOfUrl(productRepo.getUrl() + "/" + ServletUtils.urlEncodeExcludeSlashes(component.getPath()));
if (ProductLibraryComponentPathEnum.pathIsNeedPackaged(node, component.getPath())) {
String fileSource = component.getFileIdentifier();
if (StringUtils.isEmpty(fileSource)) {
fileSource = EscapeUtil.removeExtraSlashOfUrl(productRepo.getUrl() + "/" + ServletUtils.urlEncodeExcludeSlashesApplyDuplicate(component.getPath()));
}
packagedStructure.put(ProductLibraryComponentPathEnum.getChineseFixedPath(component.getPath()), fileSource);
}
packagedStructure.put(component.getPath(), fileSource);
}
String fileIdentifier = FeignUtils.getReturnData(
remoteFileService.packagedFile(
packagedStructure,
String.format("product-%s-%s", productRepo.getAlias(), DateUtils.dateTimeNow()),
String.format("product-%s-%s%s", productRepo.getAlias(), DateUtils.dateTimeNow(), ProductLibraryComponentPathEnum.getPackagedFileTag(node)),
"pms",
productRepo.getPmsEnterpriseIdentifier() + "/productLibrary",
SecurityConstants.INNER)
);
productRepo.setPackagedFileIdentifier(fileIdentifier);
productRepo.setPackagedFileIdentifiersJson(ProductLibraryComponentPathEnum.getPackagedFileJson(node, productRepo.getPackagedFileIdentifiersJson(), fileIdentifier));
pmsProductLibraryService.updatePmsProductLibrary(productRepo);
} finally {
pmsProductLibraryRepositoriesService.unlockRepository(productRepo.getPmsEnterpriseIdentifier(), productRepo.getId());

View File

@ -1,13 +1,17 @@
package com.microservices.pms.productLibrary.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.constant.CacheConstants;
import com.microservices.common.core.constant.SecurityConstants;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.PageUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.common.core.web.domain.GenericsAjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.redis.service.RedisService;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.pms.common.service.IPmsCommonService;
import com.microservices.pms.document.domain.vo.PmsDocumentDetailVo;
@ -15,6 +19,8 @@ import com.microservices.pms.document.domain.vo.PmsDocumentVo;
import com.microservices.pms.document.service.IPmsDocumentService;
import com.microservices.pms.enterprise.domain.PmsEnterprise;
import com.microservices.pms.enterprise.service.IPmsEnterpriseService;
import com.microservices.pms.enums.ProductLibraryComponentPathEnum;
import com.microservices.pms.enums.ProductLibraryRepoFromTypeEnum;
import com.microservices.pms.product.domain.PmsProduct;
import com.microservices.pms.product.service.IPmsProductService;
import com.microservices.pms.productLibrary.domain.PmsProductLibraryComponent;
@ -81,6 +87,8 @@ public class PmsProductLibraryServiceImpl implements IPmsProductLibraryService {
private IPmsCommonService pmsCommonService;
@Autowired
private IPmsProductService pmsProductService;
@Autowired
private RedisService redisService;
@Override
public GenericsTableDataInfo<PmsProductLibraryComponentDataVo> selectComponentList(PmsProductLibraryComponentSearchVo search) {
@ -106,6 +114,9 @@ public class PmsProductLibraryServiceImpl implements IPmsProductLibraryService {
EscapeUtil.removeExtraSlashOfUrl(
String.format("%s/%s", repo.getUrl(), component.getPath()))));
pmsCommonService.setBaseEntityVo(pmsProductLibraryComponentDataVo, component);
pmsProductLibraryComponentDataVo.setFromType(
ProductLibraryRepoFromTypeEnum.getByKey(component.getFromType()).getName()
);
return pmsProductLibraryComponentDataVo;
}
@ -178,37 +189,69 @@ public class PmsProductLibraryServiceImpl implements IPmsProductLibraryService {
}
@Override
public ProductPackagedResultVo getPackagedProduct(String enterpriseIdentifier, String productRepoName) {
public GenericsAjaxResult<ProductPackagedResultVo> getPackagedProduct(String enterpriseIdentifier, String productRepoName, String node) {
ProductPackagedResultVo productPackagedResultVo = new ProductPackagedResultVo();
PmsProductLibraryRepositories productLibraryRepositories = selectPmsProductLibraryByName(enterpriseIdentifier, productRepoName);
String packagedFileIdentifier = productLibraryRepositories.getPackagedFileIdentifier();
String packagedFileIdentifiersJson = productLibraryRepositories.getPackagedFileIdentifiersJson();
if (StringUtils.isEmpty(packagedFileIdentifiersJson) || !JSON.isValid(packagedFileIdentifiersJson)) {
productPackagedResultVo.setIsPackaged(false);
return GenericsAjaxResult.success(productPackagedResultVo);
}
JSONObject packagedFileIdentifiersJsonObj = JSONObject.parseObject(packagedFileIdentifiersJson);
String packagedFileIdentifier = ProductLibraryComponentPathEnum.getPackagedFileIdentifierFromJson(node, packagedFileIdentifiersJsonObj);
if (StringUtils.isEmpty(packagedFileIdentifier)) {
productPackagedResultVo.setIsPackaged(false);
} else {
productPackagedResultVo.setIsPackaged(true);
return GenericsAjaxResult.success(productPackagedResultVo);
}
productPackagedResultVo.setIsPackaged(true);
Integer isFinish = redisService.getCacheObject(CacheConstants.getPackageFileIsFinish(packagedFileIdentifier));
if (isFinish != null) {
redisService.deleteObject(CacheConstants.getPackageFileIsFinish(packagedFileIdentifier));
}
// 键值不存在或键值为1,代表打包成功通过远程接口获取文件信息
if (isFinish == null || isFinish == 1) {
SysFileInfo sysFileInfo = null;
try {
SysFileInfo sysFileInfo = FeignUtils.getReturnData(
sysFileInfo = FeignUtils.getReturnData(
remoteFileService.getFileByFileIdentifier(packagedFileIdentifier, SecurityConstants.INNER)
);
if (sysFileInfo != null) {
productPackagedResultVo.setDownloadUrl(sysFileInfo.getDownloadUrl());
productPackagedResultVo.setFileName(sysFileInfo.getFileOriginName());
}
} catch (Exception e) {
log.error("获取产品库打包文件失败:{}", e.getMessage());
} catch (ServiceException e) {
log.error("获取打包文件失败:{}", e.getMessage());
return packageError(node, productLibraryRepositories, productPackagedResultVo);
}
if (sysFileInfo != null) {
productPackagedResultVo.setDownloadUrl(sysFileInfo.getDownloadUrl());
productPackagedResultVo.setFileName(sysFileInfo.getFileOriginName());
}
} else if (isFinish == -1) {
// 键值为-1,代表打包失败需要重新打包
return packageError(node, productLibraryRepositories, productPackagedResultVo);
}
return productPackagedResultVo;
return GenericsAjaxResult.success(productPackagedResultVo);
}
private GenericsAjaxResult<ProductPackagedResultVo> packageError(String node, PmsProductLibraryRepositories productLibraryRepositories, ProductPackagedResultVo productPackagedResultVo) {
productLibraryRepositories.setPackagedFileIdentifiersJson(
ProductLibraryComponentPathEnum.setPackagedFileIdentifierNull(node, productLibraryRepositories.getPackagedFileIdentifiersJson())
);
updatePmsProductLibrary(productLibraryRepositories);
productPackagedResultVo.setIsPackaged(false);
return GenericsAjaxResult.error("打包失败,请重新打包!", productPackagedResultVo);
}
@Override
public Boolean uploadProductAsset(ProductComponentInputVo productComponentInputVo) {
public Boolean uploadProductAsset(ProductDocComponentInputVo productDocComponentInputVo) {
PmsProductLibraryRepositories repo =
selectPmsProductLibraryByName(productComponentInputVo.getEnterpriseIdentifier(), productComponentInputVo.getProductRepoName());
selectPmsProductLibraryByName(productDocComponentInputVo.getEnterpriseIdentifier(), productDocComponentInputVo.getProductRepoName());
// 产品库制品添加默认前缀
productDocComponentInputVo.setDirectory(ProductLibraryComponentPathEnum.getDocFixedPath(
productDocComponentInputVo.getDirectory()
));
List<AssetRawInputVo> assetList = new ArrayList<>();
PmsEnterprise pmsEnterprise = pmsEnterpriseService.selectPmsEnterpriseByIdentifier(productComponentInputVo.getEnterpriseIdentifier());
for (Long docId : productComponentInputVo.getDocList()) {
PmsEnterprise pmsEnterprise = pmsEnterpriseService.selectPmsEnterpriseByIdentifier(productDocComponentInputVo.getEnterpriseIdentifier());
for (Long docId : productDocComponentInputVo.getDocList()) {
PmsDocumentDetailVo pmsDocument = pmsDocumentService.selectPmsDocumentDetailVoByIdAndEnterpriseId(docId, pmsEnterprise.getId());
if (!Objects.equals(pmsDocument.getDocType(), 2) && !Objects.equals(pmsDocument.getDocType(), 3)) {
throw new ServiceException("产品库文档类型仅允许为文档类型或附件类型(文档Id[%s])", pmsDocument.getId());
@ -251,7 +294,7 @@ public class PmsProductLibraryServiceImpl implements IPmsProductLibraryService {
assetList.add(assetRawInputVo);
}
return pmsProductLibraryComponentService.insertRawComponent(productComponentInputVo.toComponentRawInputVo(assetList));
return pmsProductLibraryComponentService.insertRawComponent(productDocComponentInputVo.toComponentRawInputVo(assetList));
}
@Override
@ -338,6 +381,10 @@ public class PmsProductLibraryServiceImpl implements IPmsProductLibraryService {
if (ProductLibraryRepositoriesFormatEnum.DOCKER.getKey().equals(repo.getFormat())) {
throw new ServiceException("Docker制品移入不能使用该接口");
}
// 产品库制品添加默认前缀
commonAssetAddToProductRepoVo.setDirectory(ProductLibraryComponentPathEnum.getSoftwareFixedPath(
commonAssetAddToProductRepoVo.getDirectory()
));
List<NexusAssetResultDataVo> nexusAssetResultDataVoList = new ArrayList<>();
for (String assetId : commonAssetAddToProductRepoVo.getAssetIdList()) {
NexusComponentResultVo<NexusAssetResultDataVo> nexusAssetResultVo = pmsProductLibraryComponentService.getAssetDetailByAssetId(commonAssetAddToProductRepoVo.getEnterpriseIdentifier(), commonAssetAddToProductRepoVo.getRepoName(), null, assetId, false);
@ -434,6 +481,10 @@ public class PmsProductLibraryServiceImpl implements IPmsProductLibraryService {
if (!ProductLibraryRepositoriesFormatEnum.DOCKER.getKey().equals(repo.getFormat())) {
throw new ServiceException("当前接口仅允许进行Docker移入产品库操作");
}
// 产品库制品添加默认前缀
dockerComponentAddToProductRepoVo.setDirectory(ProductLibraryComponentPathEnum.getSoftwareFixedPath(
dockerComponentAddToProductRepoVo.getDirectory()
));
List<NexusComponentResultDataVo> nexusComponentResultDataVoList = new ArrayList<>();
for (String componentId : dockerComponentAddToProductRepoVo.getComponentIdList()) {
NexusComponentResultVo<NexusComponentResultDataVo> nexusAssetResultVo = pmsProductLibraryComponentService.getComponentDetailByComponentId(dockerComponentAddToProductRepoVo.getEnterpriseIdentifier(), dockerComponentAddToProductRepoVo.getRepoName(), null, componentId, false);
@ -496,9 +547,9 @@ public class PmsProductLibraryServiceImpl implements IPmsProductLibraryService {
@Override
public boolean packagedProduct(String enterpriseIdentifier, String productRepoName) {
public boolean packagedProduct(String enterpriseIdentifier, String productRepoName, String node) {
PmsProductLibraryRepositories productRepo = selectPmsProductLibraryByName(enterpriseIdentifier, productRepoName);
pmsProductLibraryAsyncService.packagedProduct(productRepo);
pmsProductLibraryAsyncService.packagedProduct(productRepo, node);
return true;
}
}

View File

@ -23,7 +23,7 @@
<result property="attributes" column="attributes"/>
<result property="reservedField1" column="reserved_field_1"/>
<result property="reservedField2" column="reserved_field_2"/>
<result property="reservedField3" column="reserved_field_3"/>
<result property="fromType" column="from_type"/>
</resultMap>
<sql id="selectPmsProductLibraryComponentVo">
@ -45,7 +45,7 @@
attributes,
reserved_field_1,
reserved_field_2,
reserved_field_3
from_type
from pms_product_library_component
</sql>
@ -68,7 +68,7 @@
pplc.attributes,
pplc.reserved_field_1,
pplc.reserved_field_2,
pplc.reserved_field_3,
pplc.from_type,
pe.enterprise_identifier,
pplr.format
from pms_product_library_component as pplc
@ -92,7 +92,7 @@
<if test="attributes != null and attributes != ''">and attributes = #{attributes}</if>
<if test="reservedField1 != null and reservedField1 != ''">and reserved_field_1 = #{reservedField1}</if>
<if test="reservedField2 != null and reservedField2 != ''">and reserved_field_2 = #{reservedField2}</if>
<if test="reservedField3 != null and reservedField3 != ''">and reserved_field_3 = #{reservedField3}</if>
<if test="fromType != null and fromType != ''">and from_type = #{fromType}</if>
</where>
</select>
@ -164,7 +164,7 @@
<if test="attributes != null">attributes,</if>
<if test="reservedField1 != null">reserved_field_1,</if>
<if test="reservedField2 != null">reserved_field_2,</if>
<if test="reservedField3 != null">reserved_field_3,</if>
<if test="fromType != null">from_type,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="identifier != null and identifier != ''">#{identifier},</if>
@ -184,7 +184,7 @@
<if test="attributes != null">#{attributes},</if>
<if test="reservedField1 != null">#{reservedField1},</if>
<if test="reservedField2 != null">#{reservedField2},</if>
<if test="reservedField3 != null">#{reservedField3},</if>
<if test="fromType != null">#{fromType},</if>
</trim>
</insert>
@ -208,7 +208,7 @@
<if test="attributes != null">attributes = #{attributes},</if>
<if test="reservedField1 != null">reserved_field_1 = #{reservedField1},</if>
<if test="reservedField2 != null">reserved_field_2 = #{reservedField2},</if>
<if test="reservedField3 != null">reserved_field_3 = #{reservedField3},</if>
<if test="fromType != null">from_type = #{fromType},</if>
</trim>
where id = #{id}
</update>

View File

@ -21,7 +21,7 @@
<result property="snapshotName" column="snapshot_name"/>
<result property="format" column="format"/>
<result property="pmsEnterpriseIdentifier" column="enterprise_identifier"/>
<result property="packagedFileIdentifier" column="packaged_file_identifier"/>
<result property="packagedFileIdentifiersJson" column="packaged_file_identifiers_json"/>
<result property="productIdentifier" column="product_identifier"/>
<result property="version" column="version"/>
<result property="tag" column="tag"/>
@ -43,7 +43,7 @@
pplr.alias,
pplr.snapshot_name,
pplr.format,
pplr.packaged_file_identifier,
pplr.packaged_file_identifiers_json,
pplr.product_identifier,
pplr.version,
pplr.tag,
@ -187,7 +187,7 @@
<if test="attributes != null">attributes,</if>
<if test="alias != null">alias,</if>
<if test="snapshotName != null">snapshot_name,</if>
<if test="packagedFileIdentifier != null">packaged_file_identifier,</if>
<if test="packagedFileIdentifiersJson != null">packaged_file_identifiers_json,</if>
<if test="format != null">format,</if>
<if test="productIdentifier != null">product_identifier,</if>
<if test="version != null">version,</if>
@ -207,7 +207,7 @@
<if test="attributes != null">#{attributes},</if>
<if test="alias != null">#{alias},</if>
<if test="snapshotName != null">#{snapshotName},</if>
<if test="packagedFileIdentifier != null">#{packagedFileIdentifier},</if>
<if test="packagedFileIdentifiersJson != null">#{packagedFileIdentifiersJson},</if>
<if test="format != null">#{format},</if>
<if test="productIdentifier != null">#{productIdentifier},</if>
<if test="version != null">#{version},</if>
@ -231,7 +231,9 @@
<if test="attributes != null">attributes = #{attributes},</if>
<if test="alias != null">alias = #{alias},</if>
<if test="snapshotName != null">snapshot_name = #{snapshotName},</if>
<if test="packagedFileIdentifier != null">packaged_file_identifier = #{packagedFileIdentifier},</if>
<if test="packagedFileIdentifiersJson != null">packaged_file_identifiers_json =
#{packagedFileIdentifiersJson},
</if>
<if test="format != null">format = #{format},</if>
<if test="productIdentifier != null">product_identifier = #{productIdentifier},</if>
<if test="version != null">version = #{version},</if>