dengzedong
2024-10-14 bb015596297586342fc6c3e5a5df7c4a55a426a5
提交 | 用户 | 时间
449017 1 package com.iailab.module.model.mpk.service.impl;
D 2
3 import cn.hutool.core.io.FileUtil;
4 import cn.hutool.core.util.RuntimeUtil;
5 import cn.hutool.core.util.ZipUtil;
6 import com.alibaba.fastjson.JSON;
8b3ee3 7 import com.baomidou.dynamic.datasource.annotation.DSTransactional;
449017 8 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
D 9 import com.baomidou.mybatisplus.core.metadata.IPage;
10 import com.iailab.framework.common.page.PageData;
c12dae 11 import com.iailab.framework.common.pojo.CommonResult;
449017 12 import com.iailab.framework.common.service.impl.BaseServiceImpl;
D 13 import com.iailab.framework.common.util.date.DateUtils;
14 import com.iailab.framework.common.util.object.ConvertUtils;
15 import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
558ffc 16 import com.iailab.framework.tenant.core.context.TenantContextHolder;
449017 17 import com.iailab.module.infra.api.config.ConfigApi;
D 18 import com.iailab.module.model.mpk.common.MdkConstant;
c12dae 19 import com.iailab.module.model.mpk.common.utils.DllUtils;
449017 20 import com.iailab.module.model.mpk.common.utils.GenUtils;
D 21 import com.iailab.module.model.mpk.dao.MpkFileDao;
1fea3e 22 import com.iailab.module.model.mpk.dto.GeneratorCodeHistoryDTO;
D 23 import com.iailab.module.model.mpk.dto.ModelMethodDTO;
24 import com.iailab.module.model.mpk.dto.MpkFileDTO;
25 import com.iailab.module.model.mpk.dto.ProjectPackageHistoryDTO;
26 import com.iailab.module.model.mpk.entity.GeneratorCodeHistoryEntity;
27 import com.iailab.module.model.mpk.entity.MpkFileEntity;
558ffc 28 import com.iailab.module.model.mpk.entity.ProjectPackageHistoryEntity;
1fea3e 29 import com.iailab.module.model.mpk.entity.ProjectPackageHistoryModelEntity;
449017 30 import com.iailab.module.model.mpk.service.*;
D 31 import lombok.extern.slf4j.Slf4j;
32 import org.apache.commons.io.FileUtils;
33 import org.apache.commons.lang3.StringUtils;
34 import org.apache.velocity.VelocityContext;
35 import org.apache.velocity.app.Velocity;
36 import org.springframework.beans.factory.annotation.Autowired;
a27351 37 import org.springframework.beans.factory.annotation.Value;
449017 38 import org.springframework.stereotype.Service;
D 39 import org.springframework.util.CollectionUtils;
40 import org.springframework.web.multipart.MultipartFile;
41
f7932f 42 import java.io.*;
c12dae 43 import java.net.URLClassLoader;
912a1e 44 import java.nio.file.Files;
449017 45 import java.util.*;
D 46 import java.util.stream.Collectors;
47
48 /**
49  * @author PanZhibao
50  * @Description
51  * @createTime 2024年08月14日
52  */
53 @Slf4j
54 @Service
0255ea 55 public class MpkFileServiceImpl extends BaseServiceImpl<MpkFileDao, MpkFileEntity> implements MpkFileService {
449017 56
D 57     @Autowired
58     private GeneratorCodeHistoryService generatorCodeHistoryService;
8b3ee3 59
449017 60     @Autowired
D 61     private ProjectPackageHistoryService projectPackageHistoryService;
8b3ee3 62
449017 63     @Autowired
D 64     private ModelMethodService modelMethodService;
8b3ee3 65
449017 66     @Autowired
D 67     private ProjectPackageHistoryModelService projectPackageHistoryModelService;
68
69     @Autowired
70     private ConfigApi configApi;
71
1fea3e 72     @Value("${mpk.bak-file-path}")
a27351 73     private String mpkBakFilePath;
1fea3e 74
D 75     @Value("${mpk.bak-resources}")
76     private String mpkResources;
449017 77
D 78     @Override
79     public PageData<MpkFileDTO> page(Map<String, Object> params) {
80         IPage<MpkFileEntity> page = baseDao.selectPage(
81                 getPage(params, "create_date", false),
82                 getWrapper(params)
83         );
84
85         return getPageData(page, MpkFileDTO.class);
86     }
87
88     @Override
89     public List<MpkFileDTO> list(Map<String, Object> params) {
90         List<MpkFileEntity> entityList = baseDao.selectList(getWrapper(params).orderByDesc("create_date"));
91
92         return ConvertUtils.sourceToTarget(entityList, MpkFileDTO.class);
93     }
94
8b3ee3 95     private QueryWrapper<MpkFileEntity> getWrapper(Map<String, Object> params) {
449017 96         String pyName = (String) params.get("pyName");
D 97         String pyType = (String) params.get("pyType");
98         String remark = (String) params.get("remark");
d8db4b 99         String label = (String) params.get("label");
449017 100
D 101         QueryWrapper<MpkFileEntity> wrapper = new QueryWrapper<>();
102         wrapper.like(StringUtils.isNotBlank(pyName), "py_name", pyName)
103                 .eq(StringUtils.isNotBlank(pyType), "py_type", pyType)
104                 .like(StringUtils.isNotBlank(remark), "remark", remark);
d8db4b 105
106         if (StringUtils.isNotBlank(label)) {
107             wrapper.and(w -> {
108                 w.eq(StringUtils.isNotBlank(label),"menu_name", label)
109                         .or().eq(StringUtils.isNotBlank(label),"group_name", label);
110             });
111         }
449017 112         return wrapper;
D 113     }
114
115     @Override
116     public MpkFileDTO get(String id) {
117         MpkFileDTO entity = baseDao.get(id);
118
119         return entity;
120     }
121
122     @Override
8b3ee3 123     @DSTransactional(rollbackFor = Exception.class)
449017 124     public void save(MpkFileDTO dto) {
D 125         MpkFileEntity entity = ConvertUtils.sourceToTarget(dto, MpkFileEntity.class);
8b3ee3 126         entity.setId(UUID.randomUUID().toString());
ed8ba3 127         entity.setPkgName(dto.getPkgName().trim());
128         entity.setFilePath(dto.getFilePath().trim());
449017 129         entity.setCreator(SecurityFrameworkUtils.getLoginUserId());
D 130         entity.setCreateDate(new Date());
131         insert(entity);
8b3ee3 132         modelMethodService.insertList(dto.getModelMethods(), entity.getId());
bb0155 133
D 134         // 替换环境变量MDK_PKGS下的py文件
135         String mdkPkgs = System.getenv("MDK_PKGS");
136         String pyFilePath = mdkPkgs + File.separator + entity.getPyModule().replace(".", File.separator) + File.separator + entity.getPyName() + ".pyd";
137         FileUtil.mkParentDirs(pyFilePath);
138         FileUtil.copy(entity.getFilePath(), pyFilePath, true);
449017 139     }
D 140
141     @Override
8b3ee3 142     @DSTransactional(rollbackFor = Exception.class)
449017 143     public void update(MpkFileDTO dto) {
D 144         MpkFileEntity entity = ConvertUtils.sourceToTarget(dto, MpkFileEntity.class);
145         entity.setUpdater(SecurityFrameworkUtils.getLoginUserId());
146         entity.setUpdateDate(new Date());
147         updateById(entity);
8b3ee3 148         modelMethodService.deleteModelMethod(entity.getId());
149         modelMethodService.insertList(dto.getModelMethods(), entity.getId());
bb0155 150
D 151         // 替换环境变量MDK_PKGS下的py文件
152         String mdkPkgs = System.getenv("MDK_PKGS");
153         String pyFilePath = mdkPkgs + File.separator + entity.getPyModule().replace(".", File.separator) + File.separator + entity.getPyName() + ".pyd";
154         FileUtil.mkParentDirs(pyFilePath);
155         FileUtil.copy(entity.getFilePath(), pyFilePath, true);
449017 156     }
D 157
158     @Override
8b3ee3 159     @DSTransactional(rollbackFor = Exception.class)
449017 160     public void delete(String id) {
D 161
162         //删除源文件
163         MpkFileEntity mpkFileEntity = selectById(id);
164         if (StringUtils.isNoneBlank(mpkFileEntity.getFilePath())) {
165             File mpkFile = new File(mpkFileEntity.getFilePath());
166             if (mpkFile.exists()) {
167                 mpkFile.delete();
168                 log.info("删除源文件备份文件:" + mpkFileEntity.getFilePath());
169             }
170         }
171
172         //删除备份文件
8b3ee3 173         Map<String, Object> map1 = new HashMap<>();
174         map1.put("mdkId", id);
449017 175         List<GeneratorCodeHistoryDTO> list = generatorCodeHistoryService.list(map1);
D 176         list.forEach(e -> {
177             File file = new File(e.getFilePath());
178             if (file.exists()) {
179                 file.delete();
180                 log.info("删除生成代码备份文件:" + e.getFilePath());
181             }
182         });
183
0255ea 184         //删除 会级联删除掉关联表
D 185         deleteById(id);
449017 186     }
D 187
188     @Override
189     public byte[] generatorCode(String id, String remark, String zipFileName) {
558ffc 190         Long tenantId = TenantContextHolder.getTenantId();
D 191         // 备份文件 租户隔离
192         String mpkTenantBakFilePath = mpkBakFilePath + File.separator + tenantId;
193
449017 194         MpkFileDTO entity = baseDao.get(id);
D 195         //生成代码
1fea3e 196         //设置velocity资源加载器
D 197         Properties prop = new Properties();
198         prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
199         Velocity.init(prop);
449017 200
1fea3e 201         //封装模板数据
D 202         Map<String, Object> map = new HashMap<>();
203         map.put("pkgName",entity.getPkgName());
204         map.put("modelMethods",entity.getModelMethods());
205         map.put("pyName",entity.getPyName());
206         map.put("pyModule",entity.getPyModule());
207
208         VelocityContext dataContext = new VelocityContext(map);
209
210         //临时文件夹
912a1e 211         File dirPath = null;
D 212         try {
213             dirPath = Files.createTempDirectory("generatorCodeTmp").toFile();
214             log.info("生成临时文件夹," + dirPath.getAbsolutePath());
215         } catch (IOException e) {
216             throw new RuntimeException("创建临时文件夹异常",e);
217         }
1fea3e 218
D 219         List<String> javaFilePaths = new ArrayList<>();
220         List<String> cppFilePaths = new ArrayList<>();
221
222         //生成java文件
223         File javaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + entity.getPkgName().replace(".", File.separator) + File.separator + entity.getPyName() + ".java");
224         GenUtils.drawTemplate("abstract.java.vm", dataContext, javaFile);
225         javaFilePaths.add(javaFile.getAbsolutePath());
226
227         //生成Impl.java文件
228         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");
229         GenUtils.drawTemplate("impl.java.vm", dataContext, implJavaFile);
230         javaFilePaths.add(implJavaFile.getAbsolutePath());
231
232         //生成.cpp文件
233         File cppFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + ".cpp");
234         GenUtils.drawTemplate("cpp.vm", dataContext, cppFile);
235         cppFilePaths.add(cppFile.getAbsolutePath());
236
237         //生成Jni.cpp文件
238         File jniCppFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + "Jni.cpp");
239         GenUtils.drawTemplate("Jni.cpp.vm", dataContext, jniCppFile);
240         cppFilePaths.add(jniCppFile.getAbsolutePath());
241
242         //生成.h文件
243         File hFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + ".h");
244         GenUtils.drawTemplate("h.vm", dataContext, hFile);
245
246         //生成Jni.h文件
247         File jniHFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + "Jni.h");
248         GenUtils.drawTemplate("Jni.h.vm", dataContext, jniHFile);
249
250         // 资源文件
251         FileUtil.copy(mpkResources + File.separator + "libs", dirPath.getAbsolutePath(), true);
252
253         //生成dll文件
254         String dllSavePath = dirPath.getAbsolutePath() + File.separator + MdkConstant.LIBS + File.separator + "IAIL.MDK.Mid.Jni.dll";
255         createDllFile(dirPath.getAbsolutePath(),cppFilePaths,dllSavePath);
256         //备份dll文件,用于后续运行
558ffc 257         String dllBakPath = mpkTenantBakFilePath + File.separator + MdkConstant.DLL + File.separator + entity.getPyName() + ".dll";
1fea3e 258         FileUtil.mkParentDirs(dllBakPath);
D 259         FileUtil.copy(dllSavePath, dllBakPath, true);
260
261         //utils + env java文件
262         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");
263         FileUtil.mkParentDirs(utilsJavaFile);
264         FileUtil.copy(mpkResources + File.separator +"IAILMDK/utils/AlgsUtils.java", utilsJavaFile.getAbsolutePath(), true);
265         javaFilePaths.add(utilsJavaFile.getAbsolutePath());
266         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");
267         FileUtil.mkParentDirs(envJavaFile);
268         FileUtil.copy(mpkResources + File.separator +"IAILMDK/common/Environment.java", envJavaFile.getAbsolutePath(), true);
269         javaFilePaths.add(envJavaFile.getAbsolutePath());
270         // 生成class文件
271         createClassFile(javaFilePaths);
272         // 删除java源文件
273         deleteJavaFile(javaFilePaths);
274         // 打jar包
275         String jarSavePath = pkgJar(dirPath.getAbsolutePath());
276         //备份jar文件,用于后续运行
558ffc 277         String jarBakPath = mpkTenantBakFilePath + File.separator + MdkConstant.JAR + File.separator + entity.getPyName() + ".jar";
1fea3e 278         FileUtil.mkParentDirs(dllBakPath);
D 279         FileUtil.copy(jarSavePath, jarBakPath, true);
280         // 打zip包
558ffc 281         String zipPath = mpkTenantBakFilePath + File.separator + zipFileName;
1fea3e 282         ZipUtil.zip(dirPath.getAbsolutePath(), zipPath);
D 283         byte[] bytes = FileUtil.readBytes(zipPath);
449017 284
D 285         //代码生成历史记录
286         GeneratorCodeHistoryEntity historyEntity = new GeneratorCodeHistoryEntity();
287         historyEntity.setId(UUID.randomUUID().toString());
288         historyEntity.setMdkId(id);
1fea3e 289         historyEntity.setFileName(zipFileName);
D 290         historyEntity.setFilePath(zipPath);
449017 291         historyEntity.setRemark(remark);
D 292         historyEntity.setCreateTime(new Date());
293         generatorCodeHistoryService.insert(historyEntity);
294
1fea3e 295         // 删除临时文件
3009e2 296         try {
D 297             FileUtils.deleteDirectory(dirPath);
298         } catch (IOException e) {
912a1e 299             throw new RuntimeException("删除临时文件异常",e);
3009e2 300         }
1fea3e 301         return bytes;
449017 302     }
D 303
304     @Override
8b3ee3 305     @DSTransactional(rollbackFor = Exception.class)
f7932f 306     public byte[] packageModel(List<String> ids, String projectId, String projectName, String zipFileName, String logs, String version) throws IOException, InterruptedException {
558ffc 307         Long tenantId = TenantContextHolder.getTenantId();
D 308         // 备份文件 租户隔离
309         String mpkTenantBakFilePath = mpkBakFilePath + File.separator + tenantId;
310
449017 311         List<MpkFileDTO> entities = baseDao.selectByIds(ids);
D 312
313         //模板数据
1fea3e 314 //        Map<String, Object> map = new HashMap<>();
D 315 //        map.put("entities", entities);
316 //        VelocityContext context = new VelocityContext(map);
449017 317
D 318         //临时文件夹
912a1e 319         File dirPath = null;
D 320         try {
321             dirPath = Files.createTempDirectory("packageModelTmp").toFile();
322             log.info("生成临时文件夹," + dirPath.getAbsolutePath());
323         } catch (IOException e) {
324             throw new RuntimeException("创建临时文件夹异常",e);
325         }
449017 326
D 327         //设置velocity资源加载器
328         Properties prop = new Properties();
329         prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
330         Velocity.init(prop);
331
a27351 332         //生成menu.xml文件
2cc235 333         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())));
a27351 334         Map<String, Object> map1 = new HashMap<>();
8b3ee3 335         map1.put("collects", collect);
c7009e 336         File xmlFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.LIBS + File.separator + "menu.xml");
8b3ee3 337         GenUtils.drawTemplate("menu.xml.vm", new VelocityContext(map1), xmlFile);
449017 338
D 339         List<String> javaFilePaths = new ArrayList<>();
f7932f 340         List<String> cppFilePaths = new ArrayList<>();
449017 341
D 342         //生成java文件
343         for (MpkFileDTO entity : entities) {
344             //封装模板数据
345             Map<String, Object> data = new HashMap<>();
8b3ee3 346             data.put("pkgName", entity.getPkgName());
347             data.put("modelMethods", entity.getModelMethods());
348             data.put("pyName", entity.getPyName());
349             data.put("pyModule", entity.getPyModule());
449017 350             VelocityContext dataContext = new VelocityContext(data);
D 351             //生成java文件
352             File javaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + entity.getPkgName().replace(".", File.separator) + File.separator + entity.getPyName() + ".java");
8b3ee3 353             GenUtils.drawTemplate("abstract.java.vm", dataContext, javaFile);
449017 354             javaFilePaths.add(javaFile.getAbsolutePath());
D 355
356             //生成Impl.java文件
357             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");
8b3ee3 358             GenUtils.drawTemplate("impl.java.vm", dataContext, implJavaFile);
449017 359             javaFilePaths.add(implJavaFile.getAbsolutePath());
D 360
f7932f 361             //生成.cpp文件
D 362             File cppFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + ".cpp");
363             GenUtils.drawTemplate("cpp.vm", dataContext, cppFile);
364             cppFilePaths.add(cppFile.getAbsolutePath());
365
366             //生成Jni.cpp文件
367             File jniCppFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + "Jni.cpp");
368             GenUtils.drawTemplate("Jni.cpp.vm", dataContext, jniCppFile);
369             cppFilePaths.add(jniCppFile.getAbsolutePath());
370
371             //生成.h文件
372             File hFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + ".h");
373             GenUtils.drawTemplate("h.vm", dataContext, hFile);
374
375             //生成Jni.h文件
376             File jniHFile = new File(dirPath.getAbsolutePath() + File.separator + MdkConstant.C + File.separator + entity.getPyName() + "Jni.h");
377             GenUtils.drawTemplate("Jni.h.vm", dataContext, jniHFile);
378
449017 379             // 添加python源文件
c7009e 380             String pyFilePath = dirPath.getAbsolutePath() + File.separator + MdkConstant.ALGS + File.separator + entity.getPyModule().replace(".", File.separator) + File.separator + entity.getPyName() + ".pyd";
449017 381             FileUtil.mkParentDirs(pyFilePath);
8b3ee3 382             FileUtil.copy(entity.getFilePath(), pyFilePath, true);
449017 383         }
D 384
1fea3e 385         // 资源文件
D 386         FileUtil.copy(mpkResources + File.separator + "libs", dirPath.getAbsolutePath(), true);
c7009e 387
f7932f 388         //生成dll文件
c7009e 389         String dllSavePath = dirPath.getAbsolutePath() + File.separator + MdkConstant.LIBS + File.separator + "IAIL.MDK.Mid.Jni.dll";
f7932f 390         createDllFile(dirPath.getAbsolutePath(),cppFilePaths,dllSavePath);
c12dae 391         // 打包历史id
D 392         String historyId = UUID.randomUUID().toString();
393         //备份dll,发布时使用
394         File dllFile = new File(dllSavePath);
395         if (dllFile.exists()) {
558ffc 396             File dllBakFile = new File(mpkBakFilePath + File.separator + MdkConstant.PROJECT_UNPUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll");
c12dae 397             FileUtil.copy(dllFile, dllBakFile, true);
D 398         }else {
399             log.error("dll文件不存在,无法备份。" + dllSavePath);
400         }
f7932f 401
449017 402         //utils + env java文件
c7009e 403         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");
449017 404         FileUtil.mkParentDirs(utilsJavaFile);
1fea3e 405         FileUtil.copy(mpkResources + File.separator +"IAILMDK/utils/AlgsUtils.java", utilsJavaFile.getAbsolutePath(), true);
449017 406         javaFilePaths.add(utilsJavaFile.getAbsolutePath());
c7009e 407         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");
449017 408         FileUtil.mkParentDirs(envJavaFile);
1fea3e 409         FileUtil.copy(mpkResources + File.separator +"IAILMDK/common/Environment.java", envJavaFile.getAbsolutePath(), true);
449017 410         javaFilePaths.add(envJavaFile.getAbsolutePath());
D 411         // 生成class文件
412         createClassFile(javaFilePaths);
413         // 删除java源文件
414         deleteJavaFile(javaFilePaths);
415         // 打jar包
c12dae 416         String jarSavePath = pkgJar(dirPath.getAbsolutePath());
D 417         //备份jar包,发布时使用
418         File jarFile = new File(jarSavePath);
419         if (jarFile.exists()) {
558ffc 420             File jarBakFile = new File(mpkBakFilePath + File.separator + MdkConstant.PROJECT_UNPUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar");
c12dae 421             FileUtil.copy(jarFile, jarBakFile, true);
D 422         }else {
423             log.error("jar文件不存在,无法备份。" + jarSavePath);
424         }
425
449017 426         // 本次更新日志
558ffc 427         ProjectPackageHistoryEntity projectPackageHistoryEntity = new ProjectPackageHistoryEntity();
D 428         projectPackageHistoryEntity.setId(historyId);
429         projectPackageHistoryEntity.setProjectId(projectId);
430         projectPackageHistoryEntity.setFileName(zipFileName);
431         projectPackageHistoryEntity.setLog(logs);
432         projectPackageHistoryEntity.setVersion(version);
433         projectPackageHistoryEntity.setModelNames(entities.stream().map(MpkFileDTO::getPyName).collect(Collectors.joining(",")));
434         projectPackageHistoryEntity.setCreateTime(new Date());
449017 435         // 生成更新日志
558ffc 436         createLog(projectId, projectName, dirPath.getAbsolutePath(), projectPackageHistoryEntity, version);
449017 437         // 打zip包
558ffc 438         String zipPath = mpkTenantBakFilePath + File.separator + zipFileName;
8b3ee3 439         ZipUtil.zip(dirPath.getAbsolutePath(), zipPath);
449017 440         byte[] bytes = FileUtil.readBytes(zipPath);
D 441         // 记录打包日志
558ffc 442         projectPackageHistoryEntity.setFilePath(zipPath);
D 443         projectPackageHistoryService.insert(projectPackageHistoryEntity);
449017 444         // 插入打包历史-模型关联表
D 445         List<ProjectPackageHistoryModelEntity> historyModelList = new ArrayList<>(entities.size());
446         entities.forEach(e -> {
447             ProjectPackageHistoryModelEntity entity = new ProjectPackageHistoryModelEntity();
448             entity.setId(UUID.randomUUID().toString());
449             entity.setProjectId(projectId);
450             entity.setPackageHistoryId(historyId);
451             entity.setPyName(e.getPyName());
067d7a 452             entity.setPyChineseName(e.getPyChineseName());
449017 453             entity.setPkgName(e.getPkgName());
D 454             entity.setPyModule(e.getPyModule());
455             entity.setRemark(e.getRemark());
0255ea 456             List<ModelMethodDTO> methods = e.getModelMethods();
449017 457             if (!CollectionUtils.isEmpty(methods)) {
D 458                 entity.setMethodInfo(JSON.toJSONString(methods));
459             }
460             historyModelList.add(entity);
461         });
558ffc 462         projectPackageHistoryModelService.insertList(historyModelList);
449017 463         // 删除临时文件
D 464         FileUtils.deleteDirectory(dirPath);
465         return bytes;
466     }
467
1fea3e 468     private void createDllFile(String dirPath, List<String> cppFilePaths, String dllSavePath) {
D 469         try {
470             String paths = cppFilePaths.stream().collect(Collectors.joining(" "));
471             String command = "cl /LD " + paths + " /EHsc /o " + dllSavePath + " /link " + "IAIL.MDK.Mid.Windows.lib";
472             log.info("执行cmd命令生成dll:" + command);
473             ProcessBuilder builder = new ProcessBuilder("cmd", "/c", command);
474             builder.directory(new File(dirPath + File.separator + MdkConstant.LIBS));
475             Process process = builder.start();
476             // 获取命令输出结果
477             InputStream inputStream = process.getInputStream();
478             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK")); // 设置编码为GBK
479             String line;
480             while ((line = reader.readLine()) != null) {
481                 log.info(line);
482             }
483             // 等待命令执行完成
484             process.waitFor();
485         } catch (Exception e) {
912a1e 486             throw new RuntimeException("执行cmd命令生成dll异常",e);
f7932f 487         }
D 488     }
489
449017 490     @Override
8b3ee3 491     public Map<String, String> savePyFile(MultipartFile file) throws IOException {
558ffc 492         Long tenantId = TenantContextHolder.getTenantId();
D 493         // 备份文件 租户隔离
494         String mpkTenantBakFilePath = mpkBakFilePath + File.separator + tenantId;
495
496         File dir = new File(mpkTenantBakFilePath);
449017 497         if (!dir.exists()) {
D 498             dir.mkdirs();
499         }
500         String fileName = file.getOriginalFilename();
1fea3e 501         String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
D 502         File saveFile = new File(dir.getAbsolutePath() + File.separator + UUID.randomUUID() + fileSuffix);
503
449017 504         saveFile.createNewFile();
D 505         // 保存
506         file.transferTo(saveFile);
507
8b3ee3 508         Map<String, String> result = new HashMap<>(2);
509         result.put("filePath", saveFile.getAbsolutePath());
449017 510         result.put("fileName", fileName);
D 511
512         return result;
513     }
514
c12dae 515     @Override
D 516     public CommonResult<String> publish(Map<String, Object> params) {
517         String historyId = (String) params.get("historyId");
518         String projectId = (String) params.get("projectId");
519
520         // 判断新的dll和jar文件是否存在
558ffc 521         String jarFileBakPath = mpkBakFilePath + File.separator + MdkConstant.PROJECT_UNPUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar";
D 522         String dllFileBakPath = mpkBakFilePath + File.separator + MdkConstant.PROJECT_UNPUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll";
c12dae 523         if (!FileUtil.exist(jarFileBakPath)) {
D 524             throw new RuntimeException("jar文件不存在," + jarFileBakPath);
525         }
526         if (!FileUtil.exist(dllFileBakPath)) {
527             throw new RuntimeException("dll文件不存在" + dllFileBakPath);
528         }
529
530         try {
531             // 卸载之前的dll和jar
532             DllUtils.removeClassLoaderCache(projectId);
533             // 删除之前的dll和jar备份文件
534             DllUtils.removeOldFile(mpkBakFilePath + File.separator + MdkConstant.PROJECT_PUBLISH,projectId);
535         } catch (Exception e) {
536             throw new RuntimeException("卸载之前的dll和jar异常",e);
537         }
538
539         // 备份新的dll和jar
540         String jarFilePath = mpkBakFilePath + File.separator + MdkConstant.PROJECT_PUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar";
541         String dllFilePath = mpkBakFilePath + File.separator + MdkConstant.PROJECT_PUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll";
542         FileUtil.copy(jarFileBakPath,jarFilePath,true);
543         FileUtil.copy(dllFileBakPath,dllFilePath,true);
544
545         URLClassLoader urlClassLoader = null;
546         try {
547             // 加载新的jar
548             urlClassLoader = DllUtils.loadJar(jarFilePath);
549         } catch (Exception e) {
550             throw new RuntimeException("加载新的jar异常",e);
551         }
552
553         try {
554             // 加载新的dll
555             DllUtils.loadDll(urlClassLoader.loadClass("iail.mdk.model.common.Environment"),dllFilePath);
556         } catch (Exception e) {
557             DllUtils.unloadJar(urlClassLoader);
558             throw new RuntimeException("加载新的dll异常",e);
559         }
560         // 都加载成功后加入缓存
561         DllUtils.addClassLoaderCache(projectId,urlClassLoader);
562
563         return CommonResult.success();
564     }
565
558ffc 566     private void createLog(String projectId, String projectName, String dirPath, ProjectPackageHistoryEntity projectPackageHistoryEntity, String version) {
8b3ee3 567         Map<String, Object> map = new HashMap<>();
568         map.put("projectId", projectId);
558ffc 569         List<ProjectPackageHistoryEntity> list = projectPackageHistoryService.list(map);
D 570         list.add(projectPackageHistoryEntity);
449017 571         // 按照日期分组再排序
558ffc 572         HashMap<String, List<ProjectPackageHistoryEntity>> dataMap = list.stream().collect(
449017 573                 Collectors.groupingBy(e -> DateUtils.format(e.getCreateTime(), DateUtils.DATE_PATTERN_POINT),
8b3ee3 574                         LinkedHashMap::new,
558ffc 575                         Collectors.collectingAndThen(Collectors.toList(), e -> e.stream().sorted(Comparator.comparing(ProjectPackageHistoryEntity::getCreateTime)).collect(Collectors.toList()))));
449017 576
D 577         Map<String, Object> data = new HashMap<>();
8b3ee3 578         data.put("dataMap", dataMap);
579         data.put("projectName", projectName);
580         data.put("version", version);
581         data.put("now", DateUtils.format(new Date(), DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND));
449017 582
D 583         File logFile = new File(dirPath + File.separator + "更新日志.txt");
8b3ee3 584         GenUtils.drawTemplate("log.txt.vm", data, logFile);
449017 585     }
D 586
3009e2 587     private String pkgJar(String dirPath) {
D 588         try {
589             String jarSavePath = dirPath + File.separator + MdkConstant.LIBS + File.separator + "IAILMDK.jar";
590             StringBuilder sb = new StringBuilder();
591             sb.append("jar -cvf");
592             sb.append(" ").append(jarSavePath);
593             sb.append(" -C ").append(dirPath).append(File.separator).append("IAILMDK").append(File.separator).append(" .");
594             log.info("执行cmd命令打jar包:" + sb);
595             Process process = RuntimeUtil.exec(sb.toString());
596             process.waitFor();
597             return jarSavePath;
598         } catch (InterruptedException e) {
912a1e 599             throw new RuntimeException("执行cmd命令打jar包异常",e);
3009e2 600         }
449017 601     }
D 602
603     private void deleteJavaFile(List<String> javaFilePaths) {
604         for (String javaFilePath : javaFilePaths) {
605             FileUtil.del(javaFilePath);
606         }
607     }
608
3009e2 609     private void createClassFile(List<String> javaFilePaths){
D 610         try {
611             StringBuilder sb = new StringBuilder();
612             sb.append("javac -encoding utf-8");
613             for (String path : javaFilePaths) {
614                 sb.append(" ").append(path);
615             }
616             log.info("执行cmd命令生成class:" + sb);
617             Process process = RuntimeUtil.exec(sb.toString());
618             process.waitFor();
619         } catch (InterruptedException e) {
912a1e 620             throw new RuntimeException("执行cmd命令生成class异常",e);
449017 621         }
D 622     }
623 }