package com.product.patch.service; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; import com.product.common.io.FileUtils; import com.product.common.lang.StringUtils; import com.product.core.config.Global; import com.product.core.dao.BaseDao; import com.product.core.entity.DataTableEntity; import com.product.core.entity.FieldSetEntity; import com.product.core.exception.BaseException; import com.product.core.service.support.AbstractBaseService; import com.product.patch.config.CmnConst; import com.product.patch.config.ErrorCode; import com.product.patch.service.idel.IPatchExtractService; import com.product.patch.util.RSAUtil; import com.product.util.BaseUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.File; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; /** * Copyright © 6c * * @Date: 2022-04-02 16:59 * @Author: 6c * @Description: 补丁抽取 */ @Service public class PatchExtractService extends AbstractBaseService implements IPatchExtractService { @Autowired private BaseDao baseDao; public void testExtract() { FieldSetEntity fse = new FieldSetEntity(); fse.setTableName("temp_table"); fse.setValue(CmnConst.FIELD_CLIENT_UUID, "a34f8818-d36d-4d82-b1b0-dbc0d2e70a03"); fse.setValue("deploy_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); fse.setValue("operator", "admin"); JSONObject paramObj = new JSONObject(); // 表数据 JSONObject tableReportObj = new JSONObject(); tableReportObj.put("6c_test_contract", "id<5"); tableReportObj.put("6c_test_renewal", "id<3"); paramObj.put(CmnConst.PARAM_TABLE_REPORT, tableReportObj.toJSONString()); // 表结构 JSONArray tableStructureArray = new JSONArray(); JSONObject tableStructureObj = new JSONObject(); tableStructureObj.put("table_name", "6c_test_contract"); tableStructureObj.put("field", "title,money"); tableStructureObj.put("index", "id,uuid"); tableStructureArray.add(tableStructureObj); paramObj.put(CmnConst.PARAM_TABLE_REPORT, tableStructureArray.toJSONString()); // 功能建模 JSONObject functionObj = new JSONObject(); functionObj.put("c4abd684-0788-4a39-9422-3c24bc73d2bc", "1,2,3"); functionObj.put("d0edf393-db19-44b1-87aa-95d28751b0d8", "1,2"); tableStructureArray.add(functionObj); paramObj.put(CmnConst.PARAM_FUNCTION, functionObj.toJSONString()); // 流程建模 JSONObject flowObj = new JSONObject(); flowObj.put("7c93182a-d091-4a07-b223-56b9bb9fcde8", "1,2,3"); tableStructureArray.add(functionObj); paramObj.put(CmnConst.PARAM_FLOW, flowObj.toJSONString()); fse.setValue(CmnConst.DATA, paramObj); extract(fse); } /** * 获取表、视图、索引信息 * @return */ public JSONObject listTableInfo() { String dataBaseName = baseDao.getDataBaseName(); JSONObject resultObj = new JSONObject(); StringBuilder sql = new StringBuilder(512); sql.append("\nselect table_name"); sql.append("\nfrom information_schema.`TABLES`"); sql.append("\nwhere table_schema=?"); sql.append("\nand table_type='BASE TABLE'"); sql.append("\norder by table_name"); DataTableEntity dte = baseDao.listTable(sql.toString(), new Object[]{dataBaseName}); resultObj.put(CmnConst.PARAM_TABLE_REPORT, BaseUtil.dataTableEntityToJson(dte)); sql.setLength(0); sql.append("\nselect *"); sql.append("\nfrom ("); sql.append("\n select table_name,1 table_type,1 operate_type,column_name name"); sql.append("\n from information_schema.`COLUMNS`"); sql.append("\n where table_schema=?"); sql.append("\n and table_name in ("); sql.append("\n select table_name"); sql.append("\n from information_schema.`TABLES`"); sql.append("\n where table_schema=?"); sql.append("\n and table_type='BASE TABLE'"); sql.append("\n )"); sql.append("\n union all"); sql.append("\n select table_name,1 table_type,2 operate_type,column_name name"); sql.append("\n from information_schema.`STATISTICS`"); sql.append("\n where table_schema=?"); sql.append("\n and table_name in ("); sql.append("\n select table_name"); sql.append("\n from information_schema.`TABLES`"); sql.append("\n where table_schema=?"); sql.append("\n and table_type='BASE TABLE'"); sql.append("\n )"); sql.append("\n union all"); sql.append("\n select table_name,2 table_type,null,null"); sql.append("\n from information_schema.`VIEWS`"); sql.append("\n where table_schema=?"); sql.append("\n order by table_name"); sql.append("\n) t"); sql.append("\norder by table_type,table_name,operate_type,name"); dte = baseDao.listTable(sql.toString(), new Object[]{dataBaseName, dataBaseName, dataBaseName, dataBaseName, dataBaseName}); resultObj.put(CmnConst.PARAM_TABLE_STRUCTURE, BaseUtil.dataTableEntityToJson(dte)); sql.setLength(0); sql.append("\nselect uuid,tricode,function_name,t.*"); sql.append("\nfrom product_sys_functions f,("); sql.append("\n select \"按钮\" type union all select \"页面\" union all select \"连线\""); sql.append("\n) t"); sql.append("\nwhere data_type=1"); sql.append("\norder by tricode"); dte = baseDao.listTable(sql.toString(), new Object[]{}); resultObj.put(CmnConst.PARAM_FUNCTION, BaseUtil.dataTableEntityToJson(dte)); sql.setLength(0); sql.append("\nselect uuid,title,t.*"); sql.append("\nfrom product_sys_flow_model f,("); sql.append("\n select \"节点\" type union all select \"处理器\" union all select \"连线\""); sql.append("\n) t"); sql.append("\nwhere length(type_code)>0"); sql.append("\norder by title"); dte = baseDao.listTable(sql.toString(), new Object[]{}); resultObj.put(CmnConst.PARAM_FLOW, BaseUtil.dataTableEntityToJson(dte)); return resultObj; } /** * 补丁抽取 * @param fse */ public void extract(FieldSetEntity fse) { String aimClientUUID = fse.getString(CmnConst.FIELD_CLIENT_UUID); if (StringUtils.isEmpty(aimClientUUID)) { throw new BaseException(ErrorCode.EXTRACT_NO_AIM_CLIENT_UUID); } JSONObject paramObj = JSON.parseObject(fse.getString(CmnConst.DATA)); JSONArray resultArray = new JSONArray(); // 表数据 resultArray.addAll(extractTableRecord(paramObj.getJSONObject(CmnConst.PARAM_TABLE_REPORT))); // 表结构 resultArray.addAll(extractTableStructure(paramObj.getJSONArray(CmnConst.PARAM_TABLE_STRUCTURE))); // 功能建模 resultArray.addAll(extractFunction(paramObj.getJSONArray(CmnConst.PARAM_FUNCTION))); // 流程建模 resultArray.addAll(extractTableStructure(paramObj.getJSONArray(CmnConst.PARAM_FLOW))); Date deployDate = fse.getDate(CmnConst.PARAM_DEPLOY_DATE); String operator = fse.getString(CmnConst.PARAM_OPERATOR); writeToFile(resultArray.toString(), deployDate, operator, aimClientUUID); } /** * 表数据 * @param paramObj */ private JSONArray extractTableRecord(JSONObject paramObj) { DataTableEntity dte; JSONArray resultArray = new JSONArray(); for (Map.Entry entry : paramObj.entrySet()) { dte = baseDao.listTable(entry.getKey(), entry.getValue() == null ? "" : entry.getValue().toString(), new Object[]{}); resultArray.addAll(dte.toJson()); } return resultArray; } /** * 表结构 * @param paramArr */ private JSONArray extractTableStructure(JSONArray paramArr) { JSONArray resultArray = new JSONArray(); JSONObject resultObj; JSONObject tempObj; for (Object obj : paramArr) { tempObj = (JSONObject) obj; if ("1".equals(tempObj.getString(CmnConst.TABLE_TYPE))) { // 表 if ("1".equals(tempObj.getString(CmnConst.OPERATE_TYPE))) { // 字段 resultObj = getTable(tempObj); } else if ("2".equals(tempObj.getString(CmnConst.OPERATE_TYPE))) { // 索引 resultObj = getIndex(tempObj); } else { throw new BaseException(ErrorCode.EXTRACT_INVALID_OPERATE_TYPE); } } else if ("2".equals(tempObj.getString(CmnConst.TABLE_TYPE))) { // 视图 resultObj = getView(tempObj); } else { throw new BaseException(ErrorCode.EXTRACT_INVALID_TABLE_TYPE); } if (resultObj != null && !resultObj.isEmpty()) { resultArray.add(resultObj); } } return resultArray; } /** * 表结构-字段 * @param jsonObject * @return */ private JSONObject getTable(JSONObject jsonObject) { String name = jsonObject.getString(CmnConst.NAME); if (StringUtils.isEmpty(name)) { return new JSONObject(); } String[] nameArr = name.split(","); String dataBaseName = baseDao.getDataBaseName(); List paramList = Lists.newArrayList(); paramList.add(dataBaseName); paramList.add(jsonObject.getString(CmnConst.TABLE_NAME)); paramList.addAll(Arrays.asList(nameArr)); String filter = String.format("%s=? and %s='%s' and %s=? and %s", CmnConst.DATABASE_COLUMN, CmnConst.TABLE_TYPE_COLUMN, CmnConst.TABLE_TYPE_TABLE, CmnConst.TABLE_NAME, BaseUtil.buildQuestionMarkFilter(CmnConst.COLUMNS_NAME_COLUMN, nameArr.length, true)); String tableName = String.format("%s.`%s`", CmnConst.DATABASE, CmnConst.TABLE); FieldSetEntity fse = baseDao.getFieldSetByFilter(tableName, filter, paramList.toArray(), false); return BaseUtil.fieldSetEntityToJson(fse); } /** * 表结构-索引 * @param jsonObject * @return */ private JSONObject getIndex(JSONObject jsonObject) { String name = jsonObject.getString(CmnConst.NAME); if (StringUtils.isEmpty(name)) { return new JSONObject(); } String[] nameArr = name.split(","); String dataBaseName = baseDao.getDataBaseName(); List paramList = Lists.newArrayList(); paramList.add(dataBaseName); paramList.add(jsonObject.getString(CmnConst.TABLE_NAME)); paramList.addAll(Arrays.asList(nameArr)); String filter = String.format("%s=? and %s=? and %s=?", CmnConst.DATABASE_COLUMN, CmnConst.TABLE_NAME, BaseUtil.buildQuestionMarkFilter(CmnConst.INDEX_NAME_COLUMN, nameArr.length, true)); String tableName = String.format("%s.`%s`", CmnConst.DATABASE, CmnConst.INDEX); FieldSetEntity fse = baseDao.getFieldSetByFilter(tableName, filter, paramList.toArray(), false); return BaseUtil.fieldSetEntityToJson(fse); } /** * 表结构-视图 * @param jsonObject * @return */ private JSONObject getView(JSONObject jsonObject) { String name = jsonObject.getString(CmnConst.NAME); if (StringUtils.isEmpty(name)) { return new JSONObject(); } String[] nameArr = name.split(","); String dataBaseName = baseDao.getDataBaseName(); List paramList = Lists.newArrayList(); paramList.add(dataBaseName); paramList.add(jsonObject.getString(CmnConst.TABLE_NAME)); paramList.addAll(Arrays.asList(nameArr)); String filter = String.format("%s=? and %s=? and %s=?", CmnConst.DATABASE_COLUMN, CmnConst.TABLE_NAME, BaseUtil.buildQuestionMarkFilter(CmnConst.INDEX_NAME_COLUMN, nameArr.length, true)); String tableName = String.format("%s.`%s`", CmnConst.DATABASE, CmnConst.VIEWS); FieldSetEntity fse = baseDao.getFieldSetByFilter(tableName, filter, paramList.toArray(), false); return BaseUtil.fieldSetEntityToJson(fse); } /** * 功能建模 * @param paramArr * @return */ private JSONArray extractFunction(JSONArray paramArr) { JSONArray resultArray = new JSONArray(); JSONObject paramObj; for (int i = 0;i < paramArr.size();i++) { paramObj = paramArr.getJSONObject(i); // todo // resultArray.add(); } return resultArray; } /** * 补丁输出到文件 * @param patchContent * @param deployDate * @param operator * @param clientUUID */ private void writeToFile(String patchContent, Date deployDate, String operator, String clientUUID) { deployDate = deployDate == null ? new Date() : deployDate; operator = StringUtils.isEmpty(operator) ? "admin" : operator; String patchDir = Global.getSystemConfig("patch.extract.dir",""); File dir = new File(patchDir); dir.mkdirs(); String deployDateStr = new SimpleDateFormat(CmnConst.DATE_FORMAT_1).format(deployDate); String fileName = patchDir + File.separator + deployDateStr + "-" + operator + ".patch"; File file = new File(fileName); boolean appendFlag = false; if (file.exists()) { appendFlag = true; } else { try { file.createNewFile(); } catch (Exception e) { throw new BaseException(ErrorCode.EXTRACT_CREATE_FILE_FAIL); } } StringBuilder content = new StringBuilder(1024); content.append(deployDateStr).append("-").append(operator).append(";\n") .append(patchContent); String encodedData = content.toString(); // 加密 FieldSetEntity mainFse = baseDao.getFieldSetEntityByFilter(CmnConst.TABLE_PRODUCT_SYS_ORG_LEVELS, "org_level_id=1", new Object[]{}, false); FieldSetEntity mainCryptFse = baseDao.getFieldSetEntityByFilter(CmnConst.TABLE_PRODUCT_SYS_PATCH_KEY, "org_level_uuid=?", new Object[]{mainFse.getUUID()}, false); String mainPrivateKey = mainCryptFse.getString(CmnConst.FIELD_PIRVATE_KEY); FieldSetEntity clientCryptFse = baseDao.getFieldSetEntityByFilter(CmnConst.TABLE_PRODUCT_SYS_PATCH_KEY, "org_level_uuid=?", new Object[]{clientUUID}, false); String clientPublicKey = clientCryptFse.getString(CmnConst.FIELD_PUBLIC_KEY); try { encodedData = RSAUtil.privateEncrypt(encodedData, RSAUtil.getPrivateKey(mainPrivateKey)); encodedData = RSAUtil.publicEncrypt(encodedData, RSAUtil.getPublicKey(clientPublicKey)); } catch (Exception e) { e.printStackTrace(); throw new BaseException(ErrorCode.EXTRACT_ENCODE_FAIL); } FileUtils.writeToFile(fileName, encodedData, "utf-8", appendFlag); } }