From a82313d17b2b5d1c02e880122efc1b701c401dcf Mon Sep 17 00:00:00 2001 From: houzhongjian <houzhongyi@126.com> Date: 星期三, 04 十二月 2024 09:58:58 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/service/impl/MpkFileServiceImpl.java | 558 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 443 insertions(+), 115 deletions(-) diff --git a/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/service/impl/MpkFileServiceImpl.java b/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/service/impl/MpkFileServiceImpl.java index b167e85..8560966 100644 --- a/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/service/impl/MpkFileServiceImpl.java +++ b/iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/service/impl/MpkFileServiceImpl.java @@ -8,38 +8,42 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.iailab.framework.common.page.PageData; +import com.iailab.framework.common.pojo.CommonResult; import com.iailab.framework.common.service.impl.BaseServiceImpl; import com.iailab.framework.common.util.date.DateUtils; import com.iailab.framework.common.util.object.ConvertUtils; import com.iailab.framework.security.core.util.SecurityFrameworkUtils; +import com.iailab.framework.tenant.core.context.TenantContextHolder; import com.iailab.module.infra.api.config.ConfigApi; import com.iailab.module.model.mpk.common.MdkConstant; +import com.iailab.module.model.mpk.common.utils.DllUtils; import com.iailab.module.model.mpk.common.utils.GenUtils; import com.iailab.module.model.mpk.dao.MpkFileDao; -import com.iailab.module.model.mpk.dto.*; -import com.iailab.module.model.mpk.entity.*; +import com.iailab.module.model.mpk.dto.GeneratorCodeHistoryDTO; +import com.iailab.module.model.mpk.dto.MethodSettingDTO; +import com.iailab.module.model.mpk.dto.ModelMethodDTO; +import com.iailab.module.model.mpk.dto.MpkFileDTO; +import com.iailab.module.model.mpk.entity.GeneratorCodeHistoryEntity; +import com.iailab.module.model.mpk.entity.MpkFileEntity; +import com.iailab.module.model.mpk.entity.ProjectPackageHistoryEntity; +import com.iailab.module.model.mpk.entity.ProjectPackageHistoryModelEntity; import com.iailab.module.model.mpk.service.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; +import java.net.URLClassLoader; import java.nio.file.Files; import java.util.*; import java.util.stream.Collectors; -import java.util.zip.ZipOutputStream; /** * @author PanZhibao @@ -65,13 +69,11 @@ @Autowired private ConfigApi configApi; - @Value("${mpk.bakFilePath}") + @Value("${mpk.bak-file-path}") private String mpkBakFilePath; - /*@PostConstruct - public void init() { - mpkBakFilePath = configApi.getConfigValueByKey("mpkBakFilePath").getCheckedData(); - }*/ + @Value("${mpk.bak-resources}") + private String mpkResources; @Override public PageData<MpkFileDTO> page(Map<String, Object> params) { @@ -97,7 +99,7 @@ String label = (String) params.get("label"); QueryWrapper<MpkFileEntity> wrapper = new QueryWrapper<>(); - wrapper.like(StringUtils.isNotBlank(pyName), "py_name", pyName) + wrapper.like(StringUtils.isNotBlank(pyName), "py_chinese_name", pyName) .eq(StringUtils.isNotBlank(pyType), "py_type", pyType) .like(StringUtils.isNotBlank(remark), "remark", remark); @@ -122,15 +124,81 @@ public void save(MpkFileDTO dto) { MpkFileEntity entity = ConvertUtils.sourceToTarget(dto, MpkFileEntity.class); entity.setId(UUID.randomUUID().toString()); + entity.setPkgName(dto.getPkgName().trim()); + entity.setFilePath(dto.getFilePath().trim()); entity.setCreator(SecurityFrameworkUtils.getLoginUserId()); entity.setCreateDate(new Date()); insert(entity); + + // 将备份的pyd文件,转移到MDK_PKGS环境变量下,并添加方法的默认参数(pyFile,模型路径) + String mdkPkgs = System.getenv("MDK_PKGS"); + String fileName = entity.getFilePath().substring(entity.getFilePath().lastIndexOf("\\") + 1,entity.getFilePath().lastIndexOf(".pyd")); + + String pyFilePath = mdkPkgs + File.separator + entity.getPyModule().replace(".", File.separator) + File.separator + fileName + ".pyd"; + FileUtil.mkParentDirs(pyFilePath); + FileUtil.copy(entity.getFilePath(), pyFilePath, true); + + // 添加参数 + for (ModelMethodDTO method : dto.getModelMethods()) { + List<MethodSettingDTO> methodSettings = method.getMethodSettings(); + if (methodSettings.stream().anyMatch(e -> e.getSettingKey().equals(MdkConstant.PY_FILE_KEY))) { + methodSettings.forEach(e -> { + if (e.getSettingKey().equals(MdkConstant.PY_FILE_KEY)) { + e.setValue(entity.getPyModule() + "." + fileName); + } + }); + }else { + MethodSettingDTO setting = new MethodSettingDTO(); + setting.setId(UUID.randomUUID().toString()); + setting.setMethodId(method.getId()); + setting.setSettingKey(MdkConstant.PY_FILE_KEY); + setting.setValue(entity.getPyModule() + "." + fileName); + setting.setName("模型路径"); + setting.setType("input"); + setting.setValueType("string"); + methodSettings.add(setting); + } + } + modelMethodService.insertList(dto.getModelMethods(), entity.getId()); } @Override @DSTransactional(rollbackFor = Exception.class) public void update(MpkFileDTO dto) { + // 添加方法的默认参数(pyFile,模型路径) + String mdkPkgs = System.getenv("MDK_PKGS"); + String fileName = dto.getFilePath().substring(dto.getFilePath().lastIndexOf("\\") + 1,dto.getFilePath().lastIndexOf(".pyd")); + String pyFilePath = mdkPkgs + File.separator + dto.getPyModule().replace(".", File.separator) + File.separator + fileName + ".pyd"; + // 判断文件是否存在,不存在的话将备份的pyd文件,转移到MDK_PKGS环境变量下 + File pyFile = new File(pyFilePath); + if (!pyFile.exists()) { + FileUtil.mkParentDirs(pyFilePath); + FileUtil.copy(dto.getFilePath(), pyFilePath, true); + } + + // 添加/修改参数 + for (ModelMethodDTO method : dto.getModelMethods()) { + List<MethodSettingDTO> methodSettings = method.getMethodSettings(); + if (methodSettings.stream().anyMatch(e -> e.getSettingKey().equals(MdkConstant.PY_FILE_KEY))) { + methodSettings.forEach(e -> { + if (e.getSettingKey().equals(MdkConstant.PY_FILE_KEY)) { + e.setValue(dto.getPyModule() + "." + fileName); + } + }); + }else { + MethodSettingDTO setting = new MethodSettingDTO(); + setting.setId(UUID.randomUUID().toString()); + setting.setMethodId(method.getId()); + setting.setSettingKey(MdkConstant.PY_FILE_KEY); + setting.setValue(dto.getPyModule() + "." + fileName); + setting.setName("模型路径"); + setting.setType("input"); + setting.setValueType("string"); + methodSettings.add(setting); + } + } + MpkFileEntity entity = ConvertUtils.sourceToTarget(dto, MpkFileEntity.class); entity.setUpdater(SecurityFrameworkUtils.getLoginUserId()); entity.setUpdateDate(new Date()); @@ -171,62 +239,146 @@ @Override public byte[] generatorCode(String id, String remark, String zipFileName) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - ZipOutputStream zip = new ZipOutputStream(outputStream); + Long tenantId = TenantContextHolder.getTenantId(); + // 备份文件 租户隔离 + String mpkTenantBakFilePath = mpkBakFilePath + File.separator + tenantId; MpkFileDTO entity = baseDao.get(id); //生成代码 - GenUtils.generatorCode(entity, zip); - IOUtils.closeQuietly(zip); + //设置velocity资源加载器 + Properties prop = new Properties(); + prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + Velocity.init(prop); - File file = null; - OutputStream fileOutputStream = null; - //文件备份 + //封装模板数据 + Map<String, Object> map = new HashMap<>(); + map.put("pkgName",entity.getPkgName()); + map.put("modelMethods",entity.getModelMethods()); + map.put("pyName",entity.getPyName()); + map.put("pyModule",entity.getPyModule()); + + VelocityContext dataContext = new VelocityContext(map); + + //临时文件夹 + File dirPath = null; try { - String dirPath = mpkBakFilePath; - File dir = new File(dirPath); - if (!dir.exists()) { - dir.mkdirs(); - } - String filePath = dirPath + File.separator + zipFileName; - file = new File(filePath); - file.createNewFile(); - fileOutputStream = Files.newOutputStream(file.toPath()); - IOUtils.write(outputStream.toByteArray(), fileOutputStream); + dirPath = Files.createTempDirectory("generatorCodeTmp").toFile(); + log.info("生成临时文件夹," + dirPath.getAbsolutePath()); } catch (IOException e) { - log.error("生成代码文件备份失败," + entity.getPyName(), e); - throw new RuntimeException(e); - } finally { - IOUtils.closeQuietly(fileOutputStream); + throw new RuntimeException("创建临时文件夹异常",e); } + + List<String> javaFilePaths = new ArrayList<>(); + List<String> cppFilePaths = new ArrayList<>(); + + //生成java文件 + File javaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + entity.getPkgName().replace(".", File.separator) + File.separator + entity.getPyName() + ".java"); + GenUtils.drawTemplate("abstract.java.vm", dataContext, javaFile); + javaFilePaths.add(javaFile.getAbsolutePath()); + + //生成Impl.java文件 + File implJavaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + entity.getPkgName().replace(".", File.separator) + File.separator + MdkConstant.IMPL + File.separator + entity.getPyName() + "Impl.java"); + GenUtils.drawTemplate("impl.java.vm", dataContext, implJavaFile); + javaFilePaths.add(implJavaFile.getAbsolutePath()); + + //生成.cpp文件 + File cppFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + ".cpp"); + GenUtils.drawTemplate("cpp.vm", dataContext, cppFile); + cppFilePaths.add(cppFile.getAbsolutePath()); + + //生成Jni.cpp文件 + File jniCppFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + "Jni.cpp"); + GenUtils.drawTemplate("Jni.cpp.vm", dataContext, jniCppFile); + cppFilePaths.add(jniCppFile.getAbsolutePath()); + + //生成.h文件 + File hFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + ".h"); + GenUtils.drawTemplate("h.vm", dataContext, hFile); + + //生成Jni.h文件 + File jniHFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + "Jni.h"); + GenUtils.drawTemplate("Jni.h.vm", dataContext, jniHFile); + + // 添加python源文件 + String pyFilePath = dirPath.getAbsolutePath() + File.separator + MdkConstant.ALGS + File.separator + entity.getPyModule().replace(".", File.separator) + File.separator + entity.getFilePath().substring(entity.getFilePath().lastIndexOf("\\")); + FileUtil.mkParentDirs(pyFilePath); + FileUtil.copy(entity.getFilePath(), pyFilePath, true); + + // 资源文件 + FileUtil.copy(mpkResources + File.separator + "libs", dirPath.getAbsolutePath(), true); + + //生成dll文件 + String dllSavePath = dirPath.getAbsolutePath() + File.separator + MdkConstant.LIBS + File.separator + "IAIL.MDK.Mid.Jni.dll"; + createDllFile(dirPath.getAbsolutePath(),cppFilePaths,dllSavePath); + //备份dll文件,用于后续运行 + String dllBakPath = mpkTenantBakFilePath + File.separator + MdkConstant.DLL + File.separator + entity.getPyName() + ".dll"; + FileUtil.mkParentDirs(dllBakPath); + FileUtil.copy(dllSavePath, dllBakPath, true); + + //utils + env java文件 + File utilsJavaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + "iail" + File.separator + "mdk" + File.separator + "model" + File.separator + "utils" + File.separator + "AlgsUtils.java"); + FileUtil.mkParentDirs(utilsJavaFile); + FileUtil.copy(mpkResources + File.separator +"IAILMDK/utils/AlgsUtils.java", utilsJavaFile.getAbsolutePath(), true); + javaFilePaths.add(utilsJavaFile.getAbsolutePath()); + File envJavaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + "iail" + File.separator + "mdk" + File.separator + "model" + File.separator + "common" + File.separator + "Environment.java"); + FileUtil.mkParentDirs(envJavaFile); + FileUtil.copy(mpkResources + File.separator +"IAILMDK/common/Environment.java", envJavaFile.getAbsolutePath(), true); + javaFilePaths.add(envJavaFile.getAbsolutePath()); + // 生成class文件 + createClassFile(javaFilePaths); + // 删除java源文件 + deleteJavaFile(javaFilePaths); + // 打jar包 + String jarSavePath = pkgJar(dirPath.getAbsolutePath()); + //备份jar文件,用于后续运行 + String jarBakPath = mpkTenantBakFilePath + File.separator + MdkConstant.JAR + File.separator + entity.getPyName() + ".jar"; + FileUtil.mkParentDirs(dllBakPath); + FileUtil.copy(jarSavePath, jarBakPath, true); + // 打zip包 + String zipPath = mpkTenantBakFilePath + File.separator + zipFileName; + ZipUtil.zip(dirPath.getAbsolutePath(), zipPath); + byte[] bytes = FileUtil.readBytes(zipPath); //代码生成历史记录 GeneratorCodeHistoryEntity historyEntity = new GeneratorCodeHistoryEntity(); historyEntity.setId(UUID.randomUUID().toString()); historyEntity.setMdkId(id); - historyEntity.setFileName(file.getName()); - historyEntity.setFilePath(file.getAbsolutePath()); + historyEntity.setFileName(zipFileName); + historyEntity.setFilePath(zipPath); historyEntity.setRemark(remark); historyEntity.setCreateTime(new Date()); generatorCodeHistoryService.insert(historyEntity); - return outputStream.toByteArray(); + // 删除临时文件 + try { + FileUtils.deleteDirectory(dirPath); + } catch (IOException e) { + throw new RuntimeException("删除临时文件异常",e); + } + return bytes; } @Override @DSTransactional(rollbackFor = Exception.class) - public byte[] packageModel(List<String> ids, String projectId, String projectName, String zipFileName, String log, String version) throws IOException, InterruptedException { + public byte[] packageModel(List<String> ids, String projectId, String projectName, String zipFileName, String logs, String version) throws IOException, InterruptedException { + Long tenantId = TenantContextHolder.getTenantId(); + // 备份文件 租户隔离 + String mpkTenantBakFilePath = mpkBakFilePath + File.separator + tenantId; + List<MpkFileDTO> entities = baseDao.selectByIds(ids); //模板数据 - Map<String, Object> map = new HashMap<>(); - map.put("entities", entities); - VelocityContext context = new VelocityContext(map); +// Map<String, Object> map = new HashMap<>(); +// map.put("entities", entities); +// VelocityContext context = new VelocityContext(map); //临时文件夹 - File dirPath = new File("C:/DLUT/tmp/"); - if (!dirPath.exists()) { - dirPath.mkdirs(); + File dirPath = null; + try { + dirPath = Files.createTempDirectory("packageModelTmp").toFile(); + log.info("生成临时文件夹," + dirPath.getAbsolutePath()); + } catch (IOException e) { + throw new RuntimeException("创建临时文件夹异常",e); } //设置velocity资源加载器 @@ -238,27 +390,11 @@ LinkedHashMap<String, LinkedHashMap<String, List<MpkFileDTO>>> collect = entities.stream().collect(Collectors.groupingBy(MpkFileDTO::getMenuName, LinkedHashMap::new, Collectors.groupingBy(e -> StringUtils.isNotBlank(e.getGroupName()) ? e.getGroupName() : "default_group",LinkedHashMap::new,Collectors.toList()))); Map<String, Object> map1 = new HashMap<>(); map1.put("collects", collect); - File xmlFile = new File(dirPath.getAbsolutePath() + File.separator + "menu.xml"); + File xmlFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.LIBS + File.separator + "menu.xml"); GenUtils.drawTemplate("menu.xml.vm", new VelocityContext(map1), xmlFile); - //生成cpp文件 - File cppFile = new File(dirPath.getAbsolutePath() + File.separator + UUID.randomUUID() + ".cpp"); - GenUtils.drawTemplate("pkg.cpp.vm", context, cppFile); - - //生成Jni.cpp文件 - File jniCppFile = new File(dirPath.getAbsolutePath() + File.separator + UUID.randomUUID() + "Jni.cpp"); - GenUtils.drawTemplate("pkg.Jni.cpp.vm", context, jniCppFile); - - //生成dll文件 - String dllSavePath = dirPath.getAbsolutePath() + File.separator + "IAIL.MDK.Mid.Windows.dll"; - String cppFilePath = cppFile.getAbsolutePath(); - String jniCppFilePath = jniCppFile.getAbsolutePath(); -// String command = "cmd.exe /c cl -o " + dllSavePath + " /LD " + jniCppFilePath + " " + cppFilePath; - String command = "cmd.exe /c cl -o " + dllSavePath + " /LD D:\\work\\mdk\\code\\makeDll\\src\\main\\java\\org\\example\\MakeDll.c D:\\work\\mdk\\code\\makeDll\\src\\main\\java\\org\\example\\MakeDll2.c"; - Process process = RuntimeUtil.exec(command); - // 等待命令执行完成 - process.waitFor(); List<String> javaFilePaths = new ArrayList<>(); + List<String> cppFilePaths = new ArrayList<>(); //生成java文件 for (MpkFileDTO entity : entities) { @@ -279,46 +415,89 @@ GenUtils.drawTemplate("impl.java.vm", dataContext, implJavaFile); javaFilePaths.add(implJavaFile.getAbsolutePath()); + //生成.cpp文件 + File cppFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + ".cpp"); + GenUtils.drawTemplate("cpp.vm", dataContext, cppFile); + cppFilePaths.add(cppFile.getAbsolutePath()); + + //生成Jni.cpp文件 + File jniCppFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + "Jni.cpp"); + GenUtils.drawTemplate("Jni.cpp.vm", dataContext, jniCppFile); + cppFilePaths.add(jniCppFile.getAbsolutePath()); + + //生成.h文件 + File hFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + ".h"); + GenUtils.drawTemplate("h.vm", dataContext, hFile); + + //生成Jni.h文件 + File jniHFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + "Jni.h"); + GenUtils.drawTemplate("Jni.h.vm", dataContext, jniHFile); + // 添加python源文件 - String pyFilePath = dirPath.getAbsolutePath() + File.separator + "py" + File.separator + entity.getPyName() + ".pyd"; + String pyFilePath = dirPath.getAbsolutePath() + File.separator + MdkConstant.ALGS + File.separator + entity.getPyModule().replace(".", File.separator) + File.separator + entity.getFilePath().substring(entity.getFilePath().lastIndexOf("\\")); FileUtil.mkParentDirs(pyFilePath); FileUtil.copy(entity.getFilePath(), pyFilePath, true); } + // 资源文件 + FileUtil.copy(mpkResources + File.separator + "libs", dirPath.getAbsolutePath(), true); + + //生成dll文件 + String dllSavePath = dirPath.getAbsolutePath() + File.separator + MdkConstant.LIBS + File.separator + "IAIL.MDK.Mid.Jni.dll"; + createDllFile(dirPath.getAbsolutePath(),cppFilePaths,dllSavePath); + // 打包历史id + String historyId = UUID.randomUUID().toString(); + //备份dll,发布时使用 + File dllFile = new File(dllSavePath); + if (dllFile.exists()) { + File dllBakFile = new File(mpkBakFilePath + File.separator + MdkConstant.PROJECT_UNPUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll"); + FileUtil.copy(dllFile, dllBakFile, true); + }else { + log.error("dll文件不存在,无法备份。" + dllSavePath); + } + //utils + env java文件 - File utilsJavaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + "utils" + File.separator + "AlgsUtils.java"); + File utilsJavaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + "iail" + File.separator + "mdk" + File.separator + "model" + File.separator + "utils" + File.separator + "AlgsUtils.java"); FileUtil.mkParentDirs(utilsJavaFile); - FileUtil.copy("bak/AlgsUtils.java", utilsJavaFile.getAbsolutePath(), true); + FileUtil.copy(mpkResources + File.separator +"IAILMDK/utils/AlgsUtils.java", utilsJavaFile.getAbsolutePath(), true); javaFilePaths.add(utilsJavaFile.getAbsolutePath()); - File envJavaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + "common" + File.separator + "Environment.java"); + File envJavaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + "iail" + File.separator + "mdk" + File.separator + "model" + File.separator + "common" + File.separator + "Environment.java"); FileUtil.mkParentDirs(envJavaFile); - FileUtil.copy("bak/Environment.java", envJavaFile.getAbsolutePath(), true); + FileUtil.copy(mpkResources + File.separator +"IAILMDK/common/Environment.java", envJavaFile.getAbsolutePath(), true); javaFilePaths.add(envJavaFile.getAbsolutePath()); // 生成class文件 createClassFile(javaFilePaths); // 删除java源文件 deleteJavaFile(javaFilePaths); // 打jar包 - pkgJar(dirPath.getAbsolutePath()); + String jarSavePath = pkgJar(dirPath.getAbsolutePath()); + //备份jar包,发布时使用 + File jarFile = new File(jarSavePath); + if (jarFile.exists()) { + File jarBakFile = new File(mpkBakFilePath + File.separator + MdkConstant.PROJECT_UNPUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar"); + FileUtil.copy(jarFile, jarBakFile, true); + }else { + log.error("jar文件不存在,无法备份。" + jarSavePath); + } + // 本次更新日志 - ProjectPackageHistoryDTO dto = new ProjectPackageHistoryDTO(); - String historyId = UUID.randomUUID().toString(); - dto.setId(historyId); - dto.setProjectId(projectId); - dto.setFileName(zipFileName); - dto.setLog(log); - dto.setVersion(version); - dto.setModelNames(entities.stream().map(MpkFileDTO::getPyName).collect(Collectors.joining(","))); - dto.setCreateTime(new Date()); + ProjectPackageHistoryEntity projectPackageHistoryEntity = new ProjectPackageHistoryEntity(); + projectPackageHistoryEntity.setId(historyId); + projectPackageHistoryEntity.setProjectId(projectId); + projectPackageHistoryEntity.setFileName(zipFileName); + projectPackageHistoryEntity.setLog(logs); + projectPackageHistoryEntity.setVersion(version); + projectPackageHistoryEntity.setModelNames(entities.stream().map(MpkFileDTO::getPyName).collect(Collectors.joining(","))); + projectPackageHistoryEntity.setCreateTime(new Date()); // 生成更新日志 - createLog(projectId, projectName, dirPath.getAbsolutePath(), dto, version); + createLog(projectId, projectName, dirPath.getAbsolutePath(), projectPackageHistoryEntity, version); // 打zip包 - String zipPath = mpkBakFilePath + File.separator + zipFileName; + String zipPath = mpkTenantBakFilePath + File.separator + zipFileName; ZipUtil.zip(dirPath.getAbsolutePath(), zipPath); byte[] bytes = FileUtil.readBytes(zipPath); // 记录打包日志 - dto.setFilePath(zipPath); - projectPackageHistoryService.save(dto); + projectPackageHistoryEntity.setFilePath(zipPath); + projectPackageHistoryService.insert(projectPackageHistoryEntity); // 插入打包历史-模型关联表 List<ProjectPackageHistoryModelEntity> historyModelList = new ArrayList<>(entities.size()); entities.forEach(e -> { @@ -337,42 +516,181 @@ } historyModelList.add(entity); }); - projectPackageHistoryModelService.insertBatch(historyModelList); + projectPackageHistoryModelService.insertList(historyModelList); // 删除临时文件 FileUtils.deleteDirectory(dirPath); -// FileUtils.delete(new File(zipPath)); return bytes; + } + + private void createDllFile(String dirPath, List<String> cppFilePaths, String dllSavePath) { + try { + String paths = cppFilePaths.stream().collect(Collectors.joining(" ")); + String command = "cl /LD " + paths + " /EHsc /o " + dllSavePath + " /link " + "IAIL.MDK.Mid.Windows.lib"; + log.info("执行cmd命令生成dll:" + command); + ProcessBuilder builder = new ProcessBuilder("cmd", "/c", command); + builder.directory(new File(dirPath + File.separator + MdkConstant.LIBS)); + Process process = builder.start(); + // 获取命令输出结果 + InputStream inputStream = process.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK")); // 设置编码为GBK + String line; + while ((line = reader.readLine()) != null) { + log.info(line); + } + // 等待命令执行完成 + process.waitFor(); + } catch (Exception e) { + throw new RuntimeException("执行cmd命令生成dll异常",e); + } } @Override public Map<String, String> savePyFile(MultipartFile file) throws IOException { - File dir = new File(mpkBakFilePath); - if (!dir.exists()) { - dir.mkdirs(); + Long tenantId = TenantContextHolder.getTenantId(); + // 备份文件 租户隔离 + String mpkTenantBakFilePath = mpkBakFilePath + File.separator + tenantId; + File bakDir = new File(mpkTenantBakFilePath); + if (!bakDir.exists()) { + bakDir.mkdirs(); + } + //临时文件夹 + File tempDir = null; + try { + tempDir = Files.createTempDirectory("pyFileTmp").toFile(); + log.info("生成临时文件夹," + tempDir.getAbsolutePath()); + } catch (IOException e) { + throw new RuntimeException("创建临时文件夹异常",e); } String fileName = file.getOriginalFilename(); - File saveFile = new File(dir.getAbsolutePath() + File.separator + fileName); - saveFile.createNewFile(); - // 保存 - file.transferTo(saveFile); + String pyName = fileName.substring(0, fileName.lastIndexOf(".")); + String pyName_uuTime = pyName + "_" + new Date().getTime(); + + File pydBakFile = new File(bakDir.getAbsolutePath() + File.separator + pyName_uuTime + ".pyd"); + try { + // py文件存入临时文件夹 + File saveFile = new File(tempDir.getAbsolutePath() + File.separator + fileName); + saveFile.createNewFile(); + file.transferTo(saveFile); + + // 临时文件夹中生成pyd文件 + // 生成setup.py文件 + createSetUpFile(tempDir.getAbsolutePath(),fileName,pyName_uuTime); + // 执行cmd命令编译pyd文件 + createPydFile(tempDir.getAbsolutePath()); + + // 临时文件夹中pyd文件移到dir下,修改为uuid.pyd + File pydFile = new File(tempDir.getAbsolutePath() + File.separator + pyName_uuTime + MdkConstant.PYD_SUFFIX); + if (!pydFile.exists()) { + throw new RuntimeException("编译pyd文件失败!"); + } + log.info("备份pyd文件," + pydBakFile.getAbsolutePath()); + FileUtil.copy(pydFile,pydBakFile,true); + } catch (Exception e) { + throw new RuntimeException("编译pyd文件异常"); + } finally { + if (tempDir.exists()) { + tempDir.delete(); + } + } Map<String, String> result = new HashMap<>(2); - result.put("filePath", saveFile.getAbsolutePath()); - result.put("fileName", fileName); + result.put("filePath", pydBakFile.getAbsolutePath()); + result.put("fileName", pyName); return result; } - private void createLog(String projectId, String projectName, String dirPath, ProjectPackageHistoryDTO dto, String version) throws IOException { + private void createPydFile(String dir) { + try { + String command = "python setup.py build_ext --inplace"; + log.info("执行cmd命令编译pyd:" + command); + ProcessBuilder builder = new ProcessBuilder("cmd", "/c", command); + builder.directory(new File(dir)); // 设置工作目录 + builder.redirectErrorStream(true); // 将错误输出和标准输出合并 + Process process = builder.start(); + // 获取命令输出结果 + InputStream inputStream = process.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK")); // 设置编码为GBK + String line; + while ((line = reader.readLine()) != null) { + log.info(line); + } + // 等待命令执行完成 + process.waitFor(); + } catch (Exception e) { + throw new RuntimeException("执行cmd命令生成dll异常", e); + } + } + + private void createSetUpFile(String dir, String pyFileName, String pyName) { + // 生成setup.py文件 + HashMap<String,Object> map = new HashMap<>(); + map.put("fileName",pyFileName); + map.put("pyName",pyName); + GenUtils.drawTemplate("setup.py.vm",map,new File(dir + File.separator + MdkConstant.SETUP_PY)); + } + + @Override + public CommonResult<String> publish(Map<String, Object> params) { + String historyId = (String) params.get("historyId"); + String projectId = (String) params.get("projectId"); + + // 判断新的dll和jar文件是否存在 + String jarFileBakPath = mpkBakFilePath + File.separator + MdkConstant.PROJECT_UNPUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar"; + String dllFileBakPath = mpkBakFilePath + File.separator + MdkConstant.PROJECT_UNPUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll"; + if (!FileUtil.exist(jarFileBakPath)) { + throw new RuntimeException("jar文件不存在," + jarFileBakPath); + } + if (!FileUtil.exist(dllFileBakPath)) { + throw new RuntimeException("dll文件不存在" + dllFileBakPath); + } + + try { + // 卸载之前的dll和jar + DllUtils.removeClassLoaderCache(projectId); + // 删除之前的dll和jar备份文件 + DllUtils.removeOldFile(mpkBakFilePath + File.separator + MdkConstant.PROJECT_PUBLISH,projectId); + } catch (Exception e) { + throw new RuntimeException("卸载之前的dll和jar异常",e); + } + + // 备份新的dll和jar + String jarFilePath = mpkBakFilePath + File.separator + MdkConstant.PROJECT_PUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar"; + String dllFilePath = mpkBakFilePath + File.separator + MdkConstant.PROJECT_PUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll"; + FileUtil.copy(jarFileBakPath,jarFilePath,true); + FileUtil.copy(dllFileBakPath,dllFilePath,true); + + URLClassLoader urlClassLoader = null; + try { + // 加载新的jar + urlClassLoader = DllUtils.loadJar(jarFilePath); + } catch (Exception e) { + throw new RuntimeException("加载新的jar异常",e); + } + + try { + // 加载新的dll + DllUtils.loadDll(urlClassLoader.loadClass("iail.mdk.model.common.Environment"),dllFilePath); + } catch (Exception e) { + DllUtils.unloadJar(urlClassLoader); + throw new RuntimeException("加载新的dll异常",e); + } + // 都加载成功后加入缓存 + DllUtils.addClassLoaderCache(projectId,urlClassLoader); + + return CommonResult.success(); + } + + private void createLog(String projectId, String projectName, String dirPath, ProjectPackageHistoryEntity projectPackageHistoryEntity, String version) { Map<String, Object> map = new HashMap<>(); map.put("projectId", projectId); - List<ProjectPackageHistoryDTO> list = projectPackageHistoryService.list(map); - list.add(dto); + List<ProjectPackageHistoryEntity> list = projectPackageHistoryService.list(map); + list.add(projectPackageHistoryEntity); // 按照日期分组再排序 - HashMap<String, List<ProjectPackageHistoryDTO>> dataMap = list.stream().collect( + HashMap<String, List<ProjectPackageHistoryEntity>> dataMap = list.stream().collect( Collectors.groupingBy(e -> DateUtils.format(e.getCreateTime(), DateUtils.DATE_PATTERN_POINT), LinkedHashMap::new, - Collectors.collectingAndThen(Collectors.toList(), e -> e.stream().sorted(Comparator.comparing(ProjectPackageHistoryDTO::getCreateTime)).collect(Collectors.toList())))); + Collectors.collectingAndThen(Collectors.toList(), e -> e.stream().sorted(Comparator.comparing(ProjectPackageHistoryEntity::getCreateTime)).collect(Collectors.toList())))); Map<String, Object> data = new HashMap<>(); data.put("dataMap", dataMap); @@ -384,14 +702,20 @@ GenUtils.drawTemplate("log.txt.vm", data, logFile); } - private void pkgJar(String dirPath) throws InterruptedException { - StringBuilder sb = new StringBuilder(); - sb.append("jar -cvf"); - sb.append(" ").append(dirPath).append(File.separator).append("IAILMDK.jar"); - sb.append(" -C ").append(dirPath).append(File.separator).append("IAILMDK").append(File.separator).append(" ."); - log.info("执行cmd命令打jar包:" + sb); - Process process = RuntimeUtil.exec(sb.toString()); - process.waitFor(); + private String pkgJar(String dirPath) { + try { + String jarSavePath = dirPath + File.separator + MdkConstant.LIBS + File.separator + "IAILMDK.jar"; + StringBuilder sb = new StringBuilder(); + sb.append("jar -cvf"); + sb.append(" ").append(jarSavePath); + sb.append(" -C ").append(dirPath).append(File.separator).append("IAILMDK").append(File.separator).append(" ."); + log.info("执行cmd命令打jar包:" + sb); + Process process = RuntimeUtil.exec(sb.toString()); + process.waitFor(); + return jarSavePath; + } catch (InterruptedException e) { + throw new RuntimeException("执行cmd命令打jar包异常",e); + } } private void deleteJavaFile(List<String> javaFilePaths) { @@ -400,14 +724,18 @@ } } - private void createClassFile(List<String> javaFilePaths) throws InterruptedException { - StringBuilder sb = new StringBuilder(); - sb.append("javac -encoding utf-8"); - for (String path : javaFilePaths) { - sb.append(" ").append(path); + private void createClassFile(List<String> javaFilePaths){ + try { + StringBuilder sb = new StringBuilder(); + sb.append("javac -encoding utf-8"); + for (String path : javaFilePaths) { + sb.append(" ").append(path); + } + log.info("执行cmd命令生成class:" + sb); + Process process = RuntimeUtil.exec(sb.toString()); + process.waitFor(); + } catch (InterruptedException e) { + throw new RuntimeException("执行cmd命令生成class异常",e); } - log.info("执行cmd命令生成class:" + sb); - Process process = RuntimeUtil.exec(sb.toString()); - process.waitFor(); } } \ No newline at end of file -- Gitblit v1.9.3