diff --git a/build.gradle b/build.gradle index 5e3141a4ef..ac330091bd 100644 --- a/build.gradle +++ b/build.gradle @@ -62,6 +62,22 @@ allprojects { } dependencies { + // 平台前端的jar + implementation 'com.fr.decision:fine-decision-webui:' + frVersion + implementation 'com.fr.webui:fine-webui:' + frVersion + // 报表前端依赖 + implementation 'com.fr.decision:fine-decision-report-webui:' + frVersion + //认证单点依赖 + implementation "org.jasig.cas.client:cas-client-core:3.6.4" + implementation "cas:casclient:2.0.11" + // 门户依赖前端 + implementation 'com.fr.portal:fine-portal-webui:' + apiVersion + //消息中心前端 + implementation 'com.fr.messenger:fine-messenger-webui:' + apiVersion + // 注册前端依赖 + implementation 'com.fr.license:fine-license-webui:' + apiVersion + // 认证前端依赖 + implementation 'com.fr.auth:fine-auth-webui:' + apiVersion implementation 'com.fr.essential:fine-essential:' + cbbVersion implementation 'com.fr.cbb:fine-universal-skeleton:' + cbbVersion implementation 'com.fr.plugin:fine-plugin-api:' + apiVersion @@ -88,7 +104,7 @@ allprojects { implementation 'com.fr.activator:fine-activator:' + frVersion implementation 'com.fr.datasource:fine-datasource-api:' + fdlVersion implementation 'com.fr.datasource:fine-datasource-core:' + fdlVersion - implementation 'com.fr.decision:fine-decision:' + frVersion + implementation 'com.fr.decision:decision-i18n:' + frVersion implementation 'com.fr.schedule:fine-schedule:' + frVersion implementation 'com.fr.report:engine-report:' + frDevVersion implementation 'com.fr.report:engine-x:' + frDevVersion diff --git a/designer-base/src/main/java/com/fr/decision/update/SyncExecutor.java b/designer-base/src/main/java/com/fr/decision/update/SyncExecutor.java new file mode 100644 index 0000000000..2c802a937d --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/SyncExecutor.java @@ -0,0 +1,62 @@ +package com.fr.decision.update; + +import com.fr.decision.update.backup.Recover; +import com.fr.decision.update.backup.RecoverForSync; +import com.fr.decision.update.command.SyncCommandHandler; +import com.fr.decision.update.data.UpdateConstants; +import com.fr.decision.update.info.UpdateCallBack; +import com.fr.general.CommonIOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ProjectLibrary; +import com.fr.stable.StableUtils; +import com.fr.stable.project.ProjectConstants; + +import java.io.File; + +/** + * SyncExecutor + * + * @author pengda + * @since 10.0 + * Created on 2021/6/02 + */ +public class SyncExecutor { + private static final SyncExecutor INSTANCE = new SyncExecutor(); + private SyncCommandHandler sycHandler; + private Recover recoverForSync; + + private SyncExecutor() { + sycHandler = SyncCommandHandler.getInstance(); + recoverForSync = RecoverForSync.getInstance(); + } + + /** + * 获取单例 + */ + public static SyncExecutor getInstance() { + return INSTANCE; + } + + /** + * 执行 + */ + public boolean execute(UpdateCallBack callBack, String fullBuildNo) { + String dir = StableUtils.pathJoin(ProjectLibrary.getInstance().getLibHome(),ProjectConstants.ASSIST_NAME, UpdateConstants.ENV_LIB); + try { + if (fullBuildNo != null) { + if (recoverForSync.backup()) { + if (sycHandler.execute(callBack, fullBuildNo)) { + return true; + } + recoverForSync.recover(); + } + } + return false; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return false; + } finally { + CommonIOUtils.deleteFile(new File(dir)); + } + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/UpdateExecutor.java b/designer-base/src/main/java/com/fr/decision/update/UpdateExecutor.java new file mode 100644 index 0000000000..ddffd77c88 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/UpdateExecutor.java @@ -0,0 +1,60 @@ +package com.fr.decision.update; + +import com.fr.decision.update.backup.Recover; +import com.fr.decision.update.backup.RecoverHandler; +import com.fr.decision.update.command.Command; +import com.fr.decision.update.command.CommandHandler; +import com.fr.decision.update.data.UpdateConstants; +import com.fr.decision.update.exception.UpdateException; +import com.fr.decision.update.info.UpdateCallBack; +import com.fr.io.utils.ResourceIOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StableUtils; +import com.fr.stable.project.ProjectConstants; + +/** + * UpdateExecutor + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public class UpdateExecutor { + + + private static final UpdateExecutor INSTANCE = new UpdateExecutor(); + + private Command updateHandler; + + private Recover recoverHandler; + + private UpdateExecutor() { + updateHandler = CommandHandler.getInstance(); + recoverHandler = RecoverHandler.getInstance(); + } + + public static UpdateExecutor getInstance() { + return INSTANCE; + } + + public boolean execute(UpdateCallBack callBack) { + String dir = StableUtils.pathJoin(ProjectConstants.ASSIST_NAME,UpdateConstants.ENV_LIB); + try { + if (recoverHandler.backup()) { + if (updateHandler.execute(callBack)) { + return true; + }else { + recoverHandler.recover(); + return false; + } + } + return false; + } catch (Exception e) { + UpdateException exception = new UpdateException(e.getMessage()); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + return false; + } finally { + ResourceIOUtils.delete(dir); + } + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/acquirer/AbstractAcquirer.java b/designer-base/src/main/java/com/fr/decision/update/acquirer/AbstractAcquirer.java new file mode 100644 index 0000000000..be92349ce1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/acquirer/AbstractAcquirer.java @@ -0,0 +1,81 @@ +package com.fr.decision.update.acquirer; + +import com.fanruan.product.ProductConstants; +import com.fr.base.j2v8.J2V8Utils; +import com.fr.decision.update.command.SyncCommandHandler; +import com.fr.decision.update.data.UpdateConstants; +import com.fr.general.GeneralUtils; +import com.fr.module.ModuleContext; +import com.fr.stable.ProjectLibrary; +import com.fr.stable.StableUtils; +import com.fr.stable.os.AbstractOperatingSystem; +import com.fr.stable.os.Arch; +import com.fr.stable.os.OperatingSystem; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * AbstractAcquirer + * + * @author richie + * @since 10.0 + * Created on 2019/4/24 + */ +public abstract class AbstractAcquirer implements Acquirer { + + private static final AbstractOperatingSystem os = OperatingSystem.getOperatingSystem(); + + private static final Map JS_PROPERTIES = new ConcurrentHashMap<>(); + + protected Map normalProperties() { + Map map = new HashMap<>(JS_PROPERTIES); + map.put("$build", GeneralUtils.readFullBuildNO()); + map.put("$version", ProductConstants.VERSION); + map.put("$installHome", StableUtils.getInstallHome()); + map.put("$envHome", envHome()); + map.put("$os", os.getType().getName()); + map.put("$arch", arch()); + map.put("$type", type()); + map.put("$engine", engine()); + map.put("$time", getBranchTime()); + return map; + } + + public static void registerJsProperties(String key, String value) { + JS_PROPERTIES.put(key, value); + } + + private static String arch() { + if (os.getArch() == Arch.x86) { + return UpdateConstants.ARCH_X86; + } else if (os.getArch() == Arch.x86_64) { + return UpdateConstants.ARCH_X86_64; + } else if (os.getArch() == Arch.ARM) { + return UpdateConstants.ARM; + } else { + return UpdateConstants.UNKNOWNOS; + } + } + + private static String type() { + if (ModuleContext.isDesignerStartup()) { + return UpdateConstants.DESIGNER; + } else { + return UpdateConstants.DECISION; + } + } + + private static String engine() { + return J2V8Utils.SUPPORT_J2V8 ? UpdateConstants.J2V8 : UpdateConstants.NASHORN; + } + + private static String envHome() { + return ProjectLibrary.getInstance().getLibHome(); + } + + private static String getBranchTime() { + return SyncCommandHandler.getInstance().getBranchTime(); + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/acquirer/Acquirer.java b/designer-base/src/main/java/com/fr/decision/update/acquirer/Acquirer.java new file mode 100644 index 0000000000..138214c538 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/acquirer/Acquirer.java @@ -0,0 +1,42 @@ +package com.fr.decision.update.acquirer; + +import com.fr.decision.update.data.FinallyObject; + +/** + * 更新配置检查接口 + * + * @author richie + * @since 10.0 + * Created on 2019/4/24 + */ +public interface Acquirer { + + String OPERATE_ADD = "add"; + + String OPERATE_DELETE = "deletes"; + + String OPERATE_MODIFY = "modify"; + + String TYPE_SOURCE = "source"; + + String TYPE_TARGET = "target"; + + /** + * 准备运行环境 + */ + void prepare(); + + /** + * 获取运行环境名称. + * + * @return 运行环境名称 + */ + String getName(); + + /** + * 根据配置脚本,获取各类待处理的文件 + * @param script 配置脚本 + * @return 待处理文件集合 + */ + FinallyObject execute(String script) throws IllegalStateException; +} diff --git a/designer-base/src/main/java/com/fr/decision/update/acquirer/AcquirerExecutorService.java b/designer-base/src/main/java/com/fr/decision/update/acquirer/AcquirerExecutorService.java new file mode 100644 index 0000000000..0d3afd3316 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/acquirer/AcquirerExecutorService.java @@ -0,0 +1,24 @@ +package com.fr.decision.update.acquirer; + +import com.fr.concurrent.NamedThreadFactory; +import com.fr.decision.update.operate.AcquirerTask; +import com.fr.module.ModuleContext; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +/** + * 任务执行服务管理器 + * + * @author richie + * @since 10.0 + * Created on 2019/8/16 + */ +public class AcquirerExecutorService { + + private static ExecutorService executorService = ModuleContext.getExecutor().newSingleThreadExecutor((new NamedThreadFactory("AcquirerExecutorService"))); + + public static Future registerJob(AcquirerTask task) { + return executorService.submit(task); + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/acquirer/AcquirerSelector.java b/designer-base/src/main/java/com/fr/decision/update/acquirer/AcquirerSelector.java new file mode 100644 index 0000000000..fb81d0816d --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/acquirer/AcquirerSelector.java @@ -0,0 +1,26 @@ +package com.fr.decision.update.acquirer; + +import com.fr.base.j2v8.J2V8Utils; +import com.fr.decision.update.agent.EmbedConfigAcquirer; +import com.fr.decision.update.agent.V8ConfigAcquirer; + +/** + * 配置读取器AcquirerSelector + * + * @author richie + * @since 10.0 + * Created on 2019/4/24 + */ +public class AcquirerSelector { + + public static final boolean SUPPORT_J2V8 = J2V8Utils.SUPPORT_J2V8; + + /** + * 根据情况选择不同的配置读取器 + * + * @return 配置读取器 + */ + public static Acquirer select() { + return J2V8Utils.SUPPORT_J2V8 ? new V8ConfigAcquirer() : new EmbedConfigAcquirer(); + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/acquirer/JSEngine.java b/designer-base/src/main/java/com/fr/decision/update/acquirer/JSEngine.java new file mode 100644 index 0000000000..97270a0ef6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/acquirer/JSEngine.java @@ -0,0 +1,58 @@ +package com.fr.decision.update.acquirer; + +import com.fr.decision.update.data.FinallyObject; +import com.fr.decision.update.exception.UpdateException; +import com.fr.general.IOUtils; +import com.fr.general.http.HttpToolbox; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.EncodeConstants; + +import java.io.IOException; +import java.io.InputStream; + +/** + * JSEngine + * + * @author Bryant + * @since 10.0 + * Created on 2019/8/25 + */ +public class JSEngine { + + private static final JSEngine engine = new JSEngine(); + + private JSEngine() {} + + public static JSEngine getEngine() { + return engine; + } + + /** + * 获取JS引擎名称. + * + * @return JS引擎名称 + */ + public static String getEngineName() { + return AcquirerSelector.select().getName(); + } + + public FinallyObject executeJS(String url) { + try { + Acquirer acquirer = AcquirerSelector.select(); + acquirer.prepare(); + InputStream in = HttpToolbox.download(url); + String script = IOUtils.inputStream2String(in, EncodeConstants.ENCODING_UTF_8); + FinallyObject finallyObject = null; + try { + finallyObject = acquirer.execute(script); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e,e.getMessage()); + } + return finallyObject; + } catch (IOException e) { + UpdateException exception = new UpdateException(e.getMessage()); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/acquirer/JSEngineInfo.java b/designer-base/src/main/java/com/fr/decision/update/acquirer/JSEngineInfo.java new file mode 100644 index 0000000000..4f6f0298a7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/acquirer/JSEngineInfo.java @@ -0,0 +1,49 @@ +package com.fr.decision.update.acquirer; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * 存储后台使用的JS引擎信息. + * + * @author Cloud.Liu + * @since 10.0 + * Created on 2020/12/15 + */ +public class JSEngineInfo { + + /** + * JS引擎信息. + * + *

+ * key: 模块
+ * value: 引擎名称 + *

+ */ + private static final Map INFO_MAP = new HashMap<>(); + + static { + // 注册平台使用的JS引擎信息 + registerJSEngineInfo("decision", JSEngine.getEngineName()); + } + + /** + * 注册JS引擎信息. + * + * @param module 模块名称 + * @param engine 引擎名称 + */ + public static void registerJSEngineInfo(String module, String engine) { + INFO_MAP.put(module, engine); + } + + /** + * 获取JS引擎信息. + * + * @return JS引擎信息 + */ + public static Map getInfoMap() { + return Collections.unmodifiableMap(INFO_MAP); + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/agent/EmbedConfigAcquirer.java b/designer-base/src/main/java/com/fr/decision/update/agent/EmbedConfigAcquirer.java new file mode 100644 index 0000000000..966adcfe82 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/agent/EmbedConfigAcquirer.java @@ -0,0 +1,84 @@ +package com.fr.decision.update.agent; + +import com.fr.decision.update.acquirer.AbstractAcquirer; +import com.fr.decision.update.data.FinallyObject; +import com.fr.decision.update.script.Files; +import com.fr.json.JSON; +import com.fr.json.JSONArray; +import com.fr.json.JSONFactory; +import com.fr.json.JSONObject; +import com.fr.script.Console; +import com.fr.script.ScriptFactory; + +import javax.script.ScriptEngine; +import javax.script.ScriptException; +import java.util.Map; + +/** + * EmbedConfigAcquirer + * + * @author richie + * @since 10.0 + * Created on 2019/4/24 + */ +public class EmbedConfigAcquirer extends AbstractAcquirer { + + /** + * 引擎名称. + */ + public static final String ENGINE_NAME = "nashorn"; + + private ScriptEngine scriptEngine = null; + + @Override + public void prepare() { + scriptEngine = ScriptFactory.newScriptEngine(); + scriptEngine.put("console", new Console()); + scriptEngine.put("files", new Files()); + Map globalVariables = normalProperties(); + for (Map.Entry entry : globalVariables.entrySet()) { + scriptEngine.put(entry.getKey(), entry.getValue()); + } + } + + @Override + public FinallyObject execute(String script) throws IllegalStateException { + try { + FinallyObject finallyObject = FinallyObject.create(); + JSONObject jsonObject = JSONFactory.createJSON(JSON.OBJECT, (String) scriptEngine.eval(script)); + JSONObject jo; + JSONArray array; + + array = jsonObject.getJSONArray(OPERATE_ADD); + if (array != null) { + for (int i=0; i { + String className = v8Array.getString(0); + try { + GeneralUtils.classForName(className); + return true; + } catch (ClassNotFoundException | NoClassDefFoundError e) { + return false; + } finally { + v8Array.release(); + } + }, "loadClass"); + V8Object v8Console = new V8Object(v8); + v8.add("console", v8Console); + Console console = new Console(); + InvokeUtils.registerJavaMethods(v8Console, console); + v8Console.release(); + V8Object v8Files = new V8Object(v8); + v8.add("Files", v8Files); + Files files = new Files(); + InvokeUtils.registerJavaMethods(v8Files, files); + v8Files.release(); + Map map = normalProperties(); + for (Map.Entry entry : map.entrySet()) { + v8.add(entry.getKey(), entry.getValue()); + } + } + + public FinallyObject execute(String config) throws IllegalStateException { + + FinallyObject finallyObject = FinallyObject.create(); + + try { + + V8Object returnV8Object = v8.executeObjectScript(config); + + V8Array addArray = returnV8Object.getArray(OPERATE_ADD); + if (!addArray.isUndefined()) { + for (int i = 0, len = addArray.length(); i < len; i++) { + V8Object addObject = addArray.getObject(i); + finallyObject.registerAdd(addObject.getString(TYPE_SOURCE), addObject.getString(TYPE_TARGET)); + addObject.release(); + } + addArray.release(); + } + + V8Array deleteArray = returnV8Object.getArray(OPERATE_DELETE); + if (!deleteArray.isUndefined()) { + for (int i = 0, len = deleteArray.length(); i < len; i++) { + finallyObject.registerDelete(deleteArray.getString(i)); + } + deleteArray.release(); + } + + V8Array modifyArray = returnV8Object.getArray(OPERATE_MODIFY); + if (!modifyArray.isUndefined()) { + for (int i = 0, len = modifyArray.length(); i < len; i++) { + V8Object modifyObject = modifyArray.getObject(i); + finallyObject.registerModify(modifyObject.getString(TYPE_SOURCE), modifyObject.getString(TYPE_TARGET)); + modifyObject.release(); + } + modifyArray.release(); + } + returnV8Object.release(); + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + v8.release(true); + } + return finallyObject; + } + + @Override + public String getName() { + return ENGINE_NAME; + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/backup/Recover.java b/designer-base/src/main/java/com/fr/decision/update/backup/Recover.java new file mode 100644 index 0000000000..f0872dec19 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/backup/Recover.java @@ -0,0 +1,15 @@ +package com.fr.decision.update.backup; + +/** + * 恢复备份接口 + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public interface Recover { + //恢复 + boolean recover(); + //备份 + boolean backup(); +} diff --git a/designer-base/src/main/java/com/fr/decision/update/backup/RecoverForCommon.java b/designer-base/src/main/java/com/fr/decision/update/backup/RecoverForCommon.java new file mode 100644 index 0000000000..92d930c4b8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/backup/RecoverForCommon.java @@ -0,0 +1,62 @@ +package com.fr.decision.update.backup; + +import com.fr.decision.update.data.UpdateConstants; +import com.fr.decision.update.exception.UpdateException; +import com.fr.general.CommonIOUtils; +import com.fr.io.utils.ResourceIOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ProjectLibrary; +import com.fr.stable.StableUtils; +import com.fr.stable.project.ProjectConstants; + +import java.io.IOException; + +/** + * RecoverForCommon + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public class RecoverForCommon implements Recover { + + private String envHome; + + RecoverForCommon() { + this.envHome = ProjectLibrary.getInstance().getLibHome(); + } + + @Override + public boolean recover() { + try{ + //当出现一些奇怪的问题时,从备份的jar中还原所有jar + CommonIOUtils.copyFilesInDirByPath(StableUtils.pathJoin(envHome,ProjectConstants.ASSIST_NAME,UpdateConstants.ENV_LIB,UpdateConstants.BACKUPPATH), + StableUtils.pathJoin(envHome,ProjectConstants.LIB_NAME)); + FineLoggerFactory.getLogger().error("Recover down for common"); + return true; + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage() , "Recover error for common", e); + return false; + } + } + + @Override + public boolean backup() { + try { + String envLib = StableUtils.pathJoin(ProjectConstants.ASSIST_NAME, UpdateConstants.ENV_LIB); + if (ResourceIOUtils.isDirectoryExist(envLib)) { + ResourceIOUtils.delete(envLib); + } + ResourceIOUtils.createDirectory(envLib); + ResourceIOUtils.createDirectory(StableUtils.pathJoin(envLib, UpdateConstants.DOWNLOADPATH)); + //更新之前先备份原来的jar包(设计器与平台公用的lib) + ResourceIOUtils.copy(ProjectConstants.LIB_NAME, StableUtils.pathJoin(envLib, UpdateConstants.BACKUPPATH)); + FineLoggerFactory.getLogger().error("Backup down for common yes"); + return true; + } catch (IOException e) { + UpdateException exception = new UpdateException("BackUp Exception " + e.getMessage()); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + return false; + } + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/backup/RecoverForSync.java b/designer-base/src/main/java/com/fr/decision/update/backup/RecoverForSync.java new file mode 100644 index 0000000000..459994a4ac --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/backup/RecoverForSync.java @@ -0,0 +1,65 @@ +package com.fr.decision.update.backup; + +import com.fr.decision.update.data.UpdateConstants; +import com.fr.decision.update.exception.UpdateException; +import com.fr.general.CommonIOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ProjectLibrary; +import com.fr.stable.StableUtils; +import com.fr.stable.project.ProjectConstants; + +import java.io.File; +import java.io.IOException; + +/** + * RecoverForSync + * + * @author pengda + * @since 10.0 + * Created on 2021/6/02 + */ +public class RecoverForSync implements Recover { + private static final RecoverForSync recoverForSync = new RecoverForSync(); + private String envHome; + + private RecoverForSync() { + this.envHome = ProjectLibrary.getInstance().getLibHome(); + } + + public static Recover getInstance() { + return recoverForSync; + } + + @Override + public boolean recover() { + try{ + //当出现一些奇怪的问题时,从备份的jar中还原所有jar + CommonIOUtils.copyFilesInDirByPath(StableUtils.pathJoin(envHome, ProjectConstants.ASSIST_NAME, UpdateConstants.ENV_LIB,UpdateConstants.BACKUPPATH), + StableUtils.pathJoin(envHome,ProjectConstants.LIB_NAME)); + FineLoggerFactory.getLogger().error("Recover down for sync"); + return true; + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage() , "Recover error for sync", e); + return false; + } + } + + @Override + public boolean backup() { + try { + String envLib = StableUtils.pathJoin(envHome,ProjectConstants.ASSIST_NAME, UpdateConstants.ENV_LIB); + File file = new File(envLib); + if(file.exists()){ + CommonIOUtils.deleteFile(file); + } + CommonIOUtils.copyFilesInDirByPath(StableUtils.pathJoin(envHome,ProjectConstants.LIB_NAME),StableUtils.pathJoin(envLib, UpdateConstants.BACKUPPATH)); + FineLoggerFactory.getLogger().error("Backup down for Sync yes"); + return true; + } catch (IOException e) { + UpdateException exception = new UpdateException("BackUp Exception " + e.getMessage()); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + return false; + } + + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/backup/RecoverHandler.java b/designer-base/src/main/java/com/fr/decision/update/backup/RecoverHandler.java new file mode 100644 index 0000000000..ee27f6baf9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/backup/RecoverHandler.java @@ -0,0 +1,37 @@ +package com.fr.decision.update.backup; +/** + * RecoverHandler + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public class RecoverHandler implements Recover { + + private static final RecoverHandler recoverHandler = new RecoverHandler(); + private Recover recoverManager; + + private RecoverHandler() { + this.recoverManager = RecoverManager.getInstance(); + RecoverManager.register(new RecoverForCommon()); + } + + public static Recover getInstance() { + // 不支持集群,设计器自用 + return recoverHandler; + } + + + @Override + public boolean recover() { + return recoverManager.recover(); + } + + @Override + public boolean backup() { + return recoverManager.backup(); + } + + + +} diff --git a/designer-base/src/main/java/com/fr/decision/update/backup/RecoverManager.java b/designer-base/src/main/java/com/fr/decision/update/backup/RecoverManager.java new file mode 100644 index 0000000000..44502d4416 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/backup/RecoverManager.java @@ -0,0 +1,74 @@ +package com.fr.decision.update.backup; + +import com.fr.decision.update.exception.UpdateException; +import com.fr.log.FineLoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * RecoverManager + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public class RecoverManager implements Recover { + + private static final Recover INSTANCE = new RecoverManager(); + + private RecoverManager() {} + + public static Recover getInstance() { + return INSTANCE; + } + + private static final List recovers = new ArrayList<>(); + + /** + * 注册 + */ + public static void register(Recover recover) { + if (recover != null) { + recovers.add(recover); + } + } + + /** + * 清理 + */ + public static void clear() { + recovers.clear(); + } + + @Override + public boolean recover() { + try { + for (Recover recover : recovers) { + if (!recover.recover()) { + return false; + } + } + return true; + } catch (Exception e) { + FineLoggerFactory.getLogger().error("recover in RecoverManager failed"); + return false; + } + } + + @Override + public boolean backup() { + try { + for (Recover recover : recovers) { + if (!recover.backup()) { + return false; + } + } + return true; + } catch (Exception e) { + UpdateException exception = new UpdateException(e.getMessage() + "backup in RecoverManager failed"); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + return false; + } + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/command/Command.java b/designer-base/src/main/java/com/fr/decision/update/command/Command.java new file mode 100644 index 0000000000..efa16bcbd7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/command/Command.java @@ -0,0 +1,23 @@ +package com.fr.decision.update.command; + +import com.fr.decision.update.info.UpdateCallBack; + +/** + * Command + * + * @author Bryant + * @since 10.0 + * Created on 2019/8/25 + */ +public interface Command { + + //空的command,赋值失败 & 初始化时候使用,command异常时候execute无操作 + Command EMPTY = new Command() { + @Override + public boolean execute(UpdateCallBack callBack) { + return false; + } + }; + + boolean execute(UpdateCallBack callBack); +} diff --git a/designer-base/src/main/java/com/fr/decision/update/command/CommandFactory.java b/designer-base/src/main/java/com/fr/decision/update/command/CommandFactory.java new file mode 100644 index 0000000000..9c4ffcd91f --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/command/CommandFactory.java @@ -0,0 +1,75 @@ +package com.fr.decision.update.command; + +import com.fr.decision.update.data.FinallyObject; +import com.fr.decision.update.data.UpdateConstants; +import com.fr.decision.update.exception.UpdateException; +import com.fr.decision.update.impl.AddCommand; +import com.fr.decision.update.impl.RemoveCommand; +import com.fr.decision.update.impl.delete.DeleteJars; +import com.fr.decision.update.impl.delete.DeleteOtherFiles; +import com.fr.decision.update.info.UpdateProcessBean; +import com.fr.log.FineLoggerFactory; + +import java.util.ArrayList; +import java.util.List; + + +/** + * CommandFactory + * + * @author Bryant + * @since 10.0 + * Created on 2019/8/25 + */ +public class CommandFactory { + + private CommandFactory() { + } + + public static Command build(FinallyObject finallyObject) { + UpdateProcessBean bean = new UpdateProcessBean(); + List commandList = new ArrayList<>(); + CommandGroup commands = new CommandGroup(commandList); + //下载文件 + if (finallyObject.getItemsForAdd() != null) { + int length = finallyObject.getItemsForAdd().length; + bean.setTotalFiles(length); + for (int i = 0; i < length; i++) { + Command command = new AddCommand(finallyObject.getItemsForAdd()[i].getSource(), finallyObject.getItemsForAdd()[i].getTarget(), bean); + commands.addCommands(command); + } + } + //操作文件 + if (finallyObject.getItemsForModify() != null) { + int length = finallyObject.getItemsForModify().length; + for (int i = 0; i < length; i++) { + Command command = new RemoveCommand(finallyObject.getItemsForModify()[i].getSource(), finallyObject.getItemsForModify()[i].getTarget()); + commands.addCommands(command); + } + } + //删除文件 + if (finallyObject.getFilesForDelete() != null) { + String[] fileList = finallyObject.getFilesForDelete(); + for (String file : fileList) { + commands.addCommands(buildDeleteCommand(file)); + } + } + return commands; + } + + private static Command buildDeleteCommand(String file) { + Command command = Command.EMPTY; + try { + if (file.endsWith(UpdateConstants.JAR_FILE_SUFFIX)) { + command = new DeleteJars(file); + } else { + command = new DeleteOtherFiles(file); + } + } catch (Exception e) { + UpdateException exception = new UpdateException(e.getMessage() + "get file postfix error"); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + } + + return command; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/decision/update/command/CommandGroup.java b/designer-base/src/main/java/com/fr/decision/update/command/CommandGroup.java new file mode 100644 index 0000000000..dc1067c3ed --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/command/CommandGroup.java @@ -0,0 +1,43 @@ +package com.fr.decision.update.command; + +import com.fr.decision.update.exception.UpdateException; +import com.fr.decision.update.info.UpdateCallBack; +import com.fr.log.FineLoggerFactory; + +import java.util.List; + +/** + * CommandGroup + * + * @author Bryant + * @since 10.0 + * Created on 2019/8/25 + */ +public class CommandGroup implements Command{ + + private List commands; + + public CommandGroup(List commands) { + this.commands = commands; + } + + public void addCommands(Command command) { + commands.add(command); + } + + @Override + public boolean execute(UpdateCallBack callBack) { + try { + for (Command command : commands) { + if (!command.execute(callBack)) { + return false; + } + } + return true; + } catch (Exception e) { + UpdateException exception = new UpdateException(e.getMessage() + "execute error in group"); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + return false; + } + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/command/CommandHandler.java b/designer-base/src/main/java/com/fr/decision/update/command/CommandHandler.java new file mode 100644 index 0000000000..fe7d9b56a5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/command/CommandHandler.java @@ -0,0 +1,70 @@ +package com.fr.decision.update.command; + +import com.fr.decision.update.acquirer.JSEngine; +import com.fr.decision.update.config.UpdateConfigFactory; +import com.fr.decision.update.data.FinallyObject; +import com.fr.decision.update.exception.UpdateException; +import com.fr.decision.update.info.UpdateCallBack; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; + +/** + * CommandHandler + * + * @author Bryant + * @since 10.0 + * Created on 2019/8/25 + */ +public class CommandHandler implements Command { + + private String yunURL; + + private static final CommandHandler commandHandler = new CommandHandler(); + + private CommandHandler(){} + + public static Command getInstance() { + // 不支持集群,设计器自用 + return commandHandler; + } + + + @Override + public boolean execute(UpdateCallBack callBack) { + if (checkUpdate()) { + return update(callBack); + } else { + FineLoggerFactory.getLogger().info("Not need to update"); + return false; + } + } + + /** + * 检查是否需要更新 + */ + private boolean checkUpdate() { + try { + yunURL = UpdateConfigFactory.get().getJsUpdateUrl(); + return yunURL != null && !yunURL.equals(StringUtils.EMPTY); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return false; + } + } + + /** + * 进行更新 + */ + private boolean update(UpdateCallBack callBack) { + FinallyObject finallyObject = JSEngine.getEngine().executeJS(yunURL); + //增删改在备份之后执行 + if (finallyObject != null) { + Command command = CommandFactory.build(finallyObject); + return command.execute(callBack); + } else { + UpdateException exception = new UpdateException("finallyObject can not be null"); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), exception); + return false; + } + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/command/SyncCommandHandler.java b/designer-base/src/main/java/com/fr/decision/update/command/SyncCommandHandler.java new file mode 100644 index 0000000000..6d80ba9657 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/command/SyncCommandHandler.java @@ -0,0 +1,162 @@ +package com.fr.decision.update.command; + +import com.fr.decision.update.acquirer.JSEngine; +import com.fr.decision.update.data.FinallyObject; +import com.fr.decision.update.data.UpdateConstants; +import com.fr.decision.update.info.UpdateCallBack; +import com.fr.file.FileCommonUtils; +import com.fr.general.CloudCenter; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.CommonUtils; +import com.fr.stable.ProjectLibrary; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.project.ProjectConstants; + +import java.io.File; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +/** + * SyncCommandHandler + * + * @author pengda + * @since 10.0 + * Created on 2021/6/02 + */ +public class SyncCommandHandler { + + private String jsURL; + private String branchTime; + private String HYPHEN = "-"; + private String localJarsDirName = null; + + private static final SyncCommandHandler syncCommandHandler = new SyncCommandHandler(); + + private SyncCommandHandler() { + } + + /** + * 获取单例 + */ + public static SyncCommandHandler getInstance() { + return syncCommandHandler; + } + + + /** + * 执行 + */ + public boolean execute(UpdateCallBack callBack, String fullBuildNo) { + branchTime = formatBranch(fullBuildNo); + if (checkLocalJars(fullBuildNo) || checkSync()) { + return syncJars(callBack); + } else { + FineLoggerFactory.getLogger().info("The condition of syncJars is not satisfied"); + return false; + } + } + + private boolean checkSync() { + try { + jsURL = CloudCenter.getInstance().acquireUrlByKind("js11.sync"); + return jsURL != null && !jsURL.equals(StringUtils.EMPTY); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return false; + } + } + + private boolean checkLocalJars(String fullBuildNo) { + try { + localJarsDirName = null; + File backupDir = new File(CommonUtils.pathJoin(StableUtils.getInstallHome(), UpdateConstants.DESIGNER_BACKUP_DIR)); + StableUtils.mkdirs(backupDir); + File[] versions = backupDir.listFiles(); + if (versions != null) { + for (File version : versions) { + String libName = version.getName(); + if (ComparatorUtils.equals(libName.substring(libName.lastIndexOf(HYPHEN) + 1), fullBuildNo.substring(fullBuildNo.lastIndexOf("-") + 1))) { + File[] designerJars = new File(CommonUtils.pathJoin(FileCommonUtils.getAbsolutePath(version), UpdateConstants.DESIGNERBACKUPPATH)).listFiles(); + File[] oldJars = new File(CommonUtils.pathJoin(FileCommonUtils.getAbsolutePath(version), UpdateConstants.BACKUPPATH)).listFiles(); + if (designerJars != null && oldJars != null) { + boolean result = designerJars.length > 0 && oldJars.length > 0; + if (result) { + localJarsDirName = version.getName(); + } + return result; + } + } + } + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return false; + } + + private boolean syncJars(UpdateCallBack callBack) { + FinallyObject finallyObject; + if (localJarsDirName != null) { + finallyObject = createLocalJarsFinallyObject(); + } else { + finallyObject = JSEngine.getEngine().executeJS(jsURL); + } + //增删改在备份之后执行 + if (finallyObject != null) { + Command command = CommandFactory.build(finallyObject); + return command.execute(callBack); + } else { + FineLoggerFactory.getLogger().error("sync error : finallyObject can not be null"); + return false; + } + } + + private FinallyObject createLocalJarsFinallyObject() { + FinallyObject finallyObject = FinallyObject.create(); + File[] designerJars = new File(CommonUtils.pathJoin(StableUtils.getInstallHome(), UpdateConstants.DESIGNER_BACKUP_DIR, localJarsDirName, UpdateConstants.DESIGNERBACKUPPATH)).listFiles(); + File[] oldJars = new File(CommonUtils.pathJoin(StableUtils.getInstallHome(), UpdateConstants.DESIGNER_BACKUP_DIR, localJarsDirName, UpdateConstants.BACKUPPATH)).listFiles(); + if (null == designerJars || null == oldJars) { + return finallyObject; + } + String envLibPath = CommonUtils.pathJoin(ProjectLibrary.getInstance().getLibHome(), ProjectConstants.LIB_NAME); + File file = new File(envLibPath); + File[] files = file.listFiles(); + Set fileSet = new HashSet<>(); + if (files != null) { + for (File file1 : files) { + if (file1.getName().startsWith(UpdateConstants.FINE) && file1.getName().endsWith(UpdateConstants.JAR_FILE_SUFFIX)) { + fileSet.add(file1.getName()); + } + } + } + for (File designerJar : designerJars) { + finallyObject.registerModify(FileCommonUtils.getAbsolutePath(designerJar), CommonUtils.pathJoin(StableUtils.getInstallHome(), ProjectConstants.LIB_NAME)); + } + for (File oldJar : oldJars) { + finallyObject.registerModify(FileCommonUtils.getAbsolutePath(oldJar), envLibPath); + fileSet.remove(oldJar.getName()); + } + for (String fileName : fileSet) { + finallyObject.registerDelete(CommonUtils.pathJoin(envLibPath, fileName)); + } + return finallyObject; + } + + /** + * 获取分支时间 + */ + public String getBranchTime(){ + return branchTime; + } + + private String formatBranch(String buildNO) { + Date jarDate = (new SimpleDateFormat("yyyy.MM.dd")).parse(buildNO, new ParsePosition(buildNO.indexOf("-") + 1)); + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + return df.format(jarDate); + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/config/AbstractUpdateConfig.java b/designer-base/src/main/java/com/fr/decision/update/config/AbstractUpdateConfig.java new file mode 100644 index 0000000000..fb8ab4949f --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/config/AbstractUpdateConfig.java @@ -0,0 +1,51 @@ +package com.fr.decision.update.config; + +import com.fr.general.CloudCenter; + + +/** + * AbstractUpdateConfig + * + * @author Smile.Chen + * @since 10.0 + * Created on 2022/9/9 + */ +public abstract class AbstractUpdateConfig implements UpdateConfig { + @Override + public String getUpdateUrl() { + return CloudCenter.getInstance().acquireUrlByKind(getUpdateKey()); + } + + @Override + public String getVersionUrl() { + return CloudCenter.getInstance().acquireUrlByKind(getVersionKey()); + } + + @Override + public String getJsUpdateUrl() { + return CloudCenter.getInstance().acquireUrlByKind(getJsUpdateKey()); + } + + @Override + public String getChangeLogUrl() { + return CloudCenter.getInstance().acquireUrlByKind(getChangeLogKey()); + } + + protected abstract String getUpdateKey(); + + protected abstract String getVersionKey(); + + protected abstract String getJsUpdateKey(); + + protected abstract String getChangeLogKey(); + + @Override + public String[] getLogTypeWhiteList() { + return new String[0]; + } + + @Override + public String[] getProjectValues() { + return new String[0]; + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/config/UpdateConfig.java b/designer-base/src/main/java/com/fr/decision/update/config/UpdateConfig.java new file mode 100644 index 0000000000..d517d928f8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/config/UpdateConfig.java @@ -0,0 +1,43 @@ +package com.fr.decision.update.config; + + +/** + * UpdateConfig + * + * @author Smile.Chen + * @since 10.0 + * Created on 2022/9/20 + */ +public interface UpdateConfig { + + /** + * 返回更新信息URL + */ + String getUpdateUrl(); + + /** + * 返回版本信息URL,接口中包含小版本 + */ + String getVersionUrl(); + + /** + * 返回js更新脚本的URL。 + */ + String getJsUpdateUrl(); + + /** + * 返回更新日志URL + */ + String getChangeLogUrl(); + + /** + * 白名单,title会从这个String[]中匹配是否包含其中一个关键字,如果包含则展示 + */ + String[] getLogTypeWhiteList(); + + /** + * 需要获取日志的模块 + */ + String[] getProjectValues(); + +} diff --git a/designer-base/src/main/java/com/fr/decision/update/config/UpdateConfigFactory.java b/designer-base/src/main/java/com/fr/decision/update/config/UpdateConfigFactory.java new file mode 100644 index 0000000000..6be6b47bec --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/config/UpdateConfigFactory.java @@ -0,0 +1,30 @@ +package com.fr.decision.update.config; + + +/** + * UpdateConfig + * + * @author Smile.Chen + * @since 10.0 + * Created on 2022/9/20 + */ +public class UpdateConfigFactory { + + private static volatile UpdateConfig UPDATE_CONFIG_INFO = null; + + public static UpdateConfig get() { + if (UPDATE_CONFIG_INFO == null) { + synchronized (UpdateConfigFactory.class) { + if (UPDATE_CONFIG_INFO == null) { + UPDATE_CONFIG_INFO = new UpdateConfigInfo(); + } + } + } + return UPDATE_CONFIG_INFO; + } + + public synchronized static void setUpdateConfigInfo(UpdateConfig configInfo) { + UPDATE_CONFIG_INFO = configInfo; + } + +} diff --git a/designer-base/src/main/java/com/fr/decision/update/config/UpdateConfigInfo.java b/designer-base/src/main/java/com/fr/decision/update/config/UpdateConfigInfo.java new file mode 100644 index 0000000000..5c47afb948 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/config/UpdateConfigInfo.java @@ -0,0 +1,53 @@ +package com.fr.decision.update.config; + +/** + * UpdateConfig + * + * @author Smile.Chen + * @since 10.0 + * Created on 2022/9/20 + */ +public class UpdateConfigInfo extends AbstractUpdateConfig { + + //包含更新信息 + public static final String JAR11_UPDATE = "jar11.update"; + //包含小版本信息 + public static final String JAR11_VERSION = "jar11.version"; + public static final String JS11_UPDATE = "js11.update"; + public static final String CHANGE_LOG = "changelog10"; + + //更新日志显示白名单 + private static final String[] LOG_TYPE_WHITELIST = new String[]{ + "DEC", "REPORT", "MOBILE", "DESIGN", "CHART" + }; + //日志路由project参数值 + private static final String[] PROJECT_VALUES = new String[]{ + "DEC", "REPORT", "VISUAL", "CORE", "DB", "CRON", "CHART", "DESIGN" + }; + + protected String getUpdateKey() { + return JAR11_UPDATE; + } + + protected String getVersionKey() { + return JAR11_VERSION; + } + + protected String getJsUpdateKey() { + return JS11_UPDATE; + } + + protected String getChangeLogKey() { + return CHANGE_LOG; + } + + @Override + public String[] getLogTypeWhiteList() { + return LOG_TYPE_WHITELIST; + } + + @Override + public String[] getProjectValues() { + return PROJECT_VALUES; + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/data/FinallyObject.java b/designer-base/src/main/java/com/fr/decision/update/data/FinallyObject.java new file mode 100644 index 0000000000..e2062fb7d6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/data/FinallyObject.java @@ -0,0 +1,97 @@ +package com.fr.decision.update.data; + +import com.fr.stable.AssistUtils; + +import java.util.HashSet; +import java.util.Set; +/** + * FinallyObject + * + * @author richie + * @since 10.0 + * Created on 2019/4/24 + */ +public class FinallyObject { + + public static FinallyObject create() { + return new FinallyObject(); + } + + private Set waitingForAdd = new HashSet(); + + private Set waitingForDelete = new HashSet(); + + private Set waitingForModify = new HashSet(); + + private FinallyObject() { + + } + + public void registerAdd(String source, String target) { + waitingForAdd.add(new Item(source, target)); + } + + public void registerDelete(String path) { + waitingForDelete.add(path); + } + + public void registerModify(String source, String target) { + waitingForModify.add(new Item(source, target)); + } + + /** + * 获取待添加的条目信息 + * @return 待添加条目组成的数组 + */ + public Item[] getItemsForAdd() { + return waitingForAdd.toArray(new Item[0]); + } + + /** + * 获取待删除的文件组成的数组 + * @return 待删除的文件数组 + */ + public String[] getFilesForDelete() { + return waitingForDelete.toArray(new String[0]); + } + + /** + * 获取待修改的条目信息 + * @return 待修改的条目组成的数组 + */ + public Item[] getItemsForModify() { + return waitingForModify.toArray(new Item[0]); + } + + public static final class Item { + private String source; + private String target; + + public Item(String source, String target) { + this.source = source; + this.target = target; + } + + public String getSource() { + return source; + } + + public String getTarget() { + return target; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof Item + && AssistUtils.equals(source, ((Item) obj).source) + && AssistUtils.equals(target, ((Item) obj).target); + + } + + @Override + public int hashCode() { + return AssistUtils.hashCode(source, target); + } + } + +} diff --git a/designer-base/src/main/java/com/fr/decision/update/data/UpdateConstants.java b/designer-base/src/main/java/com/fr/decision/update/data/UpdateConstants.java new file mode 100644 index 0000000000..b8b3740ca7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/data/UpdateConstants.java @@ -0,0 +1,46 @@ +package com.fr.decision.update.data; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * UpdateConstants + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public interface UpdateConstants { + + String INSTALL_LIB = "installLib"; + String ENV_LIB = "envLib"; + String WEBAPPS = "webapps"; + String ASPECTJRT = "aspectjrt"; + String FINE = "fine"; + String UPDATE_SERVICE = "update"; + String BACKUPPATH = "OldJars"; + String KB = "KB"; + String DESIGNERBACKUPPATH = "designerJars"; + String DESIGNER = "designer"; + String ARCH_X86 = "x86"; + String ARCH_X86_64 = "x86_64"; + String ARM = "ARM"; + String UNKNOWNOS = "Unknown"; + String DECISION = "decision"; + int BYTE = 8192; + String DOWNLOADPATH = "NewJars"; + String JAR_FILE_SUFFIX = ".jar"; + Color BAR_COLOR = new Color(0x3384F0); + String CHANGELOG_X_START = "2018-07-11"; + String DEFAULT_APP_NAME = "FineReport"; + String DESIGNER_BACKUP_DIR = "designerbackup"; + String UPDATE_CACHE_CONFIG_X = "updateCacheConfig10"; + String UPDATE_CACHE_INFO_X = "updateCacheInfo10"; + String J2V8 = "v8"; + String NASHORN = "nashorn"; + List LOG_TYPE = Collections.unmodifiableList(Arrays.asList(new String[]{ + "REPORT", "MOBILE", "CHART", "PFC", "BI" + })); +} diff --git a/designer-base/src/main/java/com/fr/decision/update/exception/UpdateException.java b/designer-base/src/main/java/com/fr/decision/update/exception/UpdateException.java new file mode 100644 index 0000000000..36ac6333ff --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/exception/UpdateException.java @@ -0,0 +1,38 @@ +package com.fr.decision.update.exception; + +import com.fr.intelligence.IntelligenceException; + +/** + * UpdateException + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public class UpdateException extends IntelligenceException { + + private String errorMessage; + + public UpdateException(String errorMessage) { + super(errorMessage); + this.errorMessage = errorCode() + errorMessage; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + /** + * 异常错误码,一般是一串数字,由产品经理确定并提供文档 + * + * @return 错误码 + */ + @Override + public String errorCode() { + return "21300025 "; + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/impl/AddCommand.java b/designer-base/src/main/java/com/fr/decision/update/impl/AddCommand.java new file mode 100644 index 0000000000..cedd73135f --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/impl/AddCommand.java @@ -0,0 +1,120 @@ +package com.fr.decision.update.impl; + +import com.fr.concurrent.NamedThreadFactory; +import com.fr.decision.update.command.Command; +import com.fr.decision.update.data.UpdateConstants; +import com.fr.decision.update.exception.UpdateException; +import com.fr.decision.update.info.UpdateCallBack; +import com.fr.decision.update.info.UpdateProcessBean; +import com.fr.general.CommonIOUtils; +import com.fr.general.http.HttpToolbox; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StableUtils; +import com.fr.third.org.apache.http.client.config.RequestConfig; +import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse; +import com.fr.third.org.apache.http.client.methods.HttpGet; +import com.fr.third.org.apache.http.impl.client.CloseableHttpClient; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * 提交任务 + * + * @author Bryant + * @since 10.0 + * Created on 2019/8/25 + */ +public class AddCommand implements Command { + + private static final int TIME_OUT = 30 * 1000; + + private String source; + private String target; + private UpdateProcessBean bean; + + private final ThreadPoolExecutor updateProgressExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<>()); + + public AddCommand(String source, String target, UpdateProcessBean bean) { + this.source = source; + this.target = target; + this.bean = bean; + init(); + } + + private void init() { + //十几万次提交至状态服务器会有性能问题,因此用异步阻塞队列 + updateProgressExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); + updateProgressExecutor.setThreadFactory(new NamedThreadFactory("updateProgress", true)); + } + + @Override + public boolean execute(UpdateCallBack callBack) { + return downloadFile(source, callBack); + } + + /** + * Http请求更新文件 + * + * @param urlStr 更新路由 + * @param callBack 进度条回调 + */ + private boolean downloadFile(String urlStr, UpdateCallBack callBack) { + FileOutputStream fos = null; + //http请求 + CloseableHttpClient httpClient; + CloseableHttpResponse httpResponse; + HttpGet httpGet = new HttpGet(urlStr); + RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(TIME_OUT) + .setConnectionRequestTimeout(TIME_OUT).setSocketTimeout(TIME_OUT).build(); + httpGet.setConfig(requestConfig); + httpClient = HttpToolbox.getHttpClient(urlStr); + InputStream in = null; + try { + httpResponse = httpClient.execute(httpGet); + if (httpResponse.getStatusLine().getStatusCode() != 200) { + FineLoggerFactory.getLogger().error("download jar error : no file exists!"); + return false; + } + long totalSize = httpResponse.getEntity().getContentLength(); + in = httpResponse.getEntity().getContent(); + //保存文件 + File saveDir = new File(target); + StableUtils.makesureFileExist(saveDir); + String fileName = source.substring(source.lastIndexOf('/') + 1); + bean.setDownloadedFiles(bean.getDownloadedFiles() + 1); + bean.setName(fileName); + bean.setTotalLength((int) totalSize); + bean.setDownloadLength(0); + updateProgress(callBack, bean); + fos = new FileOutputStream(saveDir); + int bytesRead; + int totalBytesRead = 0; + byte[] getData = new byte[UpdateConstants.BYTE]; + while ((bytesRead = in.read(getData)) != -1) { + fos.write(getData, 0, bytesRead); + getData = new byte[UpdateConstants.BYTE]; + totalBytesRead += bytesRead; + bean.setDownloadLength(totalBytesRead); + updateProgress(callBack, bean); + } + FineLoggerFactory.getLogger().error("Updating Download " + target); + return true; + } catch (Exception e) { + UpdateException exception = new UpdateException(e.getMessage()); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + } finally { + CommonIOUtils.close(fos); + CommonIOUtils.close(in); + } + return false; + } + + private void updateProgress(UpdateCallBack callBack, UpdateProcessBean bean) { + updateProgressExecutor.submit(() -> callBack.updateProgress(bean)); + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/impl/RemoveCommand.java b/designer-base/src/main/java/com/fr/decision/update/impl/RemoveCommand.java new file mode 100644 index 0000000000..473b45d29e --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/impl/RemoveCommand.java @@ -0,0 +1,53 @@ +package com.fr.decision.update.impl; + +import com.fr.decision.update.command.Command; +import com.fr.decision.update.exception.UpdateException; +import com.fr.decision.update.info.UpdateCallBack; +import com.fr.general.CommonIOUtils; +import com.fr.general.IOUtils; +import com.fr.log.FineLoggerFactory; + +import java.io.File; +import java.io.IOException; + +/** + * RemoveCommand + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public class RemoveCommand implements Command { + + private String source; + private String target; + + public RemoveCommand(String source, String target) { + this.source = source; + this.target = target; + } + + @Override + public boolean execute(UpdateCallBack callBack) { + try { + File src = new File(source); + File tar = new File(target); + if (src.isDirectory()) { + CommonIOUtils.copyFilesInDirByPath(source,target); + FineLoggerFactory.getLogger().error("Updating move " + target); + return true; + } else { + IOUtils.copy(src,tar); + FineLoggerFactory.getLogger().error("Updating move " + target); + return true; + } + } catch (IOException e) { + UpdateException exception = new UpdateException("Move files error " + e.getMessage()); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + return false; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return false; + } + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/impl/delete/DeleteJars.java b/designer-base/src/main/java/com/fr/decision/update/impl/delete/DeleteJars.java new file mode 100644 index 0000000000..3421b0a333 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/impl/delete/DeleteJars.java @@ -0,0 +1,47 @@ +package com.fr.decision.update.impl.delete; + +import com.fr.decision.update.command.Command; +import com.fr.decision.update.exception.UpdateException; +import com.fr.decision.update.info.UpdateCallBack; +import com.fr.general.CommonIOUtils; +import com.fr.log.FineLoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.jar.JarOutputStream; + +/** + * 删除Jar包 + * + * @author Bryant + * @since 10.0 + * Created on 2019/8/25 + */ +public class DeleteJars implements Command { + + private String file; + + public DeleteJars(String file) { + this.file = file; + } + + @Override + public boolean execute(UpdateCallBack callBack) { + FileOutputStream oldOutputStream = null; + JarOutputStream jar = null; + try { + File oldFile = new File(file); + oldOutputStream = new FileOutputStream(oldFile); + jar = new JarOutputStream(oldOutputStream); + FineLoggerFactory.getLogger().error("Updating delete jar"); + return true; + } catch (Exception e) { + UpdateException exception = new UpdateException("write jar error " + e.getMessage()); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + return false; + } finally { + CommonIOUtils.close(jar); + CommonIOUtils.close(oldOutputStream); + } + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/impl/delete/DeleteOtherFiles.java b/designer-base/src/main/java/com/fr/decision/update/impl/delete/DeleteOtherFiles.java new file mode 100644 index 0000000000..f0c7b5bda3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/impl/delete/DeleteOtherFiles.java @@ -0,0 +1,51 @@ +package com.fr.decision.update.impl.delete; + +import com.fr.decision.update.command.Command; +import com.fr.decision.update.exception.UpdateException; +import com.fr.decision.update.info.UpdateCallBack; +import com.fr.general.CommonIOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.CommonUtils; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; + +/** + * 删除其他文件 + * + * @author Bryant + * @since 10.0 + * Created on 2019/8/25 + */ +public class DeleteOtherFiles implements Command { + + private String file; + + public DeleteOtherFiles(String file) { + this.file = file; + } + + @Override + public boolean execute(UpdateCallBack callBack) { + FileOutputStream oldOutputStream = null; + BufferedOutputStream buffer = null; + try { + File oldFile = new File(file); + if (!CommonUtils.deleteFile(oldFile)) { + oldOutputStream = new FileOutputStream(file); + buffer = new BufferedOutputStream(oldOutputStream); + return true; + } + FineLoggerFactory.getLogger().error("Updating delete files"); + return true; + } catch (Exception e) { + UpdateException exception = new UpdateException(e.getMessage() + " Delete files Exception"); + FineLoggerFactory.getLogger().error(exception.getErrorMessage(), e); + return false; + }finally { + CommonIOUtils.close(buffer); + CommonIOUtils.close(oldOutputStream); + } + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/info/UpdateCallBack.java b/designer-base/src/main/java/com/fr/decision/update/info/UpdateCallBack.java new file mode 100644 index 0000000000..fcd28bf126 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/info/UpdateCallBack.java @@ -0,0 +1,15 @@ +package com.fr.decision.update.info; + +/** + * UpdateCallBack + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public interface UpdateCallBack { + /** + * 更新进度条 + */ + void updateProgress(UpdateProcessBean bean); +} diff --git a/designer-base/src/main/java/com/fr/decision/update/info/UpdateProcessBean.java b/designer-base/src/main/java/com/fr/decision/update/info/UpdateProcessBean.java new file mode 100644 index 0000000000..17752cc33d --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/info/UpdateProcessBean.java @@ -0,0 +1,109 @@ +package com.fr.decision.update.info; + +import com.fr.decision.update.data.UpdateConstants; +import com.fr.general.ComparatorUtils; +import com.fr.stable.StableUtils; + +/** + * UpdateProcessBean + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public class UpdateProcessBean { + //显示为百分比 + private static final int PERCENTAGE_RATIO = 100; + //显示kB + private static final int BYTETOKB_RATIO = 1000; + + private String name; + private long size; + + private int totalLength; + private int downloadLength; + private int downloadedFiles; + private int totalFiles; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getDownloadedFiles() { + return downloadedFiles; + } + + public void setDownloadedFiles(int downloadedFiles) { + this.downloadedFiles = downloadedFiles; + } + + int getTotalFiles() { + return totalFiles; + } + + public void setTotalFiles(int totalFiles) { + this.totalFiles = totalFiles; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public int getTotalLength() { + return totalLength; + } + + int getDownloadLength() { + return downloadLength; + } + + public void setTotalLength(int totalLength) { + this.totalLength = totalLength; + } + + public void setDownloadLength(int downloadLength) { + this.downloadLength = downloadLength; + } + + public int getProgressValue() { + return (int) ((downloadLength / (double) totalLength) * PERCENTAGE_RATIO); + } + + String getProgressString() { + return StableUtils.pathJoin(downloadLength / BYTETOKB_RATIO + UpdateConstants.KB, totalLength / BYTETOKB_RATIO + UpdateConstants.KB); + } + + /** + * 转化为字符串 + * + * @return 字符串 + */ + @Override + public String toString() { + return "name:" + name + ";download:" + getProgressString(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof UpdateProcessBean + && ComparatorUtils.equals(((UpdateProcessBean) obj).name, name); + } + + /** + * 返回一个hash码 + * + * @return hash码 + */ + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/info/UpdateProgressCallBack.java b/designer-base/src/main/java/com/fr/decision/update/info/UpdateProgressCallBack.java new file mode 100644 index 0000000000..3941988c93 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/info/UpdateProgressCallBack.java @@ -0,0 +1,27 @@ +package com.fr.decision.update.info; + +import com.fr.stable.StringUtils; + +import javax.swing.*; + +/** + * UpdateProgressCallBack + * + * @author Bryant + * @since 10.0 + * Created on 2019/9/20 + */ +public class UpdateProgressCallBack implements UpdateCallBack { + + private static JProgressBar bar; + + public UpdateProgressCallBack(JProgressBar bar) { + this.bar = bar; + } + + @Override + public void updateProgress(UpdateProcessBean bean) { + bar.setString(bean.getName() + StringUtils.BLANK + bean.getProgressString()); + bar.setValue(bean.getProgressValue()); + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/operate/AcquirerTask.java b/designer-base/src/main/java/com/fr/decision/update/operate/AcquirerTask.java new file mode 100644 index 0000000000..3f9d248d30 --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/operate/AcquirerTask.java @@ -0,0 +1,25 @@ +package com.fr.decision.update.operate; + + +import java.util.concurrent.Callable; + +/** + * 配置任务 + * + * @author richie + * @since 10.0 + * Created on 2019/8/16 + */ +public class AcquirerTask implements Callable { + + private String info; + + public AcquirerTask(String info) { + this.info = info; + } + + @Override + public String call() { + return info; + } +} diff --git a/designer-base/src/main/java/com/fr/decision/update/script/Files.java b/designer-base/src/main/java/com/fr/decision/update/script/Files.java new file mode 100644 index 0000000000..6ac79292fe --- /dev/null +++ b/designer-base/src/main/java/com/fr/decision/update/script/Files.java @@ -0,0 +1,58 @@ +package com.fr.decision.update.script; + +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.third.guava.hash.Hashing; + +import java.io.File; +import java.io.IOException; + +/** + * 文件工具类 + * + * @author richie + * @since 10.0 + * Created on 2019/4/24 + */ +public class Files { + + public Files() { + } + + /** + * 判断一个文件是否存在 + * @param path 文件路径 + * @return 文件存在则返回true,否则返回false + */ + public boolean exist(String path) { + return new File(path).exists(); + } + + /** + * 返回文件的md5校验码 + * @param file 文件路径 + * @return md5校验码 + */ + public String md5(String file) { + try { + return com.fr.third.guava.io.Files.hash(new File(file), Hashing.md5()).toString(); + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return StringUtils.EMPTY; + } + + /** + * 返回文件的sha256校验码 + * @param file 文件路径 + * @return sha256校验码 + */ + public String sha256(String file) { + try { + return com.fr.third.guava.io.Files.hash(new File(file), Hashing.sha256()).toString(); + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return StringUtils.EMPTY; + } +} diff --git a/designer-base/src/main/java/com/fr/design/bbs/BBSLoginUtils.java b/designer-base/src/main/java/com/fr/design/bbs/BBSLoginUtils.java index 9e2ba9a733..4e5be848bb 100644 --- a/designer-base/src/main/java/com/fr/design/bbs/BBSLoginUtils.java +++ b/designer-base/src/main/java/com/fr/design/bbs/BBSLoginUtils.java @@ -1,6 +1,6 @@ package com.fr.design.bbs; -import com.fr.base.passport.FinePassportManager; +import com.fr.base.password.FinePassportManager; import com.fr.log.FineLoggerFactory; diff --git a/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java b/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java index 83d6e24ac8..fb801e7e53 100644 --- a/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java +++ b/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java @@ -1,6 +1,5 @@ package com.fr.design.carton; -import com.fr.decision.webservice.v10.log.download.utils.LogZipUtils; import com.fr.design.DesignerEnvManager; import com.fr.design.constants.UIConstants; import com.fr.design.dialog.FineJOptionPane; diff --git a/designer-base/src/main/java/com/fr/design/carton/LogZipUtils.java b/designer-base/src/main/java/com/fr/design/carton/LogZipUtils.java new file mode 100644 index 0000000000..7690530391 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/carton/LogZipUtils.java @@ -0,0 +1,180 @@ +package com.fr.design.carton; + +import com.fr.log.FineLoggerFactory; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +/** + * LogZipUtils + * + * @author Hoky + * @since 10.0 + * Created on 2021/4/28 + */ +public class LogZipUtils { + private static final int BUFFER_SIZE = 2 * 1024; + /** + * 是否保留原来的目录结构 + * true: 保留目录结构; + * false: 所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败) + */ + private static final boolean KEEP_DIR_STRUCTURE = true; + public static final String GBK = "GBK"; + public static final String STRING = "/"; + public static final String REGEX = "\\*"; + + /** + * 压缩成ZIP + * + * @param outPathFile 压缩 文件/文件夹 输出路径+文件名 D:/xx.zip + * @param isDelSrcFile 只需要压缩文件夹 + */ + public static void compress(File[] sourceFiles, String outPathFile, boolean isDelSrcFile) throws Exception { + if (sourceFiles.length == 0) { + throw new NullSuchFileException("Not such zip file"); + } + byte[] buf = new byte[BUFFER_SIZE]; + try (FileOutputStream out = new FileOutputStream(outPathFile); + ZipOutputStream zos = new ZipOutputStream(out)) { + for (File sourceFile : sourceFiles) { + zos.putNextEntry(new ZipEntry(sourceFile.getName())); + int len; + InputStream in = new BufferedInputStream(new FileInputStream(sourceFile)); + while ((len = in.read(buf)) != -1) { + zos.write(buf, 0, len); + } + zos.closeEntry(); + in.close(); + } + } catch (Exception e) { + throw new Exception("zip error from ZipUtils", e); + } + } + + /** + * 递归压缩方法 + * + * @param sourceFile 源文件 + * @param zos zip输出流 + * @param name 压缩后的名称 + */ + private static void compress(File sourceFile, ZipOutputStream zos, String name) + throws Exception { + byte[] buf = new byte[BUFFER_SIZE]; + if (!sourceFile.isDirectory()) { + zos.putNextEntry(new ZipEntry(name)); + int len; + InputStream in = new BufferedInputStream(new FileInputStream(sourceFile)); + while ((len = in.read(buf)) != -1) { + zos.write(buf, 0, len); + } + zos.closeEntry(); + in.close(); + } else { + File[] listFiles = sourceFile.listFiles(); + if (listFiles == null || listFiles.length == 0) { + if (KEEP_DIR_STRUCTURE) { + zos.putNextEntry(new ZipEntry(name + STRING)); + zos.closeEntry(); + } + } else { + for (File file : listFiles) { + if (KEEP_DIR_STRUCTURE) { + compress(file, zos, name + STRING + file.getName()); + } else { + compress(file, zos, file.getName()); + } + } + } + } + } + + /** + * 解压文件到指定目录 + * + * @param zipPath 解压源文件路径 + * @param descDir 解压目标文件路径 + */ + public static void unCompress(String zipPath, String descDir) throws IOException { + long start = System.currentTimeMillis(); + File zipFile = new File(zipPath); + if (!zipFile.exists()) { + throw new IOException("zip file not exist."); + } + File pathFile = new File(descDir); + if (!pathFile.exists()) { + pathFile.mkdirs(); + } + try (ZipFile zip = new ZipFile(zipFile, Charset.forName(GBK))) { + for (Enumeration entries = zip.entries(); entries.hasMoreElements(); ) { + ZipEntry entry = (ZipEntry) entries.nextElement(); + String zipEntryName = entry.getName(); + InputStream in = zip.getInputStream(entry); + String outPath = (descDir + File.separator + zipEntryName).replaceAll(REGEX, STRING); + // 判断路径是否存在,不存在则创建文件路径 + File file = new File(outPath.substring(0, outPath.lastIndexOf('/'))); + if (!file.exists()) { + file.mkdirs(); + } + // 判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压 + if (new File(outPath).isDirectory()) { + continue; + } + // 输出文件路径信息 + OutputStream out = new FileOutputStream(outPath); + byte[] buf1 = new byte[1024]; + int len; + while ((len = in.read(buf1)) > 0) { + out.write(buf1, 0, len); + } + in.close(); + out.close(); + } + FineLoggerFactory.getLogger().info("file:{}. zip path:{}. finished. cost time:{}ms. ", zipPath, descDir, System.currentTimeMillis() - start); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + throw new IOException(e); + } + } + + + /** + * 删除dir + */ + public static void delDir(String dirPath) throws IOException { + long start = System.currentTimeMillis(); + try { + File dirFile = new File(dirPath); + if (!dirFile.exists()) { + return; + } + if (dirFile.isFile()) { + dirFile.delete(); + return; + } + File[] files = dirFile.listFiles(); + if (files == null) { + return; + } + for (int i = 0; i < files.length; i++) { + delDir(files[i].toString()); + } + dirFile.delete(); + FineLoggerFactory.getLogger().info("delete file:{}. cost:{}ms. ", dirPath, System.currentTimeMillis() - start); + } catch (Exception e) { + FineLoggerFactory.getLogger().info("delete file:{}. exception:{}. cost:{}ms. ", dirPath, e, System.currentTimeMillis() - start); + throw new IOException("delete file exception."); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/carton/NullSuchFileException.java b/designer-base/src/main/java/com/fr/design/carton/NullSuchFileException.java new file mode 100644 index 0000000000..cbb3da02fc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/carton/NullSuchFileException.java @@ -0,0 +1,14 @@ +package com.fr.design.carton; + +/** + * NullSuchFileException + * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/6/20 + */ +public class NullSuchFileException extends NullPointerException { + public NullSuchFileException(String s) { + super(s); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java index 7ee2a1dfdd..2a08dc7b0b 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java @@ -7,7 +7,6 @@ import com.fr.base.ParameterMapNameSpace; import com.fr.data.impl.DBTableData; import com.fr.data.impl.EscapeSqlHelper; import com.fr.data.operator.DataOperator; -import com.fr.decision.webservice.v10.config.ConfigService; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.dialog.link.MessageWithLink; import com.fr.design.gui.ibutton.UIButton; diff --git a/designer-base/src/main/java/com/fr/design/extra/LoginWebBridge.java b/designer-base/src/main/java/com/fr/design/extra/LoginWebBridge.java index 7892d5ce78..0e561d6881 100644 --- a/designer-base/src/main/java/com/fr/design/extra/LoginWebBridge.java +++ b/designer-base/src/main/java/com/fr/design/extra/LoginWebBridge.java @@ -1,6 +1,8 @@ package com.fr.design.extra; +import com.fanruan.carina.Carina; import com.fanruan.cloud.FanruanCloud; +import com.fanruan.config.bbs.FineBBSConfigProvider; import com.fr.concurrent.NamedThreadFactory; import com.fr.design.DesignerEnvManager; import com.fr.design.dialog.UIDialog; @@ -82,7 +84,7 @@ public class LoginWebBridge { */ public void setMessageCount(int count) { if (count == MIN_MESSAGE_COUNT) { - FanruanCloud.marketService().setInShowBBsName(DesignerEnvManager.getEnvManager().getDesignerLoginUsername()); + Carina.config(FineBBSConfigProvider.class).setInShowBBsName(DesignerEnvManager.getEnvManager().getDesignerLoginUsername()); return; } this.messageCount = count; @@ -90,7 +92,7 @@ public class LoginWebBridge { sb.append(StringUtils.BLANK).append(DesignerEnvManager.getEnvManager().getDesignerLoginUsername()) .append("(").append(this.messageCount) .append(")").append(StringUtils.BLANK); - FanruanCloud.marketService().setInShowBBsName(sb.toString()); + Carina.config(FineBBSConfigProvider.class).setInShowBBsName(sb.toString()); } public void setQQDialog(UIDialog qqDialog) { diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java b/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java index 1ba6194127..2cadcc6770 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java @@ -1,6 +1,8 @@ package com.fr.design.extra; +import com.fanruan.carina.Carina; import com.fanruan.cloud.FanruanCloud; +import com.fanruan.config.bbs.FineBBSConfigProvider; import com.fr.config.MarketConfig; import com.fr.design.DesignerEnvManager; import com.fr.design.RestartHelper; @@ -549,7 +551,7 @@ public class PluginWebBridge { * 清除用户信息 */ public void clearUserInfo() { - FanruanCloud.marketService().setInShowBBsName(StringUtils.EMPTY); + Carina.config(FineBBSConfigProvider.class).setInShowBBsName(StringUtils.EMPTY); } public void getPackInfo(final JSObject callback){ diff --git a/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java b/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java index 4382649052..544ca33be1 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java @@ -1,11 +1,10 @@ package com.fr.design.mainframe.share.collect; -import com.fanruan.cloud.FanruanCloud; +import com.fanruan.carina.Carina; +import com.fanruan.config.bbs.FineBBSConfigProvider; import com.fr.base.io.XMLReadHelper; -import com.fr.config.MarketConfig; import com.fr.design.DesignerEnvManager; import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo; -import com.fr.design.mainframe.share.ComponentShareUtil; import com.fr.form.share.DefaultSharableWidget; import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.constants.ComponentPath; @@ -530,7 +529,7 @@ public class ComponentCollector implements XMLable { public String generateTotalInfo() { collectCmpNumber(); JSONObject jo = JSONObject.create(); - jo.put("userId", FanruanCloud.marketService().getBbsUid()); + jo.put("userId", Carina.config(FineBBSConfigProvider.class).getBbsUid()); jo.put("uuid", uuid); jo.put("cmpBoardClickDaily", cmpBoardClickDaily()); jo.put("pluginVersion", GeneralUtils.getVersion()); diff --git a/designer-base/src/main/java/com/fr/design/roleAuthority/RoleTree.java b/designer-base/src/main/java/com/fr/design/roleAuthority/RoleTree.java index b52561c055..743dc4a754 100644 --- a/designer-base/src/main/java/com/fr/design/roleAuthority/RoleTree.java +++ b/designer-base/src/main/java/com/fr/design/roleAuthority/RoleTree.java @@ -64,7 +64,11 @@ public class RoleTree extends UserObjectRefreshJTree { @Override protected ExpandMutableTreeNode[] loadChildTreeNodes(ExpandMutableTreeNode selectedTreeNode) { // 启动平台模块加载角色列表, server内部已经做了启动状态与Workspace判断. - FineEmbedServer.start(); + try { + FineEmbedServer.start(); + } catch (Exception e) { + throw new RuntimeException(e); + } return super.loadChildTreeNodes(selectedTreeNode); } diff --git a/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java b/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java index 4779f91916..f218a15e23 100644 --- a/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java @@ -31,6 +31,7 @@ import com.fr.stable.plugin.ExtraDesignClassManagerProvider; import com.fr.start.ServerStarter; import com.fr.start.common.DesignerStartupContext; import com.fr.start.common.DesignerStartupUtil; +import com.fr.start.server.DesignEmbedHelper; import com.fr.value.NotNullLazyValue; import com.fr.workspace.WorkContext; import org.jetbrains.annotations.NotNull; @@ -425,7 +426,7 @@ public class DesignUtils { } } else { try { - String web = GeneralContext.getCurrentAppNameOfEnv(); + String web = DesignEmbedHelper.getAppFolderName(); String url = "http://localhost:" + DesignerEnvManager.getEnvManager().getEmbedServerPort() + "/" + web + "/" + ServerConfig.getInstance().getServletName() + baseRoute + postfixOfUri; diff --git a/designer-base/src/main/java/com/fr/start/ServerStarter.java b/designer-base/src/main/java/com/fr/start/ServerStarter.java index d2b8498bb9..e3bd6d6b75 100644 --- a/designer-base/src/main/java/com/fr/start/ServerStarter.java +++ b/designer-base/src/main/java/com/fr/start/ServerStarter.java @@ -47,7 +47,11 @@ public class ServerStarter { @Override public void run() { try { - FineEmbedServer.start(); + try { + FineEmbedServer.start(); + } catch (Exception e) { + throw new RuntimeException(e); + } } finally { FineEmbedServerMonitor.getInstance().setComplete(); } @@ -58,7 +62,11 @@ public class ServerStarter { } else if (!FineEmbedServer.isRunning()) { // 普通方式启动内置服务器 try { - FineEmbedServer.start(); + try { + FineEmbedServer.start(); + } catch (Exception e) { + throw new RuntimeException(e); + } } finally { BrowseUtils.browser(url); } diff --git a/designer-base/src/main/java/com/fr/start/server/DesignEmbedHelper.java b/designer-base/src/main/java/com/fr/start/server/DesignEmbedHelper.java new file mode 100644 index 0000000000..487e278647 --- /dev/null +++ b/designer-base/src/main/java/com/fr/start/server/DesignEmbedHelper.java @@ -0,0 +1,201 @@ +package com.fr.start.server; + +import com.fr.cbb.websocket.core.WebSocketEndpoint; +import com.fr.design.DesignerEnvManager; +import com.fr.log.FineLoggerFactory; +import com.fr.module.ModuleRole; +import com.fr.stable.EncodeConstants; +import com.fr.stable.StringUtils; +import com.fr.third.guava.collect.Sets; +import com.fr.third.springframework.web.SpringServletContainerInitializer; +import com.fr.third.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import com.fr.workspace.WorkContext; +import org.apache.catalina.Context; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.loader.WebappLoader; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.webresources.StandardRoot; +import org.apache.tomcat.websocket.server.WsSci; +;import java.io.File; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + +/** + * 内置服务器工具类 + * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/6/18 + */ +public class DesignEmbedHelper { + + private static final String TOMCAT_MAX_HEADER_SIZE = "tomcat-maxHttpHeaderSize"; + + private static Tomcat tomcat; + + /** + * 启动tomcat + */ + public static synchronized void start() { + + try { + FineEmbedServerMonitor.getInstance().reset(); + //初始化tomcat + initTomcat(); + tomcat.start(); + + } catch (LifecycleException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } finally { + FineEmbedServerMonitor.getInstance().setComplete(); + } + } + + /** + * 停止tomcat + */ + public static synchronized void stop() { + + try { + stopSpring(); + stopServerActivator(); + stopTomcat(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + private static void initTomcat() { + + tomcat = new Tomcat(); + + tomcat.setPort(DesignerEnvManager.getEnvManager().getEmbedServerPort()); + // 设置解码uri使用的字符编码 + tomcat.getConnector().setURIEncoding(EncodeConstants.ENCODING_UTF_8); + // 参考 https://jira.atlassian.com/browse/CONFSERVER-57582 + // https://tomcat.apache.org/tomcat-8.5-doc/config/http.html + // 8.5.x 请求参数带特殊字符被tomcat拒绝 []|{}^\`"<> + tomcat.getConnector().setProperty("relaxedQueryChars", "[]|{}^\`"<>"); + setMaxPostSize(); + setMaxHttpHeaderSize(); + Paths.get(System.getProperty("user.dir")).getParent().toAbsolutePath().normalize().toString(); + String docBase = new File(WorkContext.getCurrent().getPath()).getParent(); + + //内置的上下文使用工程目录比如webroot + String contextPath = "/" + getAppFolderName(); + final Context context = tomcat.addContext(contextPath, docBase); + context.setResources(new StandardRoot(context)); + Tomcat.initWebappDefaults(context); + //覆盖tomcat的WebAppClassLoader + context.setLoader(new FRTomcatLoader()); + + + //直接指定initializer,tomcat就不用再扫描一遍了 + SpringServletContainerInitializer initializer = new SpringServletContainerInitializer(); + Set> classes = new HashSet>(); + classes.add(EmbedWebApplicationInitializer.class); + context.addServletContainerInitializer(initializer, classes); + context.addServletContainerInitializer(new WsSci(), Sets.newHashSet(WebSocketEndpoint.class)); + } + + /** + * 获取App文件夹名称 + */ + public static String getAppFolderName() { + String webApplication = new File(WorkContext.getCurrent().getPath()).getParent(); + return webApplication == null + ? StringUtils.EMPTY + : new File(webApplication).getName().replaceAll(".war", StringUtils.EMPTY); + } + + // tomcat的maxPostSize会影响到post参数获取,默认2M + private static void setMaxPostSize() { + + if (System.getProperty("tomcat-maxPostSize") != null) { + try { + tomcat.getConnector().setMaxPostSize(Integer.parseInt(System.getProperty("tomcat-maxPostSize"))); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("maxPostSize error: " + e.getMessage(), e); + } + } + } + + private static void setMaxHttpHeaderSize() { + String value = System.getProperty(TOMCAT_MAX_HEADER_SIZE); + if (StringUtils.isNotEmpty(value)) { + try { + tomcat.getConnector().setProperty("maxHttpHeaderSize", value); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + + private static String getDocBase() { + String path = Paths.get(System.getProperty("user.dir")).getParent().toAbsolutePath().normalize().toString(); + boolean isBuildProject = false; + String docBase = null; + Path libPath = Paths.get(path, "lib"); + Path buildPath = Paths.get(path, "serviceBuild"); + if (!Files.exists(libPath, new LinkOption[0])) { + if (Files.exists(buildPath, new LinkOption[0])) { + isBuildProject = true; + docBase = buildPath.toAbsolutePath().normalize().toString(); + } else { + buildPath = Paths.get(System.getProperty("user.dir"), "build"); + if (Files.exists(buildPath, new LinkOption[0])) { + isBuildProject = true; + String base = buildPath.toAbsolutePath().normalize().toString(); + docBase = base; + } + } + } else { + docBase = libPath.toAbsolutePath().normalize().toString(); + } + + return docBase; + } + private static String getContextPath(Properties carinaBootProp) { + String contextPath = "/webroot"; + return contextPath; + } + private static void stopServerActivator() { + + ModuleRole.ServerRoot.stop(); + } + + private static void stopSpring() { + + AnnotationConfigWebApplicationContext context = ModuleRole.ServerRoot.findSingleton(AnnotationConfigWebApplicationContext.class); + if (context != null) { + context.stop(); + context.destroy(); + } + } + + private static void stopTomcat() throws LifecycleException { + + tomcat.stop(); + tomcat.destroy(); + } + + + /** + * Created by juhaoyu on 2018/6/5. + * 自定义的tomcat loader,主要用于防止内置服务器再加载一遍class + */ + private static class FRTomcatLoader extends WebappLoader { + + @Override + public ClassLoader getClassLoader() { + + return this.getClass().getClassLoader(); + } + + } +} diff --git a/designer-base/src/main/java/com/fr/start/server/DesignEmbedLauncher.java b/designer-base/src/main/java/com/fr/start/server/DesignEmbedLauncher.java new file mode 100644 index 0000000000..787892df56 --- /dev/null +++ b/designer-base/src/main/java/com/fr/start/server/DesignEmbedLauncher.java @@ -0,0 +1,34 @@ +package com.fr.start.server; + +import com.fanruan.carina.Carina; +import com.fanruan.carina.context.CarinaApplicationContext; +import com.fanruan.carina.launch.XmlCarinaLauncher; + +import javax.servlet.ServletContext; +import java.util.Properties; + + +/** + * 内置服务器launcher + * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/6/18 + */ +public class DesignEmbedLauncher extends XmlCarinaLauncher { + public DesignEmbedLauncher() { + super( + Carina.getApplicationContext().getPartitionManager(), + Carina.getApplicationContext().getServletContext(), + Carina.getApplicationContext().getCarinaApplicationProperties(), + "/com/fr/config/starter/designer-server.xml" + ); + } + + @Override + protected CarinaApplicationContext createApplicationContext(ServletContext servletContext, Properties carinaApplicationProperties) { + return Carina.getApplicationContext(); + } + + +} diff --git a/designer-base/src/main/java/com/fr/start/server/EmbedWebApplicationInitializer.java b/designer-base/src/main/java/com/fr/start/server/EmbedWebApplicationInitializer.java new file mode 100644 index 0000000000..7190aad7dd --- /dev/null +++ b/designer-base/src/main/java/com/fr/start/server/EmbedWebApplicationInitializer.java @@ -0,0 +1,32 @@ +package com.fr.start.server; + +import com.fanruan.carina.Carina; +import com.fr.third.springframework.web.WebApplicationInitializer; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +/** + * 内置服务器WebApplicationInitializer + *

用于FR服务的WebApplication初始化

+ * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/6/18 + */ +public class EmbedWebApplicationInitializer implements WebApplicationInitializer { + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + if (Carina.getApplicationContext().getServletContext() instanceof ServletContextWrapper) { + ServletContextWrapper wrapper = (ServletContextWrapper) Carina.getApplicationContext().getServletContext(); + wrapper.update(servletContext); + DesignEmbedLauncher launcher = new DesignEmbedLauncher(); + try { + launcher.launch(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + } +} diff --git a/designer-realize/src/main/java/com/fr/start/EmptyServletContext.java b/designer-base/src/main/java/com/fr/start/server/EmptyServletContext.java similarity index 99% rename from designer-realize/src/main/java/com/fr/start/EmptyServletContext.java rename to designer-base/src/main/java/com/fr/start/server/EmptyServletContext.java index 89b1f72ef2..a641673463 100644 --- a/designer-realize/src/main/java/com/fr/start/EmptyServletContext.java +++ b/designer-base/src/main/java/com/fr/start/server/EmptyServletContext.java @@ -1,4 +1,4 @@ -package com.fr.start; +package com.fr.start.server; import com.fr.stable.StringUtils; diff --git a/designer-base/src/main/java/com/fr/start/server/FineEmbedServer.java b/designer-base/src/main/java/com/fr/start/server/FineEmbedServer.java index efc2ebd594..ad258131dd 100644 --- a/designer-base/src/main/java/com/fr/start/server/FineEmbedServer.java +++ b/designer-base/src/main/java/com/fr/start/server/FineEmbedServer.java @@ -1,5 +1,6 @@ package com.fr.start.server; +import com.fanruan.carina.Carina; import com.fr.event.EventDispatcher; import com.fr.module.ModuleContext; @@ -13,25 +14,23 @@ public abstract class FineEmbedServer { */ private static volatile boolean onStarting = false; - public synchronized static void start() { - // // 内置服务器先去除 - // onStarting = true; - // EventDispatcher.fire(EmbedServerEvent.BeforeStart); - // ModuleContext.getModule(FineEmbedServerActivator.class).start(); - // onStarting = false; - // EventDispatcher.fire(EmbedServerEvent.AfterStart); + public synchronized static void start() throws Exception { + onStarting = true; + EventDispatcher.fire(EmbedServerEvent.BeforeStart); + DesignEmbedHelper.start(); + onStarting = false; + EventDispatcher.fire(EmbedServerEvent.AfterStart); } public synchronized static void stop() { - // //内置服务器先去除 - // EventDispatcher.fire(EmbedServerEvent.BeforeStop); - // ModuleContext.getModule(FineEmbedServerActivator.class).stop(); - // EventDispatcher.fire(EmbedServerEvent.AfterStop); + EventDispatcher.fire(EmbedServerEvent.BeforeStop); + ModuleContext.getModule(FineEmbedServerActivator.class).stop(); + EventDispatcher.fire(EmbedServerEvent.AfterStop); } public static boolean isRunning() { - return false; + return Carina.partition("fine_report") != null && Carina.partition("fine_report").getReady(); } public static boolean isOnStarting() { diff --git a/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java b/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java index 1ad9d8af1a..37b6effacb 100644 --- a/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java +++ b/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java @@ -7,8 +7,6 @@ import com.fr.module.ModuleRole; import com.fr.stable.EncodeConstants; import com.fanruan.product.ProductConstants; import com.fr.stable.StringUtils; -import com.fr.startup.FineWebApplicationInitializer; -import com.fr.third.guava.collect.Sets; import com.fr.third.springframework.web.SpringServletContainerInitializer; import com.fr.third.springframework.web.context.support.AnnotationConfigWebApplicationContext; import com.fr.workspace.WorkContext; @@ -27,6 +25,7 @@ import java.util.Set; /** * Created by juhaoyu on 2018/6/5. */ +@Deprecated public class FineEmbedServerActivator extends Activator { private static final String TOMCAT_MAX_HEADER_SIZE = "tomcat-maxHttpHeaderSize"; @@ -92,7 +91,7 @@ public class FineEmbedServerActivator extends Activator { //直接指定initializer,tomcat就不用再扫描一遍了 SpringServletContainerInitializer initializer = new SpringServletContainerInitializer(); Set> classes = new HashSet>(); - classes.add(FineWebApplicationInitializer.class); + //classes.add(FineWebApplicationInitializer.class); context.addServletContainerInitializer(initializer, classes); // 后面本地设计的内置服务器考虑用XST // context.addServletContainerInitializer(new WsSci(), Sets.newHashSet(WebSocketEndpoint.class)); diff --git a/designer-base/src/main/java/com/fr/start/server/ServletContextWrapper.java b/designer-base/src/main/java/com/fr/start/server/ServletContextWrapper.java new file mode 100644 index 0000000000..eddece1b41 --- /dev/null +++ b/designer-base/src/main/java/com/fr/start/server/ServletContextWrapper.java @@ -0,0 +1,307 @@ +package com.fr.start.server; + + +import javax.servlet.Filter; +import javax.servlet.FilterRegistration; +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; +import javax.servlet.SessionCookieConfig; +import javax.servlet.SessionTrackingMode; +import javax.servlet.descriptor.JspConfigDescriptor; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.Map; +import java.util.Set; + +/** + * 内置服务器的ServletContext包装 + * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/6/18 + */ +public class ServletContextWrapper implements ServletContext { + public static final ServletContext EMPTY = new EmptyServletContext(); + private ServletContext context = EMPTY; + + @Override + public String getContextPath() { + return context.getContextPath(); + } + + @Override + public ServletContext getContext(String s) { + return context.getContext(s); + } + + @Override + public int getMajorVersion() { + return context.getMajorVersion(); + } + + @Override + public int getMinorVersion() { + return context.getMinorVersion(); + } + + @Override + public int getEffectiveMajorVersion() { + return context.getEffectiveMajorVersion(); + } + + @Override + public int getEffectiveMinorVersion() { + return context.getEffectiveMinorVersion(); + } + + @Override + public String getMimeType(String s) { + return context.getMimeType(s); + } + + @Override + public Set getResourcePaths(String s) { + return context.getResourcePaths(s); + } + + @Override + public URL getResource(String s) throws MalformedURLException { + return context.getResource(s); + } + + @Override + public InputStream getResourceAsStream(String s) { + return context.getResourceAsStream(s); + } + + @Override + public RequestDispatcher getRequestDispatcher(String s) { + return context.getRequestDispatcher(s); + } + + @Override + public RequestDispatcher getNamedDispatcher(String s) { + return context.getNamedDispatcher(s); + } + + @Override + public Servlet getServlet(String s) throws ServletException { + return context.getServlet(s); + } + + @Override + public Enumeration getServlets() { + return context.getServlets(); + } + + @Override + public Enumeration getServletNames() { + return context.getServletNames(); + } + + @Override + public void log(String s) { + context.log(s); + } + + @Override + public void log(Exception e, String s) { + context.log(e, s); + } + + @Override + public void log(String s, Throwable throwable) { + context.log(s, throwable); + } + + @Override + public String getRealPath(String s) { + return context.getRealPath(s); + } + + @Override + public String getServerInfo() { + return context.getServerInfo(); + } + + @Override + public String getInitParameter(String s) { + return context.getInitParameter(s); + } + + @Override + public Enumeration getInitParameterNames() { + return context.getInitParameterNames(); + } + + @Override + public boolean setInitParameter(String s, String s1) { + return context.setInitParameter(s, s1); + } + + @Override + public Object getAttribute(String s) { + return context.getAttribute(s); + } + + @Override + public Enumeration getAttributeNames() { + return context.getAttributeNames(); + } + + @Override + public void setAttribute(String s, Object o) { + context.setAttribute(s, o); + } + + @Override + public void removeAttribute(String s) { + context.removeAttribute(s); + } + + @Override + public String getServletContextName() { + return context.getServletContextName(); + } + + @Override + public ServletRegistration.Dynamic addServlet(String s, String s1) { + return context.addServlet(s, s1); + } + + @Override + public ServletRegistration.Dynamic addServlet(String s, Servlet servlet) { + return context.addServlet(s, servlet); + } + + @Override + public ServletRegistration.Dynamic addServlet(String s, Class aClass) { + return context.addServlet(s, aClass); + } + + @Override + public T createServlet(Class aClass) throws ServletException { + return context.createServlet(aClass); + } + + @Override + public ServletRegistration getServletRegistration(String s) { + return context.getServletRegistration(s); + } + + @Override + public Map getServletRegistrations() { + return context.getServletRegistrations(); + } + + @Override + public FilterRegistration.Dynamic addFilter(String s, String s1) { + return context.addFilter(s, s1); + } + + @Override + public FilterRegistration.Dynamic addFilter(String s, Filter filter) { + return context.addFilter(s, filter); + } + + @Override + public FilterRegistration.Dynamic addFilter(String s, Class aClass) { + return context.addFilter(s, aClass); + } + + @Override + public T createFilter(Class aClass) throws ServletException { + return context.createFilter(aClass); + } + + @Override + public FilterRegistration getFilterRegistration(String s) { + return context.getFilterRegistration(s); + } + + @Override + public Map getFilterRegistrations() { + return context.getFilterRegistrations(); + } + + @Override + public SessionCookieConfig getSessionCookieConfig() { + return context.getSessionCookieConfig(); + } + + @Override + public void setSessionTrackingModes(Set set) { + context.setSessionTrackingModes(set); + } + + @Override + public Set getDefaultSessionTrackingModes() { + return context.getDefaultSessionTrackingModes(); + } + + @Override + public Set getEffectiveSessionTrackingModes() { + return context.getEffectiveSessionTrackingModes(); + } + + @Override + public void addListener(String s) { + context.addListener(s); + } + + @Override + public void addListener(T t) { + context.addListener(t); + } + + @Override + public void addListener(Class aClass) { + context.addListener(aClass); + } + + @Override + public T createListener(Class aClass) throws ServletException { + return context.createListener(aClass); + } + + @Override + public JspConfigDescriptor getJspConfigDescriptor() { + return context.getJspConfigDescriptor(); + } + + @Override + public ClassLoader getClassLoader() { + return context.getClassLoader(); + } + + @Override + public void declareRoles(String... strings) { + context.declareRoles(strings); + } + + @Override + public String getVirtualServerName() { + return context.getVirtualServerName(); + } + + /** + * 重置 + */ + public void reset() { + context = EMPTY; + } + + + /** + * 更新context + */ + public void update(ServletContext context) { + this.context = context; + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/generate/task/ComponentUploader.java b/designer-form/src/main/java/com/fr/design/mainframe/share/generate/task/ComponentUploader.java index ec7e705add..dfc08ed53d 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/generate/task/ComponentUploader.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/generate/task/ComponentUploader.java @@ -1,7 +1,7 @@ package com.fr.design.mainframe.share.generate.task; -import com.fanruan.cloud.FanruanCloud; -import com.fr.config.MarketConfig; +import com.fanruan.carina.Carina; +import com.fanruan.config.bbs.FineBBSConfigProvider; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.share.config.ComponentReuseConfigManager; import com.fr.design.mainframe.share.generate.ComponentBanner; @@ -103,8 +103,8 @@ public class ComponentUploader implements ComponentBanner { private boolean login(CloseableHttpClient client) throws IOException { - String bbsUsername = FanruanCloud.marketService().getBbsUsername(); - String bbsPassword = FanruanCloud.marketService().getBbsPassword(); + String bbsUsername = Carina.config(FineBBSConfigProvider.class).getBbsUsername(); + String bbsPassword = Carina.config(FineBBSConfigProvider.class).getBbsPassword(); List pairs = new ArrayList<>(); pairs.add(new BasicNameValuePair(KEY_USERNAME, bbsUsername)); pairs.add(new BasicNameValuePair(KEY_PASSWORD, bbsPassword)); diff --git a/designer-realize/src/main/java/com/fanruan/boot/ConfigHelper.java b/designer-realize/src/main/java/com/fanruan/boot/ConfigHelper.java new file mode 100644 index 0000000000..b987a1e277 --- /dev/null +++ b/designer-realize/src/main/java/com/fanruan/boot/ConfigHelper.java @@ -0,0 +1,71 @@ +package com.fanruan.boot; + +import com.fanruan.carina.Carina; +import com.fanruan.product.ProductConstants; +import com.fr.io.utils.ResourceIOUtils; +import com.fr.log.FineLoggerFactory; + + +import java.io.File; +import java.io.InputStream; +import java.util.Properties; + +/** + * 配置工具类 + * + *
  • 1.获取基础配置
  • + *
  • 2.获取环境配置
  • + *
  • 3.基础的变量定义与对应环境配置路径获取
  • + *
    + * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/6/26 + */ +public class ConfigHelper { + public static final String BASE = ProductConstants.getEnvHome() + File.separator + ProductConstants.APP_NAME; + public static final String TAIL = ".properties"; + public static final String BASE_PATH = BASE + "BaseProperties" + TAIL; + + + /** + * 获取基础的配置(工作环境无关的配置内容,所有工作环境共用一份) + */ + public static Properties getBaseProperties() { + return getProperties(BASE_PATH, null); + } + + + /** + * 获取当前环境配置 + */ + public static Properties getEnvProperties() { + return getProperties(getEnvPropertiesPath(), getBaseProperties()); + } + + /** + * 获取当前环境配置的路径 + */ + public static String getEnvPropertiesPath() { + return BASE + Carina.getApplicationContext().getWebInfPath().replace("\\", "_").replace("/", "_").replace(":", "_") + TAIL; + } + + private static Properties getProperties(String path, Properties defaultValue){ + Properties properties = new Properties(); + if (defaultValue != null) { + properties.putAll(defaultValue); + } + try { + if (!ResourceIOUtils.exist(path)) { + ResourceIOUtils.createFile(path); + } + try (InputStream is = ResourceIOUtils.read(path)){ + properties.load(is); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + } + + return properties; + } +} diff --git a/designer-realize/src/main/java/com/fanruan/boot/adaptation/ReportAdaptationComponent.java b/designer-realize/src/main/java/com/fanruan/boot/adaptation/ReportAdaptationComponent.java new file mode 100644 index 0000000000..30eeb3f302 --- /dev/null +++ b/designer-realize/src/main/java/com/fanruan/boot/adaptation/ReportAdaptationComponent.java @@ -0,0 +1,41 @@ +package com.fanruan.boot.adaptation; + +import com.fanruan.carina.Carina; +import com.fanruan.carina.annotions.FineComponent; +import com.fanruan.carina.annotions.Start; +import com.fr.general.I18nResource; +import com.fr.general.InterProviderImpl; +import com.fr.locale.InterMutableKey; +import com.fr.locale.LocaleMarker; +import com.fr.locale.LocaleScope; + +/** + * 用于内置服务器检查并适配其他FR服务细节的模块 + *

    当前需要检查一下国际化,后续应该还有东西

    + * + * @author Destiny.Lin + * @since 11.0 + * Created on 2024/6/24 + */ +@FineComponent(name = "fine_report_adaptation") +public class ReportAdaptationComponent { + + @Start + public void start() { + checkI18n(); + } + + private void checkI18n() { + for (LocaleMarker marker : Carina.getApplicationContext().group(InterMutableKey.class).getAll()) { + if (marker.match(LocaleScope.SERVER)) { + // richie:服务器端国际化的文件进来 + InterProviderImpl.getInstance().addResource(marker.getPath()); + } + if (marker.match(LocaleScope.WEB)) { + //web端 + I18nResource.getInstance().addResource(marker.getPath()); + } + } + + } +} diff --git a/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvChooseComponent.java b/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvChooseComponent.java index 7c4faa30ad..20a92f2c54 100644 --- a/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvChooseComponent.java +++ b/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvChooseComponent.java @@ -1,14 +1,15 @@ package com.fanruan.boot.env; +import com.fanruan.boot.ConfigHelper; import com.fanruan.boot.key.StartupArgsShell; import com.fanruan.carina.Carina; -import com.fanruan.carina.annotions.ActivatorRefer; import com.fanruan.carina.annotions.FineComponent; import com.fanruan.carina.annotions.Start; import com.fanruan.carina.annotions.Stop; import com.fanruan.carina.annotions.Supplemental; -import com.fanruan.carina.lifecycle.bootstrap.BootUnit; import com.fanruan.carina.lifecycle.bootstrap.BootstrapFactory; +import com.fanruan.config.realm.ConfigRepositoryFactory; +import com.fanruan.config.realm.local.LocalConfigRepositoryBuilder; import com.fr.base.operator.org.OrganizationOperator; import com.fr.base.rpc.encrypt.EncryptOperator; import com.fr.decision.service.context.ServiceContext; @@ -106,19 +107,7 @@ public class DesignEnvChooseComponent { @Override public void on(Event event, Workspace current) { try { - BootstrapFactory.get().stop("design_env_prepare"); - BootstrapFactory.get().resetStatus("design_env_prepare", BootUnit.State.SUPPLEMENTED); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - }; - private Listener afterSwitch4Max = new Listener(Integer.MAX_VALUE) { - - @Override - public void on(Event event, Workspace current) { - try { - BootstrapFactory.get().start("design_function"); + BootstrapFactory.get().reboot("design_env_prepare"); } catch (Exception e) { throw new RuntimeException(e); } @@ -204,19 +193,23 @@ public class DesignEnvChooseComponent { EnvChangeEntrance.getInstance().dealEvnExceptionWhenStartDesigner(e, workspaceInfo); } } + updateConfigBuilder(); pluginErrorRemind(); editLockCheckerStart(); } + private void updateConfigBuilder() { + ConfigRepositoryFactory.getInstance().reset(); + ConfigRepositoryFactory.getInstance().registerConfigRepositoryBuilder(new LocalConfigRepositoryBuilder(ConfigHelper.getEnvProperties(), ConfigHelper.getEnvPropertiesPath())); + } + /** * 注册切换环境前后事件监听 */ private void registerEnvListener() { - /*切换环境前,关闭所有相关模块,最后执行*/ + /*切换环境前,重启所有相关模块,最后执行*/ EventDispatcher.listen(WorkspaceEvent.BeforeSwitch, beforeSwitch4Min); - /*切换环境后,重新启动所有相关模块,最先执行*/ - EventDispatcher.listen(WorkspaceEvent.AfterSwitch, afterSwitch4Max); /*切换环境前,存储一下打开的所有文件对象,要先于 关闭相关模块部分 被触发*/ EventDispatcher.listen(WorkspaceEvent.BeforeSwitch, beforeSwitch4Max); @@ -289,7 +282,6 @@ public class DesignEnvChooseComponent { EventDispatcher.stopListen(beforeSwitch4Max); EventDispatcher.stopListen(beforeSwitch4Min); EventDispatcher.stopListen(afterSwitch4Min); - EventDispatcher.stopListen(afterSwitch4Max); } } diff --git a/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvComponent.java b/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvComponent.java index 3218172853..55799fc3ec 100644 --- a/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvComponent.java +++ b/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvComponent.java @@ -1,28 +1,29 @@ package com.fanruan.boot.env; import com.fanruan.boot.FSProperties; +import com.fanruan.boot.KVProperties; import com.fanruan.boot.LoggerProperties; -import com.fanruan.boot.mem.MemConfigRepositoryBuilder; import com.fanruan.carina.Carina; import com.fanruan.carina.annotions.FineComponent; import com.fanruan.carina.annotions.JPAEntityScan; import com.fanruan.carina.annotions.Start; import com.fanruan.carina.annotions.Stop; -import com.fanruan.carina.annotions.Supplemental; import com.fanruan.config.ConfigProviderFactory; import com.fanruan.config.realm.ConfigRealm; import com.fanruan.dao.context.DBContextProvider; import com.fanruan.dao.context.DBContextStarter; -import com.fanruan.dao.encryption.EncryptionInitializationProvider; -import com.fanruan.dao.encryption.singleton.EncryptionInitializationProviderSingleton; import com.fanruan.dao.property.DBPropertyProvider; import com.fanruan.dao.shell.DBContextShell; import com.fanruan.dao.shell.DBPropertyShell; import com.fanruan.fs.DesignFileRepository; -import com.fanruan.fs.FSConstants; import com.fanruan.fs.FileServer; import com.fanruan.fs.RepositoryFactory; import com.fanruan.fs.repository.local.LocalFileRepository; +import com.fanruan.kv.CarinaKV; +import com.fanruan.kv.factory.KVStoreFactory; +import com.fanruan.kv.manager.CarinaKVManager; +import com.fanruan.kv.store.KVStore; +import com.fanruan.kv.store.KVStoreHolder; import com.fr.cbb.dialect.security.InsecurityElementFactory; import com.fr.config.BaseDBEnv; import com.fr.config.ConfigContext; @@ -50,12 +51,13 @@ import com.fr.io.repository.ResourceRepository; import com.fr.io.repository.ResourceRepositoryWrapper; import com.fr.io.utils.ResourceIOUtils; import com.fr.log.FineLoggerFactory; -import com.fr.properties.encryption.EncryptionInitialization; + +import com.fr.security.encryption.EncryptionInitialization; import com.fr.security.encryption.core.EncryptionScaffold; import com.fr.security.encryption.provider.SecuritySeedProvider; import com.fr.security.encryption.storage.keys.LoadSeedSecurityKey; -import com.fr.stable.CarinaGraphDrawHelper; -import com.fr.stable.CoreGraphDrawServiceImpl; + +import com.fr.stable.GraphDrawHelper; import com.fr.stable.StringUtils; import com.fr.stable.db.DBContext; import com.fr.stable.db.properties.FineMicroServicesDBProperties; @@ -78,16 +80,13 @@ import java.util.Objects; * Created on 2024/6/7 */ @FineComponent(name = "design_env_prepare") -@JPAEntityScan("com.fr.config.entity") +@JPAEntityScan({"com.fr.config.entity", + "com.fr.decision.authority.entity", + "com.fanruan.user.oa.basic.db.entity", + "com.fr.decision.system.entity", + "com.fr.decision.workflow.bean"}) public class DesignEnvComponent { - @Supplemental - public void supplemental() { - supplementalCorePrepare(); - } - - - @Start public void start() throws Exception { @@ -103,10 +102,13 @@ public class DesignEnvComponent { startFileServer(); // 6.logger启动 startLogger(); + // 7.kv + startKv(); } + @Stop public void stop() { stopLogger(); @@ -122,6 +124,14 @@ public class DesignEnvComponent { * -------------------private------------------- */ + /** + * ----------kv--------- + */ + private void startKv() { + KVStore kvStore = KVStoreFactory.createFineKVStore(Carina.properties(KVProperties.class).getType()); + KVStoreHolder.getInstance().setStore(kvStore); + CarinaKV.switchTo(new CarinaKVManager()); + } /** * ----------- logger -------- @@ -147,14 +157,10 @@ public class DesignEnvComponent { FSProperties fsProperties = Carina.properties(FSProperties.class); FileServer.init( new ResourceRepositoryWrapper(localFileRepository, StringUtils.EMPTY), - new ResourceRepositoryWrapper(realRepo, Carina.getApplicationContext().getMainServletName()), - new ResourceRepositoryWrapper(realRepo, FSConstants.PUBLIC_NAMESPACE), + new ResourceRepositoryWrapper(realRepo, StringUtils.EMPTY), + new ResourceRepositoryWrapper(realRepo, StringUtils.EMPTY), new ResourceRepositoryWrapper(realRepo.generateTenantsSharedRepo(fsProperties.getTenantsSharedNamespace()), StringUtils.EMPTY)); - if (StringUtils.isEmpty(fsProperties.getPath()) && Objects.equals(fsProperties.getType(), FSConstants.LOCAL_ENV)) { - fsProperties.setPath(Carina.getApplicationContext().getWebInfPath()); - } - ResourceIOUtils.setUnderlying(FileServer.local()); ResourceIOUtils.setIsolationMode(false); @@ -178,13 +184,6 @@ public class DesignEnvComponent { private void startDao() { if (WorkContext.getCurrent().isLocal()) { // 类似com.fr.config.activator.BaseDBActivator.start里的逻辑 - EncryptionInitializationProvider initializationProvider = Carina.getApplicationContext().singleton(EncryptionInitializationProviderSingleton.class).get(); - if (initializationProvider != null) { - initializationProvider.init(); - } else { - throw new IllegalStateException("no EncryptionInitializationProvider implementation found, this may cause encryption exception."); - } - DBPropertyProvider dbPropertyProvider = FineMicroServicesDBProperties.getInstance().from(Carina.getApplicationContext().getCarinaApplicationProperties()); DBContextProvider dbContextProvider = new DBContextStarter(dbPropertyProvider).start(); @@ -243,12 +242,10 @@ public class DesignEnvComponent { * --------- core-supplemental -------- */ - private void supplementalCorePrepare() { - Carina.getApplicationContext().singleton(EncryptionInitializationProviderSingleton.class).set(EncryptionInitialization.getInstance()); - } - private void startCorePrepare() { + + EncryptionInitialization.getInstance().init(); EncryptionScaffold.setSecuritySeedProvider(new SecuritySeedProvider() { @Override public byte[] getSeed() { @@ -261,7 +258,6 @@ public class DesignEnvComponent { } }); LoadSeedSecurityKey.getInstance().init(); - CarinaGraphDrawHelper.getInstance().registerGraphDrawHelper(new CoreGraphDrawServiceImpl()); } private void stopCorePrepare() { diff --git a/designer-realize/src/main/java/com/fanruan/boot/init/DesignPreLoadComponent.java b/designer-realize/src/main/java/com/fanruan/boot/init/DesignPreLoadComponent.java index cc9b9db46d..14083d5182 100644 --- a/designer-realize/src/main/java/com/fanruan/boot/init/DesignPreLoadComponent.java +++ b/designer-realize/src/main/java/com/fanruan/boot/init/DesignPreLoadComponent.java @@ -34,11 +34,16 @@ import com.fr.general.FRLogger; import com.fr.general.FrontProviderImpl; import com.fr.general.GeneralContext; import com.fr.general.I18nActivator; +import com.fr.general.I18nResource; import com.fr.general.Inter; import com.fr.general.InterProviderImpl; +import com.fr.general.LocaleType; import com.fr.invoke.ClassFactory; import com.fr.license.function.VT4FR; import com.fr.locale.InterMutableKey; +import com.fr.locale.LocaleMarker; +import com.fr.locale.LocaleScope; +import com.fr.locale.LocaleUtils; import com.fr.log.FineLoggerFactory; import com.fr.measure.DBMeterFactory; import com.fr.record.DefaultDBMeter; @@ -48,6 +53,9 @@ import com.fr.stable.ArrayUtils; import com.fr.stable.CommonUtils; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; +import com.fr.stable.bridge.StableFactory; +import com.fr.stable.fun.WebLocaleProvider; +import com.fr.stable.plugin.ExtraClassManagerProvider; import com.fr.stable.project.ProjectConstants; import com.fr.stable.xml.StableXMLUtils; import com.fr.start.DesignerProcessType; @@ -64,6 +72,8 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; +import java.util.Locale; +import java.util.Set; import java.util.concurrent.TimeUnit; /** @@ -122,8 +132,17 @@ public class DesignPreLoadComponent { */ private void startI18n() { - // 扫描默认路径 - I18nActivator.registerI18N(new ArrayList<>(ServiceContext.group(InterMutableKey.class).getAll())); + for (LocaleMarker marker : Carina.getApplicationContext().group(InterMutableKey.class).getAll()) { + if (marker.match(LocaleScope.SERVER)) { + // richie:服务器端国际化的文件进来 + InterProviderImpl.getInstance().addResource(marker.getPath()); + } + if (marker.match(LocaleScope.WEB)) { + //web端 + I18nResource.getInstance().addResource(marker.getPath()); + } + } + FrontProviderImpl.init(InterProviderImpl.getInstance()); } @@ -131,6 +150,31 @@ public class DesignPreLoadComponent { private void supplementalI18n() { // 国际化插件class自定义管理 Carina.getApplicationContext().group(AutonomyClassManagerGroup.class).add(new ExtraLocaleClassManager()); + + // base-i18n国际化文件注册 + Carina.getApplicationContext().group(InterMutableKey.class).add(LocaleMarker.create("com/fr/i18n/server/core", LocaleScope.SERVER)); + Carina.getApplicationContext().group(InterMutableKey.class).add(LocaleMarker.create("com/fr/i18n/web/core", LocaleScope.WEB)); + Carina.getApplicationContext().group(InterMutableKey.class).add(LocaleMarker.create("com/fr/i18n/function/core", LocaleScope.SERVER)); + Carina.getApplicationContext().group(InterMutableKey.class).add(LocaleMarker.create("com/fr/decision/server/i18n/server", LocaleScope.SERVER)); + Carina.getApplicationContext().group(InterMutableKey.class).add(LocaleMarker.create("com/fr/decision/web/i18n/dec", LocaleScope.WEB)); + Carina.getApplicationContext().group(InterMutableKey.class).add(LocaleMarker.create("com/fr/fineui/i18n/fineui", LocaleScope.WEB)); + Carina.getApplicationContext().group(InterMutableKey.class).add(LocaleMarker.create("com/fr/fineui/i18n/fineui", LocaleScope.SERVER)); + + // WebLocaleProvider插件接口适配 + LocaleUtils.registerLocaleParser(localeStr -> { + ExtraClassManagerProvider provider = StableFactory.getMarkedObject(ExtraClassManagerProvider.XML_TAG, ExtraClassManagerProvider.class); + if (provider != null) { + Set set = provider.getArray(WebLocaleProvider.XML_TAG); + Locale locale; + for (WebLocaleProvider localeProvider : set) { + locale = localeProvider.dispatchLocale(localeStr); + if (locale != null) { + return locale; + } + } + } + return LocaleType.parse(localeStr); + }); } private void stopClass() { diff --git a/designer-realize/src/main/java/com/fanruan/boot/pre/DesignPreStartComponent.java b/designer-realize/src/main/java/com/fanruan/boot/pre/DesignPreStartComponent.java index e4db0280b9..c30a97436d 100644 --- a/designer-realize/src/main/java/com/fanruan/boot/pre/DesignPreStartComponent.java +++ b/designer-realize/src/main/java/com/fanruan/boot/pre/DesignPreStartComponent.java @@ -1,5 +1,6 @@ package com.fanruan.boot.pre; +import com.fanruan.boot.ConfigHelper; import com.fanruan.boot.key.StartupArgsShell; import com.fanruan.boot.mem.MemConfigRepositoryBuilder; import com.fanruan.carina.Carina; @@ -11,9 +12,14 @@ import com.fanruan.config.impl.PublicConfigProviderImpl; import com.fanruan.config.impl.ShareConfigProviderImpl; import com.fanruan.config.realm.ConfigRealm; import com.fanruan.config.realm.ConfigRepositoryFactory; +import com.fanruan.config.realm.local.LocalConfigRepositoryBuilder; +import com.fanruan.mq.CarinaMQ; +import com.fanruan.mq.InternalMQProvider; +import com.fanruan.product.ProductConstants; import com.fr.base.function.UITerminator; -import com.fr.carina.revert.CarinaRevertManager; import com.fr.carina.revert.provider.CarinaPluginProvider; +import com.fr.carina.util.CarinaResourceUtils; +import com.fr.carina.util.provider.CarinaResourceProvider; import com.fr.design.DesignerEnvManager; import com.fr.design.deeplink.DeepLinkManager; import com.fr.design.fun.OemProcessor; @@ -26,13 +32,18 @@ import com.fr.design.utils.DesignerPort; import com.fr.event.Event; import com.fr.event.EventDispatcher; import com.fr.event.Listener; +import com.fr.general.CommonIOUtils; +import com.fr.general.GeneralUtils; import com.fr.log.FineLoggerFactory; import com.fr.module.engine.event.LifecycleErrorEvent; import com.fr.plugin.ExtraClassManager; import com.fr.runtime.FineRuntime; +import com.fr.stable.CommonCodeUtils; +import com.fr.stable.CommonUtils; import com.fr.stable.fun.ResourcePathTransformer; import com.fr.stable.lifecycle.FineLifecycleFatalError; import com.fr.stable.plugin.ExtraClassManagerProvider; +import com.fr.stable.project.ProjectConstants; import com.fr.stable.resource.ResourceLoader; import com.fr.start.DesignerSubListener; import com.fr.start.LifecycleFatalErrorHandler; @@ -49,9 +60,16 @@ import com.fr.tenant.store.impl.DefaultTenantStorage; import com.fr.web.controller.common.FileContentModificator; import com.fr.web.controller.plugin.PluginFileContentModificator; import com.fr.web.file.FileContentProcessorFactory; +import com.fr.workspace.WorkContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.servlet.http.HttpServletRequest; +import java.io.ByteArrayInputStream; +import java.io.File; import java.io.InputStream; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; @@ -68,7 +86,7 @@ import java.util.concurrent.CompletableFuture; public class DesignPreStartComponent { @Start - public void start() { + public void start() throws Exception { // 1.注册ConfigFactory与对应的membuilder startUniversalConfig(); // 2.start本地租户配置 @@ -77,6 +95,12 @@ public class DesignPreStartComponent { startPluginPrepare(); // 4.正式启动 startPre(); + // 5.mq + startMq(); + } + + private void startMq() throws Exception { + CarinaMQ.switchTo(InternalMQProvider.KEY); } private void startPre() { @@ -108,45 +132,53 @@ public class DesignPreStartComponent { } private void startPluginPrepare() { - CarinaRevertManager.setCarinaPluginProvider(new CarinaPluginProvider() { + CarinaResourceUtils.registerCarinaResourceProvider(new CarinaResourceProvider() { @Override - public InputStream getResourceAsStream(String name, Class caller) { - return ResourceLoader.getResourceAsStream(name, caller); + public @NotNull String name() { + return "WorkContextCPTAndXML"; } @Override - public String transformPath(String path) { - Set set = getResourcePathTransformers(); - for (ResourcePathTransformer transformer : set) { - if (transformer.accept(path)) { - return transformer.transform(path); - } - } - return path; + public int priority() { + return 1; } @Override - public String dealWithFileContentModificator(String content, HttpServletRequest req, String path) { - String modifiedContent = FileContentProcessorFactory.getInstance().modify(content, path, req); - FileContentModificator pluginFileContentModificator = new PluginFileContentModificator(); - if (pluginFileContentModificator.accept(req, path)) { - return pluginFileContentModificator.modify(modifiedContent, req, path); + public @Nullable InputStream getResource(@NotNull String resourcePath) { + + if (!resourcePath.startsWith("/")) { + resourcePath = "/" + resourcePath; } - return modifiedContent; - } + InputStream result = null; + + try { + if (resourcePath.endsWith(".cpt")) { + result = new ByteArrayInputStream(WorkContext.getWorkResource().readFully(CommonUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, resourcePath))); + } + + if (resourcePath.endsWith(".xml")) { + result = new ByteArrayInputStream(WorkContext.getWorkResource().readFully(CommonUtils.pathJoin(ProjectConstants.RESOURCES_NAME, resourcePath))); + } + + if (result != null) { + String content = CommonCodeUtils.passwordEncode(CommonIOUtils.inputStream2String(result, "UTF-8")); + return new ByteArrayInputStream(content.getBytes("UTF-8")); + } + } catch (Exception ignored) { - private Set getResourcePathTransformers() { - Set set = new HashSet<>(); - ExtraClassManagerProvider provider = ExtraClassManager.getInstance(); - if (provider != null) { - Set pluginProvided = provider.getArray(ResourcePathTransformer.MARK_STRING); - set.addAll(pluginProvided); } - return set; + if (resourcePath.startsWith("/")) { + result = ResourceLoader.getResourceAsStream(resourcePath, GeneralUtils.class); + } else { + result = ResourceLoader.getResourceAsStream("/" + resourcePath, GeneralUtils.class); + } + return result; } }); + } + private void startTenant() { TenantContext.registerStorage(new DefaultTenantStorage()); TenantContext.registerConfigProvider(new TenantConfigProvider() { @@ -161,7 +193,8 @@ public class DesignPreStartComponent { private void startUniversalConfig() { ConfigProviderFactory.getInstance().registerProvider(ConfigRealm.SHARE, new ShareConfigProviderImpl()); ConfigProviderFactory.getInstance().registerProvider(ConfigRealm.PUBLIC, new PublicConfigProviderImpl()); - ConfigRepositoryFactory.getInstance().registerConfigRepositoryBuilder(new MemConfigRepositoryBuilder()); + ConfigRepositoryFactory.getInstance().registerConfigRepositoryBuilder(new LocalConfigRepositoryBuilder(ConfigHelper.getBaseProperties(), ConfigHelper.BASE_PATH)); + } diff --git a/designer-realize/src/main/java/com/fr/start/CarinaDesigner.java b/designer-realize/src/main/java/com/fr/start/CarinaDesigner.java index 138c23993b..d681d79261 100644 --- a/designer-realize/src/main/java/com/fr/start/CarinaDesigner.java +++ b/designer-realize/src/main/java/com/fr/start/CarinaDesigner.java @@ -12,6 +12,7 @@ import com.fr.log.FineLoggerFactory; import com.fr.start.common.DesignerStartupContext; import com.fr.start.module.StartupArgs; +import com.fr.start.server.ServletContextWrapper; import java.util.Properties; import java.util.concurrent.TimeUnit; @@ -36,7 +37,7 @@ public class CarinaDesigner extends MainDesigner{ DesignerStartupContext.getRecorder().start(); PartitionManager manager = new PartitionManagerImpl(); StateHubContext.setReady(false); - CarinaApplicationContext carinaApplicationContext = new DesignContext(new EmptyServletContext(), manager, new Properties()); + CarinaApplicationContext carinaApplicationContext = new DesignContext(new ServletContextWrapper(), manager, new Properties()); Carina.setApplicationContext(carinaApplicationContext); Carina.setPartitionManager(manager); DesignLauncher.setContext(carinaApplicationContext); diff --git a/designer-realize/src/main/java/com/fr/start/DesignContext.java b/designer-realize/src/main/java/com/fr/start/DesignContext.java index f08df80179..b4bb41ff58 100644 --- a/designer-realize/src/main/java/com/fr/start/DesignContext.java +++ b/designer-realize/src/main/java/com/fr/start/DesignContext.java @@ -3,6 +3,7 @@ package com.fr.start; import com.fanruan.carina.context.CarinaApplicationContext; import com.fanruan.carina.standard.PartitionManager; import com.fanruan.carina.standard.PartitionManagerImpl; +import com.fr.start.server.EmptyServletContext; import javax.servlet.ServletContext; @@ -18,9 +19,6 @@ import java.util.Properties; public class DesignContext extends CarinaApplicationContext { private String designWebInfPath; - public DesignContext() { - super(new EmptyServletContext(), new PartitionManagerImpl(), new Properties()); - } public DesignContext(ServletContext servletContext, PartitionManager manager, Properties carinaApplicationProperties) { super(servletContext, manager, carinaApplicationProperties); diff --git a/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java b/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java index 0e97fb6f52..e8a7def014 100644 --- a/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java +++ b/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java @@ -1,12 +1,13 @@ package com.fr.start.module; -import com.fanruan.cloud.FanruanCloud; +import com.fanruan.carina.Carina; +import com.fanruan.config.bbs.FineBBSConfigProvider; import com.fr.base.BaseFormula; import com.fr.base.Formula; import com.fr.base.MultiFieldParameter; import com.fr.base.OptimizeUtil; -import com.fr.base.passport.FinePassportListenerAdapter; -import com.fr.base.passport.FinePassportManager; +import com.fr.base.password.FinePassportListenerAdapter; +import com.fr.base.password.FinePassportManager; import com.fr.base.process.ProcessOperator; import com.fr.base.theme.migrator.FormThemeConfigMigrator; import com.fr.base.theme.migrator.ReportThemeConfigMigrator; @@ -513,15 +514,15 @@ public class DesignerActivator extends Activator implements Prepare { if (newUid > 0) { return; } - int oldUid = FanruanCloud.marketService().getBbsUid(); + int oldUid = Carina.config(FineBBSConfigProvider.class).getBbsUid(); if (oldUid > 0) { manager.setDesignerLoginUid(oldUid); - manager.setDesignerLoginUsername(FanruanCloud.marketService().getBbsUsername()); - manager.setDesignerLoginAppId(FanruanCloud.marketService().getBbsAppId()); - manager.setDesignerLoginRefreshToken(FanruanCloud.marketService().getBbsRefreshToken()); + manager.setDesignerLoginUsername(Carina.config(FineBBSConfigProvider.class).getBbsUsername()); + manager.setDesignerLoginAppId(Carina.config(FineBBSConfigProvider.class).getBbsAppId()); + manager.setDesignerLoginRefreshToken(Carina.config(FineBBSConfigProvider.class).getBbsRefreshToken()); manager.setDesignerLastLoginTime(System.currentTimeMillis()); manager.setLastLoginType(DesignerLoginType.NORMAL_LOGIN); - manager.setLastLoginAccount(FanruanCloud.marketService().getBbsUsername()); + manager.setLastLoginAccount(Carina.config(FineBBSConfigProvider.class).getBbsUsername()); manager.setCurrentVersionFirstLaunch(false); DesignerEnvManager.getEnvManager().saveXMLFile(); } diff --git a/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java b/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java index 40036212e9..8c51795438 100644 --- a/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java +++ b/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java @@ -139,7 +139,13 @@ public class DesignerStartup extends Activator { private void startEmbeddedServer() { ExecutorService service = newSingleThreadExecutor(new NamedThreadFactory("FineEmbedServerStart")); - service.submit(FineEmbedServer::start); + service.submit(() -> { + try { + FineEmbedServer.start(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); service.shutdown(); } diff --git a/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceActivator.java b/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceActivator.java index 13d97017b2..eaa2aac326 100644 --- a/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceActivator.java +++ b/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceActivator.java @@ -149,7 +149,11 @@ public class DesignerWorkspaceActivator extends Activator implements Prepare { @Override public void run() { - FineEmbedServer.start(); + try { + FineEmbedServer.start(); + } catch (Exception e) { + throw new RuntimeException(e); + } } }); service.shutdown();