Destiny.Lin
6 months ago
67 changed files with 3197 additions and 132 deletions
@ -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)); |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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<String, String> JS_PROPERTIES = new ConcurrentHashMap<>(); |
||||
|
||||
protected Map<String, String> normalProperties() { |
||||
Map<String, String> 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(); |
||||
} |
||||
} |
@ -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; |
||||
} |
@ -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<String> registerJob(AcquirerTask task) { |
||||
return executorService.submit(task); |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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引擎信息. |
||||
* |
||||
* <p> |
||||
* key: 模块<br> |
||||
* value: 引擎名称 |
||||
* </p> |
||||
*/ |
||||
private static final Map<String, String> 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<String, String> getInfoMap() { |
||||
return Collections.unmodifiableMap(INFO_MAP); |
||||
} |
||||
} |
@ -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<String, String> globalVariables = normalProperties(); |
||||
for (Map.Entry<String, String> 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<array.length(); i++) { |
||||
jo = array.getJSONObject(i); |
||||
finallyObject.registerAdd(jo.getString(TYPE_SOURCE),jo.getString(TYPE_TARGET)); |
||||
} |
||||
} |
||||
|
||||
array = jsonObject.getJSONArray(OPERATE_MODIFY); |
||||
if (array != null) { |
||||
for (int i=0; i<array.length(); i++) { |
||||
jo = array.getJSONObject(i); |
||||
finallyObject.registerModify(jo.getString(TYPE_SOURCE),jo.getString(TYPE_TARGET)); |
||||
} |
||||
} |
||||
|
||||
array = jsonObject.getJSONArray(OPERATE_DELETE); |
||||
if (array != null) { |
||||
for (int i=0; i<array.length(); i++) { |
||||
finallyObject.registerDelete(array.getString(i)); |
||||
} |
||||
} |
||||
return finallyObject; |
||||
} catch (ScriptException e) { |
||||
throw new IllegalStateException(e); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public String getName() { |
||||
return ENGINE_NAME; |
||||
} |
||||
} |
@ -0,0 +1,107 @@
|
||||
package com.fr.decision.update.agent; |
||||
|
||||
import com.eclipsesource.v8.V8; |
||||
import com.eclipsesource.v8.V8Array; |
||||
import com.eclipsesource.v8.V8Object; |
||||
import com.fr.decision.update.acquirer.AbstractAcquirer; |
||||
import com.fr.decision.update.data.FinallyObject; |
||||
import com.fr.decision.update.script.Files; |
||||
import com.fr.general.GeneralUtils; |
||||
import com.fr.script.Console; |
||||
import com.fr.script.InvokeUtils; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* v8 实现 |
||||
* |
||||
* @author richie |
||||
* @version 10.0 |
||||
* Created by richie on 2019-04-24 |
||||
*/ |
||||
public class V8ConfigAcquirer extends AbstractAcquirer { |
||||
|
||||
/** |
||||
* 引擎名称. |
||||
*/ |
||||
public static final String ENGINE_NAME = "j2v8"; |
||||
|
||||
private V8 v8 = V8.createV8Runtime(); |
||||
|
||||
public void prepare() { |
||||
v8.registerJavaMethod((v8Object, v8Array) -> { |
||||
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<String, String> map = normalProperties(); |
||||
for (Map.Entry<String, String> 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; |
||||
} |
||||
} |
@ -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(); |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
|
||||
|
||||
|
||||
} |
@ -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<Recover> 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; |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
@ -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<Command> 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; |
||||
} |
||||
} |
@ -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<Command> commands; |
||||
|
||||
public CommandGroup(List<Command> 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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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<String> 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); |
||||
} |
||||
} |
@ -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]; |
||||
} |
||||
} |
@ -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(); |
||||
|
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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<Item> waitingForAdd = new HashSet<Item>(); |
||||
|
||||
private Set<String> waitingForDelete = new HashSet<String>(); |
||||
|
||||
private Set<Item> waitingForModify = new HashSet<Item>(); |
||||
|
||||
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); |
||||
} |
||||
} |
||||
|
||||
} |
@ -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<String> LOG_TYPE = Collections.unmodifiableList(Arrays.asList(new String[]{ |
||||
"REPORT", "MOBILE", "CHART", "PFC", "BI" |
||||
})); |
||||
} |
@ -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 "; |
||||
} |
||||
} |
@ -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)); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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()); |
||||
} |
||||
} |
@ -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<String> { |
||||
|
||||
private String info; |
||||
|
||||
public AcquirerTask(String info) { |
||||
this.info = info; |
||||
} |
||||
|
||||
@Override |
||||
public String call() { |
||||
return info; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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."); |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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<Class<?>> classes = new HashSet<Class<?>>(); |
||||
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(); |
||||
} |
||||
|
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
|
||||
|
||||
} |
@ -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 |
||||
* <p>用于FR服务的WebApplication初始化</p> |
||||
* |
||||
* @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); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
@ -1,4 +1,4 @@
|
||||
package com.fr.start; |
||||
package com.fr.start.server; |
||||
|
||||
import com.fr.stable.StringUtils; |
||||
|
@ -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<String> 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<Servlet> getServlets() { |
||||
return context.getServlets(); |
||||
} |
||||
|
||||
@Override |
||||
public Enumeration<String> 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<String> 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<String> 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<? extends Servlet> aClass) { |
||||
return context.addServlet(s, aClass); |
||||
} |
||||
|
||||
@Override |
||||
public <T extends Servlet> T createServlet(Class<T> aClass) throws ServletException { |
||||
return context.createServlet(aClass); |
||||
} |
||||
|
||||
@Override |
||||
public ServletRegistration getServletRegistration(String s) { |
||||
return context.getServletRegistration(s); |
||||
} |
||||
|
||||
@Override |
||||
public Map<String, ? extends ServletRegistration> 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<? extends Filter> aClass) { |
||||
return context.addFilter(s, aClass); |
||||
} |
||||
|
||||
@Override |
||||
public <T extends Filter> T createFilter(Class<T> aClass) throws ServletException { |
||||
return context.createFilter(aClass); |
||||
} |
||||
|
||||
@Override |
||||
public FilterRegistration getFilterRegistration(String s) { |
||||
return context.getFilterRegistration(s); |
||||
} |
||||
|
||||
@Override |
||||
public Map<String, ? extends FilterRegistration> getFilterRegistrations() { |
||||
return context.getFilterRegistrations(); |
||||
} |
||||
|
||||
@Override |
||||
public SessionCookieConfig getSessionCookieConfig() { |
||||
return context.getSessionCookieConfig(); |
||||
} |
||||
|
||||
@Override |
||||
public void setSessionTrackingModes(Set<SessionTrackingMode> set) { |
||||
context.setSessionTrackingModes(set); |
||||
} |
||||
|
||||
@Override |
||||
public Set<SessionTrackingMode> getDefaultSessionTrackingModes() { |
||||
return context.getDefaultSessionTrackingModes(); |
||||
} |
||||
|
||||
@Override |
||||
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() { |
||||
return context.getEffectiveSessionTrackingModes(); |
||||
} |
||||
|
||||
@Override |
||||
public void addListener(String s) { |
||||
context.addListener(s); |
||||
} |
||||
|
||||
@Override |
||||
public <T extends EventListener> void addListener(T t) { |
||||
context.addListener(t); |
||||
} |
||||
|
||||
@Override |
||||
public void addListener(Class<? extends EventListener> aClass) { |
||||
context.addListener(aClass); |
||||
} |
||||
|
||||
@Override |
||||
public <T extends EventListener> T createListener(Class<T> 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; |
||||
} |
||||
} |
@ -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; |
||||
|
||||
/** |
||||
* 配置工具类 |
||||
* <oi> |
||||
* <li>1.获取基础配置</li> |
||||
* <li>2.获取环境配置</li> |
||||
* <li>3.基础的变量定义与对应环境配置路径获取</li> |
||||
* </oi> |
||||
* |
||||
* @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; |
||||
} |
||||
} |
@ -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服务细节的模块 |
||||
* <p>当前需要检查一下国际化,后续应该还有东西</p> |
||||
* |
||||
* @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()); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
Loading…
Reference in new issue