You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
11 KiB
231 lines
11 KiB
package com.fr.design.mainframe.app; |
|
|
|
import com.fr.design.DesignerEnvManager; |
|
import com.fr.design.dialog.DialogActionAdapter; |
|
import com.fr.design.dialog.UIExpandDialog; |
|
import com.fr.design.extra.exe.callback.InstallOnlineCallback; |
|
import com.fr.design.extra.exe.callback.ModifyStatusCallback; |
|
import com.fr.design.i18n.Toolkit; |
|
import com.fr.design.mainframe.DesignerContext; |
|
import com.fr.design.mainframe.app.PluginRemote.PluginStatus; |
|
import com.fr.locale.InterProviderFactory; |
|
import com.fr.plugin.context.PluginMarker; |
|
import com.fr.plugin.context.PluginMarkerAdapter; |
|
import com.fr.plugin.manage.PluginManager; |
|
import com.fr.plugin.manage.control.PluginControllerHelper; |
|
import com.fr.plugin.manage.control.PluginExtraInfo; |
|
import com.fr.plugin.manage.control.PluginTask; |
|
import com.fr.plugin.observer.PluginEvent; |
|
import com.fr.plugin.observer.PluginEventListener; |
|
import com.fr.plugin.observer.PluginEventType; |
|
import com.fr.plugin.observer.PluginListenerRegistration; |
|
import com.fr.stable.StringUtils; |
|
import com.fr.stable.TemplateIOErrorContextHolder; |
|
import com.fr.third.guava.cache.Cache; |
|
import com.fr.third.guava.cache.CacheBuilder; |
|
import com.fr.third.guava.collect.Multimap; |
|
import com.fr.workspace.WorkContext; |
|
|
|
import javax.swing.SwingUtilities; |
|
import java.time.Duration; |
|
import java.util.Collection; |
|
import java.util.Map; |
|
import java.util.stream.Collectors; |
|
|
|
/** |
|
* 设计器app共用工具类 |
|
* |
|
* @author vito |
|
* @version 10.0 |
|
* Created by vito on 2021/5/27 |
|
*/ |
|
public class DesignerAppUtils { |
|
private static final int DEFAULT_MAX_CACHE_SIZE = 50; |
|
private static final int DEFAULT_CONCURRENCY_LEVEL = 8; |
|
private static final long DEFAULT_EXPIRE_HOURS = 1; |
|
private volatile static boolean enablePluginTipDialog = true; |
|
|
|
private static final Cache<String, Multimap<String, PluginMarkerAdapter>> ERROR_CACHE = CacheBuilder.newBuilder() |
|
.maximumSize(DEFAULT_MAX_CACHE_SIZE) |
|
.expireAfterAccess(Duration.ofHours(DEFAULT_EXPIRE_HOURS)) |
|
.concurrencyLevel(DEFAULT_CONCURRENCY_LEVEL) |
|
.build(); |
|
|
|
public static void initPluginAllActiveListener() { |
|
PluginListenerRegistration.getInstance().listen(PluginEventType.BeforeAllStop, new PluginEventListener() { |
|
@Override |
|
public void on(PluginEvent event) { |
|
enablePluginTipDialog = false; |
|
} |
|
}); |
|
PluginListenerRegistration.getInstance().listen(PluginEventType.AfterAllActive, new PluginEventListener() { |
|
@Override |
|
public void on(PluginEvent event) { |
|
enablePluginTipDialog = true; |
|
} |
|
}); |
|
} |
|
|
|
/** |
|
* 弹出指定的插件信息, |
|
* 并失效缓存 |
|
* |
|
* @param key 指定key |
|
* @return 插件安装信息 |
|
*/ |
|
public static Multimap<String, PluginMarkerAdapter> popPluginInfoMap(String key) { |
|
Multimap<String, PluginMarkerAdapter> ifPresent = ERROR_CACHE.getIfPresent(key); |
|
ERROR_CACHE.invalidate(key); |
|
return ifPresent; |
|
} |
|
|
|
/** |
|
* 失效指定的插件信息缓存 |
|
* |
|
* @param key 指定key |
|
*/ |
|
public static void invalidatePlugins(String key) { |
|
ERROR_CACHE.invalidate(key); |
|
} |
|
|
|
|
|
/** |
|
* 格式化多行插件错误信息详情并缓存, |
|
* 用于界面展示 |
|
* |
|
* @param key 缓存key |
|
* @return 格式化后的多行插件错误信息详情 |
|
*/ |
|
public static String dealWithErrorDetailMultiLineAndCache(String key) { |
|
if (!DesignerEnvManager.getEnvManager().isShowTemplateMissingPlugin() || !enablePluginTipDialog) { |
|
// 直接清空不提示 |
|
TemplateIOErrorContextHolder.reset(); |
|
return StringUtils.EMPTY; |
|
} |
|
Multimap<String, PluginMarkerAdapter> pendingPlugins = TemplateIOErrorContextHolder.getPendingPlugin(); |
|
if (pendingPlugins.isEmpty()) { |
|
return StringUtils.EMPTY; |
|
} |
|
dealWithRemote(pendingPlugins); |
|
StringBuilder sb = new StringBuilder(); |
|
if (WorkContext.getCurrent().isLocal()) { |
|
// 缓存等待后续处理 |
|
ERROR_CACHE.put(key, pendingPlugins); |
|
} |
|
Collection<PluginMarkerAdapter> unknownPlugins = pendingPlugins.get(TemplateIOErrorContextHolder.UNKNOWN_PLUGIN); |
|
if (!unknownPlugins.isEmpty()) { |
|
sb.append(InterProviderFactory.getProvider().getLocText("Fine-Core_Plugin_Error_UnknownPlugin")).append(":\n"); |
|
for (PluginMarkerAdapter pluginMarker : unknownPlugins) { |
|
sb.append("\"").append(pluginMarker.getPluginID()).append("\"") |
|
.append(InterProviderFactory.getProvider().getLocText("Fine-Dec_Platform_Plugin")).append('\n'); |
|
} |
|
} |
|
Collection<PluginMarkerAdapter> notInstalledPlugins = pendingPlugins.get(TemplateIOErrorContextHolder.NOT_INSTALLED_PLUGIN); |
|
if (!notInstalledPlugins.isEmpty()) { |
|
sb.append(InterProviderFactory.getProvider().getLocText("Fine-Core_Plugin_Error_UninstalledPlugins")).append(":\n"); |
|
for (PluginMarkerAdapter pluginMarker : notInstalledPlugins) { |
|
sb.append("\"").append(pluginMarker.getPluginName()).append("\"") |
|
.append(InterProviderFactory.getProvider().getLocText("Fine-Dec_Platform_Plugin")).append('\n'); |
|
} |
|
} |
|
Collection<PluginMarkerAdapter> disablePlugins = pendingPlugins.get(TemplateIOErrorContextHolder.DISABLE_PLUGIN); |
|
if (!disablePlugins.isEmpty()) { |
|
sb.append(InterProviderFactory.getProvider().getLocText("Fine-Core_Plugin_Error_InactivePlugins")).append(":\n"); |
|
for (PluginMarkerAdapter pluginMarker : disablePlugins) { |
|
sb.append("\"").append(pluginMarker.getPluginName()).append("\"") |
|
.append(InterProviderFactory.getProvider().getLocText("Fine-Dec_Platform_Plugin")).append('\n'); |
|
|
|
} |
|
} |
|
return sb.toString(); |
|
} |
|
|
|
/** |
|
* 远程环境下需要特殊处理远程服务器尚未安装的插件 |
|
* |
|
* @param pendingPlugins 待处理插件 |
|
*/ |
|
private static void dealWithRemote(Multimap<String, PluginMarkerAdapter> pendingPlugins) { |
|
if (!WorkContext.getCurrent().isLocal()) { |
|
rearrange(pendingPlugins); |
|
} |
|
} |
|
|
|
/** |
|
* 远程设计重新整理下列表 |
|
* |
|
* @param pendingPlugins 待处理列表 |
|
*/ |
|
public static void rearrange(Multimap<String, PluginMarkerAdapter> pendingPlugins) { |
|
Map<String, PluginStatus> pluginRemoteStatus = PluginRemote.getInstance().getPluginRemoteStatus(); |
|
Collection<PluginMarkerAdapter> unknownPlugins = pendingPlugins.get(TemplateIOErrorContextHolder.UNKNOWN_PLUGIN); |
|
Collection<PluginMarkerAdapter> notInstall = pendingPlugins.get(TemplateIOErrorContextHolder.NOT_INSTALLED_PLUGIN); |
|
Collection<PluginMarkerAdapter> disable = pendingPlugins.get(TemplateIOErrorContextHolder.DISABLE_PLUGIN); |
|
unknownPlugins.removeIf(adapter -> pluginRemoteStatus.containsKey(adapter.getPluginID())); |
|
// 本地未启用名单不准确添加到一起之后重新分配 |
|
notInstall.addAll(disable); |
|
disable.clear(); |
|
// 从所有未安装中过滤远程未启用的,添加到未启用列表 |
|
disable.addAll(notInstall.stream().filter(plugin -> |
|
pluginRemoteStatus.containsKey(plugin.getPluginID()) |
|
&& !pluginRemoteStatus.get(plugin.getPluginID()).isRunning()) |
|
.collect(Collectors.toList())); |
|
// 清理未安装中所有远程安装过的插件(包含启用和未启用) |
|
notInstall.removeIf(adapter -> pluginRemoteStatus.containsKey(adapter.getPluginID())); |
|
} |
|
|
|
/** |
|
* 处理模板读取时的异常 |
|
* |
|
* @param path 模板路径 |
|
*/ |
|
public static void dealWithTemplateIOError(String path) { |
|
// 试图获取多行读取错误提示并缓存待处理列表 |
|
String detail = dealWithErrorDetailMultiLineAndCache(path); |
|
if (detail.length() > 0) { |
|
SwingUtilities.invokeLater(() -> { |
|
if (WorkContext.getCurrent().isLocal()) { |
|
UIExpandDialog.Builder() |
|
.owner(DesignerContext.getDesignerFrame()) |
|
.title(Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")) |
|
.message(Toolkit.i18nText("Fine-Design_Template_Plugin_Error_Message_Local")) |
|
.detail(detail) |
|
.okText(Toolkit.i18nText("Fine-Design_Template_Plugin_Error_OK_Btn")) |
|
.cancelText(Toolkit.i18nText("Fine-Design_Template_Plugin_Error_Cancel_Btn")) |
|
.dialogActionListener(new DialogActionAdapter() { |
|
public void doOk() { |
|
installAndEnablePlugin(path); |
|
} |
|
|
|
@Override |
|
public void doCancel() { |
|
invalidatePlugins(path); |
|
} |
|
}).build().setVisible(true); |
|
} else { |
|
UIExpandDialog.Builder().owner(DesignerContext.getDesignerFrame()) |
|
.title(Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")) |
|
.cancelText(StringUtils.EMPTY) |
|
.message(Toolkit.i18nText("Fine-Design_Template_Plugin_Error_Message_Remote")) |
|
.detail(detail) |
|
.build() |
|
.setVisible(true); |
|
} |
|
}); |
|
} |
|
} |
|
|
|
private static void installAndEnablePlugin(String key) { |
|
Multimap<String, PluginMarkerAdapter> stringPluginMarkerAdapterMultimap = popPluginInfoMap(key); |
|
Collection<PluginMarkerAdapter> disablePlugins = stringPluginMarkerAdapterMultimap.get(TemplateIOErrorContextHolder.DISABLE_PLUGIN); |
|
for (PluginMarkerAdapter disablePlugin : disablePlugins) { |
|
PluginManager.getController().enable(disablePlugin, new ModifyStatusCallback(false)); |
|
} |
|
|
|
Collection<PluginMarkerAdapter> uninstallPlugins = stringPluginMarkerAdapterMultimap.get(TemplateIOErrorContextHolder.NOT_INSTALLED_PLUGIN); |
|
for (PluginMarker uninstallPlugin : uninstallPlugins) { |
|
PluginTask pluginTask = PluginTask.installTask(uninstallPlugin); |
|
PluginControllerHelper.installOnline(uninstallPlugin, new InstallOnlineCallback(pluginTask), PluginExtraInfo.newBuilder().username(DesignerEnvManager.getEnvManager().getDesignerLoginUsername()).build()); |
|
} |
|
} |
|
}
|
|
|