Browse Source

Merge remote-tracking branch 'origin/fbp/release' into fbp/release

fbp/release
Levy.Xie-解安森 3 months ago
parent
commit
7977d20b9b
  1. 14
      designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java
  2. 2
      designer-base/src/main/java/com/fr/design/EnvSwitcherSubmitTask.java
  3. 2
      designer-base/src/main/java/com/fr/design/actions/file/RenameAction.java
  4. 21
      designer-base/src/main/java/com/fr/design/carton/CartonUtils.java
  5. 68
      designer-base/src/main/java/com/fr/design/carton/DispatchInfo.java
  6. 193
      designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java
  7. 8
      designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java
  8. 33
      designer-base/src/main/java/com/fr/design/carton/latency/AbstractUIDispatchHandler.java
  9. 104
      designer-base/src/main/java/com/fr/design/carton/latency/UIDispatchManager.java
  10. 33
      designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java
  11. 15
      designer-base/src/main/java/com/fr/design/data/datapane/GlobalTableDataComboBox.java
  12. 2
      designer-base/src/main/java/com/fr/design/data/datapane/GlobalTreeTableDataDictPane.java
  13. 301
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataComboBox.java
  14. 3
      designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataDictPane.java
  15. 19
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java
  16. 36
      designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java
  17. 264
      designer-base/src/main/java/com/fr/design/data/datapane/connect/JNDIDefPane.java
  18. 2
      designer-base/src/main/java/com/fr/design/data/tabledata/datacenter/DCTableDataPane.java
  19. 16
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java
  20. 2
      designer-base/src/main/java/com/fr/design/debug/remote/HeaderRenderer.java
  21. 14
      designer-base/src/main/java/com/fr/design/debug/remote/RemoteDesignNetWorkAction.java
  22. 2
      designer-base/src/main/java/com/fr/design/debug/remote/RemoteDesignNetWorkHelper.java
  23. 8
      designer-base/src/main/java/com/fr/design/debug/remote/RemoteDesignNetWorkTablePane.java
  24. 2
      designer-base/src/main/java/com/fr/design/debug/remote/RemoteDesignNetWorkTableRowSorter.java
  25. 4
      designer-base/src/main/java/com/fr/design/debug/remote/SizeColorCellRenderer.java
  26. 4
      designer-base/src/main/java/com/fr/design/debug/remote/TimeColorCellRenderer.java
  27. 48
      designer-base/src/main/java/com/fr/design/debug/ui/LatencyInfo.java
  28. 17
      designer-base/src/main/java/com/fr/design/debug/ui/LatencyMonitorEvent.java
  29. 56
      designer-base/src/main/java/com/fr/design/debug/ui/UIInspectorHolder.java
  30. 46
      designer-base/src/main/java/com/fr/design/debug/ui/UILatencyInfoHandler.java
  31. 124
      designer-base/src/main/java/com/fr/design/debug/ui/UILatencyWorker.java
  32. 40
      designer-base/src/main/java/com/fr/design/debug/ui/UIMonitorAction.java
  33. 44
      designer-base/src/main/java/com/fr/design/debug/ui/UIMonitorHelper.java
  34. 274
      designer-base/src/main/java/com/fr/design/debug/ui/UIMonitorPane.java
  35. 3
      designer-base/src/main/java/com/fr/design/editor/editor/ColumnSelectedEditor.java
  36. 3
      designer-base/src/main/java/com/fr/design/env/HttpWorkspaceConnector.java
  37. 10
      designer-base/src/main/java/com/fr/design/jxbrowser/JxEngine.java
  38. 6
      designer-base/src/main/java/com/fr/design/jxbrowser/JxUIPane.java
  39. 33
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java
  40. 20
      designer-base/src/main/java/com/fr/design/mainframe/toolbar/DebugModeMenuDef.java
  41. 2
      designer-base/src/main/java/com/fr/design/mainframe/widget/editors/DataBindingEditor.java
  42. 2
      designer-base/src/main/java/com/fr/design/mainframe/widget/editors/DataTableEditor.java
  43. 3
      designer-base/src/main/java/com/fr/design/present/dict/TableDataDictPane.java
  44. 158
      designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java
  45. 6
      designer-base/src/main/java/com/fr/design/utils/DesignUtils.java
  46. 27
      designer-base/src/main/java/com/fr/env/EnvPrepare.java
  47. 2
      designer-base/src/main/java/com/fr/env/RemoteEnvPane.java
  48. 28
      designer-base/src/main/java/com/fr/env/RemoteWorkspaceURL.java
  49. 3
      designer-base/src/main/java/com/fr/start/ServerStarter.java
  50. 7
      designer-base/src/main/java/com/fr/start/server/DesignEmbedHelper.java
  51. 156
      designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java
  52. 98
      designer-base/src/main/resources/com/fr/design/data/tabledata/datacenter/web/data-choose.main.js
  53. 18
      designer-base/src/test/java/com/fr/env/RemoteWorkspaceURLTest.java
  54. 2
      designer-chart/src/main/java/com/fr/design/chart/AutoChartTypePane.java
  55. 2
      designer-chart/src/main/java/com/fr/design/chartx/component/MapAreaMatchPane.java
  56. 6
      designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartOtherPane.java
  57. 15
      designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartStylePane.java
  58. 2
      designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/DatabaseTableDataPane.java
  59. 14
      designer-realize/src/main/java/com/fanruan/boot/adaptation/DesignServerSupportModule.java
  60. 44
      designer-realize/src/main/java/com/fanruan/boot/adaptation/ReportAdaptationComponent.java
  61. 42
      designer-realize/src/main/java/com/fanruan/boot/env/DesignCorePluginComponent.java
  62. 2
      designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvComponent.java
  63. 109
      designer-realize/src/main/java/com/fanruan/boot/env/DesignPluginComponent.java
  64. 31
      designer-realize/src/main/java/com/fanruan/boot/env/DesignVersionComponent.java
  65. 12
      designer-realize/src/main/java/com/fanruan/boot/env/function/DesignComponent.java
  66. 2
      designer-realize/src/main/java/com/fanruan/boot/env/function/DesignDatasourceComponent.java
  67. 2
      designer-realize/src/main/java/com/fanruan/boot/env/function/DesignUpdateComponent.java
  68. 3
      designer-realize/src/main/java/com/fanruan/boot/init/DesignPreLoadComponent.java
  69. 2
      designer-realize/src/main/java/com/fanruan/boot/init/DesignWorkContextComponent.java
  70. 2
      designer-realize/src/main/java/com/fr/design/dscolumn/SelectedDataColumnPane.java
  71. 12
      designer-realize/src/main/java/com/fr/start/CarinaDesigner.java
  72. 2
      designer-realize/src/main/java/com/fr/start/Designer.java
  73. 2
      designer-realize/src/main/java/com/fr/start/Designer4Debug.java
  74. 21
      designer-realize/src/main/java/com/fr/start/MainDesigner.java
  75. 591
      designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java
  76. 26
      designer-realize/src/main/java/com/fr/start/module/DesignerESDActivator.java
  77. 38
      designer-realize/src/main/java/com/fr/start/module/DesignerInitActivator.java
  78. 24
      designer-realize/src/main/java/com/fr/start/module/DesignerShowActivator.java
  79. 200
      designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java
  80. 123
      designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceActivator.java
  81. 99
      designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java
  82. 21
      designer-realize/src/main/java/com/fr/start/module/EnvBasedModule.java
  83. 59
      designer-realize/src/main/java/com/fr/start/module/PreStartActivator.java
  84. 36
      designer-realize/src/main/java/com/fr/start/module/optimized/BaseDBActivator4Designer.java
  85. 23
      designer-realize/src/main/java/com/fr/start/module/optimized/ConfigurationActivator4Designer.java
  86. 25
      designer-realize/src/main/java/com/fr/start/module/optimized/DesignUpdateActivator.java
  87. 35
      designer-realize/src/main/java/com/fr/start/module/optimized/DesignerPluginActivator.java
  88. 221
      designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.java
  89. 32
      designer-realize/src/main/java/com/fr/start/module/optimized/ReportBaseActivator4Designer.java
  90. 7
      designer-realize/src/main/java/com/fr/strongest/WidgetThemeListenerStarter.java
  91. 1
      designer-realize/src/test/java/com/fr/design/mainframe/app/DesignerAppUtilsTest.java
  92. 50
      designer-realize/src/test/java/com/fr/start/module/DesignerWorkspaceProviderTest.java

14
designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java

@ -6,6 +6,8 @@ import com.fr.design.border.FineBorderFactory;
import com.fr.design.constants.LayoutConstants;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.design.mainframe.theme.edit.ui.LabelUtils;
import com.fr.design.i18n.DesignSizeI18nManager;
import com.fr.stable.os.OperatingSystem;
@ -503,4 +505,16 @@ public class FineUIUtils {
public static JTextArea createAutoWrapTipLabel(String text) {
return LabelUtils.createAutoWrapLabel(text, FineUIUtils.getUIColor("Label.tipColor", "inactiveCaption"));
}
/**
* 基于设计器父面板计算当前面板尺寸
* @param width 宽度比例
* @param height 高度比例
*
* @return 面板尺寸
*/
public static Dimension calPaneDimensionByContext(double width, double height) {
DesignerFrame parent = DesignerContext.getDesignerFrame();
return new Dimension((int) (parent.getWidth() * width),(int) (parent.getHeight() * height));
}
}

2
designer-base/src/main/java/com/fr/design/EnvSwitcherSubmitTask.java

@ -162,7 +162,7 @@ public class EnvSwitcherSubmitTask extends AbstractDesignerMetric {
/**
* 循环处理 JSON, 并降序排序
*
* @param moduleUsed 模块用时 {@link com.fr.module.engine.FineModule}
* @param moduleUsed 模块用时
* @param entries 降序排序的树集合
*/
private void sortBySelfUsed(JSONObject moduleUsed, TreeSet<Entry> entries) {

2
designer-base/src/main/java/com/fr/design/actions/file/RenameAction.java

@ -186,7 +186,7 @@ public class RenameAction extends UpdateAction {
warnLabel.setPreferredSize(FineUIScale.scale(new Dimension(300, 50)));
warnLabel.setHorizontalAlignment(SwingConstants.LEFT);
warnLabel.setVerticalAlignment(SwingConstants.TOP);
warnLabel.setForeground(Color.RED);
FineUIStyle.setStyle(warnLabel, FineUIStyle.LABEL_WARNING_TIP);
warnLabel.setVisible(false);
JPanel midPanel = new JPanel(new BorderLayout());

21
designer-base/src/main/java/com/fr/design/carton/CartonUtils.java

@ -1,5 +1,6 @@
package com.fr.design.carton;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StableUtils;
@ -15,9 +16,11 @@ import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.text.SimpleDateFormat;
import static com.fr.design.carton.CartonConstants.DATE_FORMAT;
import static com.fr.design.carton.CartonConstants.EASY_CHECKER_FILE_NAME;
import static com.fr.design.carton.CartonConstants.JOURNAL_FILE_PATH;
import static com.fr.design.carton.CartonConstants.TIMER_CHECKER_FILE_NAME;
import static com.fr.design.carton.CartonConstants.UNREASONABLE_DISPATCH_DURATION_MS;
/**
* 设计器卡顿业务工具类
@ -125,6 +128,24 @@ public class CartonUtils {
}
}
/**
* 记录event事件信息
* @param info event事件信息
*/
public static void recordDispatchInfo(DispatchInfo info) {
long cost = info.timeSoFar();
JSONObject jsonObject = new JSONObject();
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), DATE_FORMAT.format(System.currentTimeMillis()));
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "eventQueue_" + info.getEventSeq());
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Start_Time"), DATE_FORMAT.format(info.getStartDispatchTimeMillis()));
if (cost > UNREASONABLE_DISPATCH_DURATION_MS) {
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), cost + "ms");
} else {
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), info.totalTime() + "ms");
}
outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG);
}
/**
* 用于判断是不是特定的堆栈
*/

68
designer-base/src/main/java/com/fr/design/carton/DispatchInfo.java

@ -0,0 +1,68 @@
package com.fr.design.carton;
/**
* SwingEvent事件包装类
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/05
*/
public class DispatchInfo {
/**
* 当前线程
*/
private final Thread eventDispatchThread = Thread.currentThread();
/**
* 上次触发时间
*/
private long lastDispatchTimeMillis = System.currentTimeMillis();
/**
* 开始时间
*/
private final long startDispatchTimeMillis = System.currentTimeMillis();
/**
* 事件唯一编号
*/
private final long eventSeq;
public DispatchInfo() {
eventSeq = EventDispatchThreadHangMonitor.incrementAndGetSeq();
}
public Thread getEventDispatchThread() {
return eventDispatchThread;
}
public long getLastDispatchTimeMillis() {
return lastDispatchTimeMillis;
}
public long getStartDispatchTimeMillis() {
return startDispatchTimeMillis;
}
public void setLastDispatchTimeMillis(long lastDispatchTimeMillis) {
this.lastDispatchTimeMillis = lastDispatchTimeMillis;
}
public long getEventSeq() {
return eventSeq;
}
/**
* event事件已运行时间
*/
public long timeSoFar() {
return (System.currentTimeMillis() - lastDispatchTimeMillis);
}
/**
* event事件总运行时间
*/
public long totalTime() {
return (System.currentTimeMillis() - startDispatchTimeMillis);
}
}

193
designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java

@ -1,16 +1,8 @@
package com.fr.design.carton;
import com.fanruan.product.ProductConstantsBase;
import com.fr.concurrent.FineExecutors;
import com.fr.design.carton.latency.DesignerLatencyMetric;
import com.fr.design.ui.util.UIUtil;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.SwingUtilities;
import java.awt.EventQueue;
@ -18,15 +10,10 @@ import java.awt.Toolkit;
import java.awt.AWTEvent;
import java.awt.event.WindowEvent;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static com.fr.design.carton.CartonConstants.CHECK_INTERVAL_MS;
import static com.fr.design.carton.CartonConstants.DATE_FORMAT;
import static com.fr.design.carton.CartonConstants.LATENCY_SAMPLING_FREQUENCY;
import static com.fr.design.carton.CartonConstants.UNREASONABLE_DISPATCH_DURATION_MS;
/**
* 参考自git swinghelper
@ -39,14 +26,11 @@ import static com.fr.design.carton.CartonConstants.UNREASONABLE_DISPATCH_DURATIO
public final class EventDispatchThreadHangMonitor extends EventQueue {
public static final EventDispatchThreadHangMonitor INSTANCE = new EventDispatchThreadHangMonitor();
/**
* 一个timer
*/
private Timer timer;
/**
* 事件唯一编码用于方便日志的查看
*/
private static long hangCount = 0;
private static long eventSequence = 0;
/**
* 类似于一个开关当该值为默认的false启动时定时任务在窗口开启前都不会对执行的事件进行检查
*/
@ -54,7 +38,7 @@ public final class EventDispatchThreadHangMonitor extends EventQueue {
/**
* 该链表为主要的实现定时任务的容器在重写的dispatchEvent中由pre方法将DispatchInfo加入到链表由post方法remove
*/
private final LinkedList<DispatchInfo> dispatches = new LinkedList<DispatchInfo>();
private final LinkedList<DispatchInfo> dispatches = new LinkedList<>();
/**
* 一个变量用于控制easy监测模式的开关
*/
@ -72,7 +56,6 @@ public final class EventDispatchThreadHangMonitor extends EventQueue {
/**
* 一个变量用于记录Timer的开关
*/
public boolean isTimerWitch() {
return timerWitch;
}
@ -83,96 +66,20 @@ public final class EventDispatchThreadHangMonitor extends EventQueue {
private boolean timerWitch = false;
private synchronized static long getHangCount() {
return hangCount++;
}
/**
* event事件的包装类
* 获取Swing事件唯一编号
*
* @return 事件编号
*/
public static class DispatchInfo {
// 上一次被打印的堆栈ou
private StackTraceElement[] lastReportedStack;
//获取执行该事件的线程
private final Thread eventDispatchThread = Thread.currentThread();
//在队列中等待执行的事件最后未执行的时间,当有一个事件执行完后就遍历dispatches给该值赋当前时间
private long lastDispatchTimeMillis = System.currentTimeMillis();
//事件开始的时间
private final long startDispatchTimeMillis = System.currentTimeMillis();
//事件编号
private final long hangNumber;
//构造函数,给当前对象赋一个递增的唯一编号
public DispatchInfo() {
hangNumber = getHangCount();
}
//定时调度任务检测的入口,如果执行时间大于设定的值就进入examineHang()方法
public void checkForHang() {
if (timeSoFar() > UNREASONABLE_DISPATCH_DURATION_MS) {
examineHang();
}
}
//超时堆栈的具体处理
private void examineHang() {
//获取执行线程的当前堆栈
StackTraceElement[] currentStack = eventDispatchThread.getStackTrace();
if (CartonUtils.isWaitingForNextEvent(currentStack)) {
return;
}
//某个事件执行时间很长,定时处理时可能会连续打很多个堆栈,对同一个事件的相同堆栈只打一次
if (lastReportedStack != null && CartonUtils.stacksEqual(lastReportedStack, currentStack)) {
return;
}
String stackTrace = CartonUtils.stackTraceToString(currentStack);
lastReportedStack = currentStack;
JSONObject jsonObject = new JSONObject();
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), DATE_FORMAT.format(System.currentTimeMillis()));
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "eventQueue_" + hangNumber);
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Duration_Task_Execute"), timeSoFar() + "ms");
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info"), stackTrace);
CartonUtils.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG);
CartonUtils.checkForDeadlock();
}
//记录连续运行了多长时间
public long timeSoFar() {
return (System.currentTimeMillis() - lastDispatchTimeMillis);
}
//记录一个事件从被分发到结束的总运行时间
public long totalTime() {
return (System.currentTimeMillis() - startDispatchTimeMillis);
}
//事件处理完后的时间判断
public void dispose() {
if (timeSoFar() > UNREASONABLE_DISPATCH_DURATION_MS) {
exportCartonLog(true);
} else if (lastReportedStack != null) {
exportCartonLog(false);
}
}
public synchronized static long incrementAndGetSeq() {
return eventSequence++;
}
/**
*
* @param flag 判断一下输出日志时要输出哪个时间
*/
private void exportCartonLog(boolean flag) {
JSONObject jsonObject = new JSONObject();
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), DATE_FORMAT.format(System.currentTimeMillis()));
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "eventQueue_" + hangNumber);
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Start_Time"), DATE_FORMAT.format(startDispatchTimeMillis));
if (flag) {
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), timeSoFar() + "ms");
} else {
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), totalTime() + "ms");
}
CartonUtils.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG);
}
public LinkedList<DispatchInfo> getDispatches() {
return dispatches;
}
private EventDispatchThreadHangMonitor() {
}
/**
@ -183,17 +90,9 @@ public final class EventDispatchThreadHangMonitor extends EventQueue {
*/
public void startFilterModalWindow() {
scheduledExecutorService = FineExecutors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
//不用干事,切个片就可以
}
});
}
}, 0, 500, TimeUnit.MILLISECONDS);
scheduledExecutorService.scheduleAtFixedRate(() -> SwingUtilities.invokeLater(() -> {
// 切片即可
}), 0, 500, TimeUnit.MILLISECONDS);
}
public void stopFilterModalWindow() {
@ -201,54 +100,11 @@ public final class EventDispatchThreadHangMonitor extends EventQueue {
scheduledExecutorService.shutdown();
}
}
/**
* Sets up a timer to check for hangs frequently.
* 初始化一个Timer
*/
public void initTimer() {
final long initialDelayMs = 0;
final boolean daemon = true;
timer = new Timer("EventDispatchThreadHangMonitor", daemon);
timer.schedule(new HangChecker(), initialDelayMs, CHECK_INTERVAL_MS);
}
/**
* /消除Timer
*/
public void stopTimer() {
if (timer != null) {
timer.cancel();
}
}
/**
* /定时执行的任务
*/
public class HangChecker extends TimerTask {
@Override
public void run() {
synchronized (dispatches) {
//如果链表为空或者窗口还没启开,定时检测就不进行
if (dispatches.isEmpty() || !haveShownSomeComponent) {
return;
}
dispatches.getLast().checkForHang();
}
}
}
/**
* 将swing中默认的EventQueue换成自己的
*/
public static void initMonitoring() {
UIUtil.invokeLaterIfNeeded(() -> Toolkit.getDefaultToolkit().getSystemEventQueue().push(INSTANCE));
}
/**
* Overrides EventQueue.dispatchEvent to call our pre and post hooks either
* side of the system's event dispatch code.
* 重写
*/
@Override
protected void dispatchEvent(AWTEvent event) {
if (!useCustomEventQueue()) {
@ -267,16 +123,23 @@ public final class EventDispatchThreadHangMonitor extends EventQueue {
}
}
/**
* EDT监控器是否已就绪
*
* @return EDT监控器初始化完成
*/
public boolean ready() {
return !dispatches.isEmpty() && haveShownSomeComponent;
}
private boolean useCustomEventQueue() {
// 开启性能监控或开启卡顿工具箱,则走自定义的EventQueue
return SwitchForSwingChecker.isLatencyMonitoring() ||
isEasyWitch() || isTimerWitch();
return SwitchForSwingChecker.isLatencyMonitoring() || isEasyWitch() || isTimerWitch();
}
private boolean needSampling() {
// UI性能采样逻辑:开启采样并且符合采样频次
return SwitchForSwingChecker.isLatencyMonitoring()
&& (hangCount % LATENCY_SAMPLING_FREQUENCY == 0);
return SwitchForSwingChecker.isLatencyMonitoring() && (eventSequence % LATENCY_SAMPLING_FREQUENCY == 0);
}
/**
@ -298,13 +161,13 @@ public final class EventDispatchThreadHangMonitor extends EventQueue {
DesignerLatencyMetric.getInstance().record(justFinishedDispatch.timeSoFar());
}
if (isEasyWitch()) {
justFinishedDispatch.dispose();
CartonUtils.recordDispatchInfo(justFinishedDispatch);
}
//嵌套最深的事件执行完毕后刷新链表中其他事件的lastDispatchTimeMillis
Thread currentEventDispatchThread = Thread.currentThread();
for (DispatchInfo dispatchInfo : dispatches) {
if (dispatchInfo.eventDispatchThread == currentEventDispatchThread) {
dispatchInfo.lastDispatchTimeMillis = System.currentTimeMillis();
if (dispatchInfo.getEventDispatchThread() == currentEventDispatchThread) {
dispatchInfo.setLastDispatchTimeMillis(System.currentTimeMillis());
}
}
}

8
designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java

@ -1,7 +1,7 @@
package com.fr.design.carton;
import com.fanruan.product.ProductConstantsBase;
import com.fr.design.carton.latency.UIDispatchManager;
import com.fr.design.i18n.Toolkit;
import com.fr.general.GeneralUtils;
import com.fr.json.JSON;
@ -82,7 +82,7 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter {
public static void startTimerChecker() {
if (!checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.initTimer();
UIDispatchManager.getInstance().startScheduler();
CartonThreadExecutorPool.getTimerThreadExecutorPool().initTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(true);
checkerTimerSwitch = true;
@ -94,7 +94,7 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter {
public static void stopTimerChecker() {
if (checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.stopTimer();
UIDispatchManager.getInstance().stopSchedulerIfNecessary();
CartonThreadExecutorPool.getTimerThreadExecutorPool().stopTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(false);
checkerTimerSwitch = false;
@ -286,7 +286,7 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter {
CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(true);
}
if (checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.initTimer();
UIDispatchManager.getInstance().startScheduler();
CartonThreadExecutorPool.getTimerThreadExecutorPool().initTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(true);
}

33
designer-base/src/main/java/com/fr/design/carton/latency/AbstractUIDispatchHandler.java

@ -0,0 +1,33 @@
package com.fr.design.carton.latency;
import com.fr.design.carton.DispatchInfo;
/**
* 设计器UI事件切面处理器
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/07
*/
public abstract class AbstractUIDispatchHandler {
/**
* 是否需要处理
*/
protected abstract boolean accept(DispatchInfo info);
/**
* 实际处理
*/
protected abstract void doHandle(DispatchInfo info);
/**
* 处理UI切面
*/
public void handle(DispatchInfo info) {
if (accept(info)) {
doHandle(info);
}
}
}

104
designer-base/src/main/java/com/fr/design/carton/latency/UIDispatchManager.java

@ -0,0 +1,104 @@
package com.fr.design.carton.latency;
import com.fr.design.carton.DispatchInfo;
import com.fr.design.carton.EventDispatchThreadHangMonitor;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static com.fr.design.carton.CartonConstants.CHECK_INTERVAL_MS;
/**
* 设计器UI事件切面处理器
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/05
*/
public class UIDispatchManager {
private ScheduledExecutorService scheduler;
private final List<AbstractUIDispatchHandler> handlerList = new ArrayList<>();
private final static class InstanceHolder {
static final UIDispatchManager INSTANCE = new UIDispatchManager();
}
/**
* 单例
*/
public static UIDispatchManager getInstance() {
return UIDispatchManager.InstanceHolder.INSTANCE;
}
/**
* 注册处理器
* @param handler 处理器
*/
public void registerHandler(AbstractUIDispatchHandler handler) {
handlerList.add(handler);
}
/**
* 注销处理器
* @param handler 处理器
*/
public void unregisterHandler(AbstractUIDispatchHandler handler) {
handlerList.remove(handler);
}
/**
* 开启定时UI事件监听任务
*/
public void startScheduler() {
if (scheduler != null && !scheduler.isShutdown()) {
return;
}
scheduler = Executors.newSingleThreadScheduledExecutor(r -> {
Thread thread = new Thread(r, "DesignerLatencyChecker");
thread.setDaemon(true);
return thread;
});
scheduler.scheduleAtFixedRate(new DispatchChecker(), 0, CHECK_INTERVAL_MS, TimeUnit.MILLISECONDS);
}
/**
* 尝试停止定时UI事件监听任务但如果存在处理器则不停止
*/
public void stopSchedulerIfNecessary() {
if (!handlerList.isEmpty()) {
return;
}
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdownNow();
}
}
/**
* UI事件切面检查器
*/
public class DispatchChecker implements Runnable {
@Override
public void run() {
LinkedList<DispatchInfo> dispatches = EventDispatchThreadHangMonitor.INSTANCE.getDispatches();
synchronized (dispatches) {
if (EventDispatchThreadHangMonitor.INSTANCE.ready()) {
handle(dispatches.getLast());
}
}
}
}
/**
* 处理UI事件
* @param dispatchInfo ui事件信息
*/
public void handle(DispatchInfo dispatchInfo) {
handlerList.forEach(handler -> handler.handle(dispatchInfo));
}
}

33
designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java

@ -121,6 +121,9 @@ public abstract class DesignTableDataManager {
//增强for循环用的iterator实现的, 如果中间哪个listener修改或删除了(如ChartEditPane.dsChangeListener),
// 由于dsListeners是arraylist, 此时会ConcurrentModifyException
ChangeEvent e = null;
if (dsListeners.get(i) == null) {
continue;
}
dsListeners.get(i).stateChanged(e);
}
}
@ -197,17 +200,27 @@ public abstract class DesignTableDataManager {
* @param l ChangeListener监听器
*/
public static void addDsChangeListener(ChangeListener l) {
getDsListenersForCurrentTemplate().add(l);
}
/**
* 移除模板数据集改变 监听事件.
*
* @param l ChangeListener监听器
*/
public static void removeDsChangeListener(ChangeListener l) {
getDsListenersForCurrentTemplate().remove(l);
}
/**
* 获取当前模板的监听器列表.
*
* @return 模板对应的监听器列表如果列表不存在则新建.
*/
private static List<ChangeListener> getDsListenersForCurrentTemplate() {
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
String key = StringUtils.EMPTY;
if (JTemplate.isValid(template)) {
key = template.getPath();
}
List<ChangeListener> dsListeners = dsListenersMap.get(key);
if (dsListeners == null) {
dsListeners = new ArrayList<ChangeListener>();
dsListenersMap.put(key, dsListeners);
}
dsListeners.add(l);
String key = JTemplate.isValid(template) ? template.getPath() : StringUtils.EMPTY;
return dsListenersMap.computeIfAbsent(key, k -> new ArrayList<>());
}
/**

15
designer-base/src/main/java/com/fr/design/data/datapane/GlobalTableDataComboBox.java

@ -12,9 +12,24 @@ import com.fr.data.TableDataSource;
*/
public class GlobalTableDataComboBox extends TableDataComboBox {
/**
* 兼容插件调用
* @param source 数据源
* @param treeName 树数据集名称
*/
public GlobalTableDataComboBox(TableDataSource source, String treeName) {
super(source, treeName);
}
/**
* 初始化GlobalTableDataComboBox
* @param treeName 树数据集名称
*/
public GlobalTableDataComboBox(String treeName) {
super(treeName);
}
@Override
protected void setResMap(TableDataSource source){
resMap = DesignTableDataManager.getGlobalDataSet();

2
designer-base/src/main/java/com/fr/design/data/datapane/GlobalTreeTableDataDictPane.java

@ -16,6 +16,6 @@ public class GlobalTreeTableDataDictPane extends TreeTableDataDictPane {
}
protected void setTableDataNameComboBox(String string) {
tableDataNameComboBox = new GlobalTableDataComboBox(DesignTableDataManager.getEditingTableDataSource(),string);
tableDataNameComboBox = new GlobalTableDataComboBox(string);
}
}

301
designer-base/src/main/java/com/fr/design/data/datapane/TableDataComboBox.java

@ -4,12 +4,12 @@ import com.fr.design.constants.UIConstants;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.util.Iterator;
import java.util.Map.Entry;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@ -33,136 +33,217 @@ public class TableDataComboBox extends UIComboBox implements Prepare4DataSourceC
protected java.util.Map<String, TableDataWrapper> resMap;
private java.util.Map<String, TableDataWrapper> dsMap;
private static final long serialVersionUID = 1L;
private boolean refresModel = false;
private String treeName; //树数据集本身的名字
private ChangeListener changeListener;
private boolean refreshModel = false;
private String treeName = StringUtils.EMPTY; //树数据集本身的名字
private ChangeListener changeListener;
public TableDataComboBox(TableDataSource source){
this(source,StringUtils.EMPTY);
/**
* 兼容插件调用
*
* @param source 插件中传入的数据源
*/
public TableDataComboBox(TableDataSource source) {
this();
}
public TableDataComboBox(TableDataSource source, String treeName) {
super();
/**
* 兼容插件调用
*
* @param source 插件中传入的数据源
* @param treeName 树数据集名称
*/
public TableDataComboBox(TableDataSource source, String treeName) {
this(treeName);
}
/**
* 根据树名称创建TableDataComboBox
*
* @param treeName 树数据集名称
*/
public TableDataComboBox(String treeName) {
this();
// 传入树数据集名称
this.treeName = treeName;
this.setRenderer(new UIComboBoxRenderer() {
private static final long serialVersionUID = 1L;
private boolean labelVisible = true;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel renderer = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof TableDataWrapper) {
labelVisible = true;
TableDataWrapper tableDataWrapper = (TableDataWrapper)value;
renderer.setIcon(tableDataWrapper.getIcon());
renderer.setText(tableDataWrapper.getTableDataName());
renderer.setToolTipText(tableDataWrapper.getTableDataName());
} else {
labelVisible = false;
renderer.setIcon(null);
renderer.setText(StringUtils.EMPTY);
}
return renderer;
}
@Override
public Dimension getPreferredSize() {
return labelVisible ? super.getPreferredSize() : new Dimension(super.getPreferredSize().width, 0);
}
});
refresh(source);
registerDSChangeListener();
}
}
/**
* 初始化TableDataComboBox
*/
public TableDataComboBox() {
super();
setListCellRenderer();
addListener();
}
/**
* 设置渲染器
*/
private void setListCellRenderer() {
this.setRenderer(new UIComboBoxRenderer() {
private static final long serialVersionUID = 1L;
private boolean labelVisible = true;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel renderer = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof TableDataWrapper) {
labelVisible = true;
TableDataWrapper tableDataWrapper = (TableDataWrapper) value;
renderer.setIcon(tableDataWrapper.getIcon());
renderer.setText(tableDataWrapper.getTableDataName());
renderer.setToolTipText(tableDataWrapper.getTableDataName());
} else {
labelVisible = false;
renderer.setIcon(null);
renderer.setText(StringUtils.EMPTY);
}
return renderer;
}
@Override
public Dimension getPreferredSize() {
return labelVisible ? super.getPreferredSize() : new Dimension(super.getPreferredSize().width, 0);
}
});
}
/**
* 在comboBox可见时添加下拉事件与数据集响应事件
*/
private void addListener() {
this.addAncestorListener(new AncestorListener() {
@Override
public void ancestorAdded(AncestorEvent event) {
registerDSChangeListener();
refresh(DesignTableDataManager.getEditingTableDataSource());
}
@Override
public void ancestorRemoved(AncestorEvent event) {
DesignTableDataManager.removeDsChangeListener(changeListener);
}
@Override
public void ancestorMoved(AncestorEvent event) {
}
});
}
/**
* refresh ComboBox
* @param source
*
* @param source 数据源
*/
public void refresh(TableDataSource source) {
TableDataWrapper dataWrapper = getSelectedItem();
refresModel = true;
setResMap(source);
public void refresh(TableDataSource source) {
refreshModel = true;
setResMap(source);
setDsMap();
DefaultComboBoxModel model = new DefaultComboBoxModel();
this.setModel(model);
model.addElement(UIConstants.PENDING);
// 遍历添加所有数据项到模型
Iterator<Entry<String, TableDataWrapper>> entryIt = dsMap.entrySet().iterator();
while (entryIt.hasNext()) {
TableDataWrapper tableDataWrapper = entryIt.next().getValue();
if (!ComparatorUtils.equals(tableDataWrapper.getTableDataName(), treeName)) {
model.addElement(tableDataWrapper);
}
}
// 获取当前选中的数据项
TableDataWrapper dataWrapper = getSelectedItem();
// 更新下拉模型
refreshComboBoxModel();
//处理已选中的数据项
updateSelectedItem(dataWrapper);
refreshModel = false;
}
protected void setResMap(TableDataSource source) {
this.resMap = DesignTableDataManager.getAllEditingDataSet(source);
}
private void setDsMap() {
dsMap = DesignTableDataManager.getAllDataSetIncludingProcedure(resMap);
}
private void refreshComboBoxModel() {
//创建ComboBox模型并设置
DefaultComboBoxModel model = new DefaultComboBoxModel();
this.setModel(model);
model.addElement(UIConstants.PENDING);
// 遍历添加所有数据项到模型,树数据集comboBox下拉模型中排除掉本身
dsMap.values().stream()
.filter(tableDataWrapper -> tableDataWrapper != null && !ComparatorUtils.equals(tableDataWrapper.getTableDataName(), treeName))
.forEach(model::addElement);
}
private void updateSelectedItem(TableDataWrapper dataWrapper) {
if (dataWrapper != null) {
if (DesignTableDataManager.isDsNameChanged(dataWrapper.getTableDataName())) {
this.setSelectedTableDataByName(DesignTableDataManager.getChangedDsNameByOldDsName(dataWrapper.getTableDataName()));
this.setSelectedTableData(DesignTableDataManager.getChangedDsNameByOldDsName(dataWrapper.getTableDataName()));
} else {
this.getModel().setSelectedItem(dataWrapper);
}
}
refresModel = false;
}
}
protected void setResMap(TableDataSource source) {
this.resMap = DesignTableDataManager.getAllEditingDataSet(source);
/**
* 向resMap中添加TableData信息
*
* @param name 数据集名字
* @param templateTableDataWrapper 数据集
*/
public void putTableDataIntoMap(String name, TemplateTableDataWrapper templateTableDataWrapper) {
if (dsMap.containsKey(name)) {
return;
}
this.addItem(templateTableDataWrapper);
dsMap.put(name, templateTableDataWrapper);
}
private void setDsMap() {
dsMap = DesignTableDataManager.getAllDataSetIncludingProcedure(resMap);
public void setSelectedTableDataByName(String name) {
setResMap(DesignTableDataManager.getEditingTableDataSource());
setDsMap();
// 数据集名称修改后控件传入的还是旧名称
if (DesignTableDataManager.isDsNameChanged(name)) {
name = DesignTableDataManager.getChangedDsNameByOldDsName(name);
}
setSelectedTableData(name);
}
private void setSelectedTableData(String name) {
TableDataWrapper tableDataWrapper = dsMap.get(name) == null ? dsMap.get(name + "_P_CURSOR") : dsMap.get(name);
this.getModel().setSelectedItem(tableDataWrapper);
}
@Override
public TableDataWrapper getSelectedItem() {
if (dataModel.getSelectedItem() instanceof TableDataWrapper) {
return (TableDataWrapper) dataModel.getSelectedItem();
}
return null;
}
/**
* 向resMap中添加TableData信息
* @param name 数据集名字
* @param templateTableDataWrappe 数据集
* august:addElement方法竟然会fireItemStateChanged蛋疼
* @param e the event of interest
*
*/
public void putTableDataIntoMap(String name, TemplateTableDataWrapper templateTableDataWrappe) {
if (dsMap.containsKey(name)) {
return;
}
this.addItem(templateTableDataWrappe);
dsMap.put(name, templateTableDataWrappe);
}
public void setSelectedTableDataByName(String name) {
TableDataWrapper tableDataWrappe = dsMap.get(name) == null? dsMap.get(name + "_P_CURSOR") : dsMap.get(name);
this.getModel().setSelectedItem(tableDataWrappe);
}
@Override
public TableDataWrapper getSelectedItem() {
if (dataModel.getSelectedItem() instanceof TableDataWrapper) {
return (TableDataWrapper)dataModel.getSelectedItem();
}
return null;
}
//august:addElement方法竟然会fireItemStateChanged,蛋疼
@Override
protected void fireItemStateChanged(ItemEvent e) {
if (!refresModel) {
super.fireItemStateChanged(e);
}
}
/**
*注册listener,相应数据集改变
*/
@Override
public void registerDSChangeListener() {
changeListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
TableDataComboBox.this.refresh(DesignTableDataManager.getEditingTableDataSource());
}
};
DesignTableDataManager.addDsChangeListener(changeListener);
}
public void registerGlobalDSChangeListener() {
DesignTableDataManager.addGlobalDsChangeListener(changeListener);
}
@Override
protected void fireItemStateChanged(ItemEvent e) {
if (!refreshModel) {
super.fireItemStateChanged(e);
}
}
/**
* 注册listener,相应数据集改变
*/
@Override
public void registerDSChangeListener() {
changeListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
TableDataComboBox.this.refresh(DesignTableDataManager.getEditingTableDataSource());
}
};
DesignTableDataManager.addDsChangeListener(changeListener);
}
/**
* 兼容插件调用
*/
public void registerGlobalDSChangeListener() {
DesignTableDataManager.addGlobalDsChangeListener(changeListener);
}
}

3
designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataDictPane.java

@ -180,8 +180,7 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable {
}
protected void setTableDataNameComboBox(String treeName) {
tableDataNameComboBox = new TableDataComboBox(DesignTableDataManager.getEditingTableDataSource(), treeName);
tableDataNameComboBox = new TableDataComboBox(treeName);
}
private void tdChange(boolean isChangeDS) {

19
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java

@ -5,7 +5,6 @@ import com.fine.theme.utils.FineUIScale;
import com.fr.config.remote.RemoteConfigEvent;
import com.fr.data.impl.Connection;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.impl.JNDIDatabaseConnection;
import com.fr.decision.webservice.bean.datasource.ConnectionInfoBean;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.data.MapCompareUtils;
@ -36,8 +35,9 @@ import com.fr.workspace.server.repository.WorkplaceConstants;
import com.fr.workspace.server.repository.connection.ConnectionRepository;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import java.awt.Window;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -172,17 +172,8 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
"JDBC", new LazyIcon("dataLink"),
JDBCDatabaseConnection.class, DatabaseConnectionPane.JDBC.class
);
NameObjectCreator jndi = new NameObjectCreator(
"JNDI", new LazyIcon("dataLink"),
JNDIDatabaseConnection.class, DatabaseConnectionPane.JNDI.class
);
NameableCreator[] creators;
if (WorkplaceConstants.isLimitDatabaseType()) {
// 不支持JNDI,屏蔽接口
creators = new NameableCreator[]{jdbc};
} else {
creators = new NameableCreator[]{jdbc, jndi};
}
creators = new NameableCreator[]{jdbc};
Set<ConnectionProvider> pluginCreators = ExtraDesignClassManager.getInstance().getArray(ConnectionProvider.XML_TAG);
for (ConnectionProvider provider : pluginCreators) {
NameObjectCreator creator = new NameObjectCreator(
@ -292,7 +283,7 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
* @return
*/
private boolean isEmbedConnection(Connection connection) {
return connection instanceof JDBCDatabaseConnection || connection instanceof JNDIDatabaseConnection;
return connection instanceof JDBCDatabaseConnection;
}
});
/// 先不管

36
designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java

@ -11,15 +11,14 @@ import com.formdev.flatlaf.util.ScaledEmptyBorder;
import com.fr.data.driver.util.JarFileParseUtil;
import com.fr.data.impl.Connection;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.impl.JNDIDatabaseConnection;
import com.fr.data.security.ssl.impl.NormalSsl;
import com.fr.data.solution.ExceptionSolutionSelector;
import com.fr.data.solution.entity.DriverPage;
import com.fr.data.solution.processor.ClassNotFoundExceptionSolutionProcessor;
import com.fr.data.solution.processor.SolutionProcessor;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.data.datapane.preview.ConnectionInfoBeanHelper;
import com.fr.design.constants.LayoutConstants;
import com.fr.design.data.datapane.preview.ConnectionInfoBeanHelper;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icontainer.UIScrollPane;
@ -34,8 +33,8 @@ import com.fr.stable.EncodeConstants;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.engine.exception.DriverUnExistException;
import org.jetbrains.annotations.NotNull;
import com.fr.workspace.server.repository.connection.ConnectionRepository;
import org.jetbrains.annotations.NotNull;
import javax.swing.JDialog;
import javax.swing.JLabel;
@ -69,8 +68,8 @@ import java.util.concurrent.ExecutionException;
import static com.fine.swing.ui.layout.Layouts.cell;
import static com.fine.swing.ui.layout.Layouts.fix;
import static com.fine.swing.ui.layout.Layouts.row;
import static com.fine.swing.ui.layout.Layouts.flex;
import static com.fine.swing.ui.layout.Layouts.row;
import static com.fine.theme.utils.FineUIUtils.wrapComponentWithTitle;
/**
@ -411,35 +410,6 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
}
}
public static class JNDI extends DatabaseConnectionPane<JNDIDatabaseConnection> {
private static JNDIDefPane jndiDefPane = new JNDIDefPane();
@Override
protected JPanel mainPanel() {
return jndiDefPane;
}
@Override
protected boolean isFineBI() {
return false;
}
@Override
protected void populateSubDatabaseConnectionBean(JNDIDatabaseConnection ob) {
jndiDefPane.populate(ob);
}
@Override
protected JNDIDatabaseConnection updateSubDatabaseConnectionBean() {
return jndiDefPane.update();
}
@Override
protected String title4PopupWindow() {
return "JNDI";
}
}
private class TestConnectionWorker extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() throws Exception {

264
designer-base/src/main/java/com/fr/design/data/datapane/connect/JNDIDefPane.java

@ -1,264 +0,0 @@
package com.fr.design.data.datapane.connect;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.naming.Context;
import javax.swing.JDialog;
import com.fine.theme.utils.FineUIScale;
import com.formdev.flatlaf.util.ScaledEmptyBorder;
import com.fr.design.constants.LayoutConstants;
import com.fr.design.gui.ilable.UILabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import com.fr.data.impl.JNDIDatabaseConnection;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.FRExplainLabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.dialog.BasicPane;
import com.fr.general.ComparatorUtils;
import com.fr.stable.StringUtils;
import static com.fine.swing.ui.layout.Layouts.cell;
import static com.fine.swing.ui.layout.Layouts.column;
import static com.fine.swing.ui.layout.Layouts.row;
import static com.fine.theme.utils.FineUIUtils.wrapComponentWithTitle;
public class JNDIDefPane extends JPanel {
private static Map<String, String> jndiMap = new HashMap<String, String>();
static {
jndiMap.put("weblogic.jndi.WLInitialContextFactory", "t3://localhost:7001");
jndiMap.put("com.ibm.websphere.naming.WsnInitialContextFactory", "iiop://localhost:2809");
jndiMap.put("org.jboss.naming.HttpNamingContextFactory", "http://jboss_server_address:8080/invoker/JNDIFactory");
jndiMap.put("org.jnp.interfaces.NamingContextFactory", "localhost:1099");
jndiMap.put("com.caucho.burlap.BurlapContextFactory", "http://localhost:8080/hello/burlap");
}
private UITextField jndiNameTextField;
private UIComboBox JNDIFactoryComboBox;
private ContextTextField PROVIDER_URL_TF = new ContextTextField(Context.PROVIDER_URL);
private ContextTextField SECURITY_PRINCIPAL_TF = new ContextTextField(Context.SECURITY_PRINCIPAL);
private ContextTextField SECURITY_CREDENTIALS_TF = new ContextTextField(Context.SECURITY_CREDENTIALS);
private ContextTextField OBJECT_FACTORIES_TF = new ContextTextField(Context.OBJECT_FACTORIES);
private ContextTextField STATE_FACTORIES_TF = new ContextTextField(Context.STATE_FACTORIES);
private ContextTextField URL_PKG_PREFIXES_TF = new ContextTextField(Context.URL_PKG_PREFIXES);
private ContextTextField DNS_URL_TF = new ContextTextField(Context.DNS_URL);
private ContextTextField AUTHORITATIVE_TF = new ContextTextField(Context.AUTHORITATIVE);
private ContextTextField BATCHSIZE_TF = new ContextTextField(Context.BATCHSIZE);
private ContextTextField REFERRAL_TF = new ContextTextField(Context.REFERRAL);
private ContextTextField SECURITY_PROTOCOL_TF = new ContextTextField(Context.SECURITY_PROTOCOL);
private ContextTextField SECURITY_AUTHENTICATION_TF = new ContextTextField(Context.SECURITY_AUTHENTICATION);
private ContextTextField LANGUAGE_TF = new ContextTextField(Context.LANGUAGE);
private ContextTextField APPLET_TF = new ContextTextField(Context.APPLET);
private JDialog otherAttrDialog;
public JNDIDefPane() {
this.setLayout(new BorderLayout());
jndiNameTextField = new UITextField(20);
JNDIFactoryComboBox = new UIComboBox(new String[] { "", "weblogic.jndi.WLInitialContextFactory", "com.ibm.websphere.naming.WsnInitialContextFactory",
"org.jboss.naming.HttpNamingContextFactory", "org.jnp.interfaces.NamingContextFactory", "com.caucho.burlap.BurlapContextFactory", });
JNDIFactoryComboBox.setEditable(true);
JNDIFactoryComboBox.addActionListener(jndiListener);
JNDIFactoryComboBox.setPreferredSize(new Dimension(FineUIScale.scale(30), JNDIFactoryComboBox.getPreferredSize().height + FineUIScale.scale(2)));
// 上下文
JPanel contextPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
contextPane.add(column(LayoutConstants.VERTICAL_GAP,
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("INITIAL_CONTEXT_FACTORY")).weight(0.35), cell(JNDIFactoryComboBox).weight(0.65)),
row(LayoutConstants.HORIZONTAL_GAP,cell(new UILabel("PROVIDER_URL")).weight(0.35), cell(PROVIDER_URL_TF).weight(0.65)),
row(LayoutConstants.HORIZONTAL_GAP,cell(new UILabel("SECURITY_PRINCIPAL")).weight(0.35), cell(SECURITY_PRINCIPAL_TF).weight(0.65)),
row(LayoutConstants.HORIZONTAL_GAP,cell(new UILabel("SECURITY_CREDENTIALS")).weight(0.35), cell(SECURITY_CREDENTIALS_TF).weight(0.65))
).getComponent());
//其他属性
JPanel otherAttributePanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
ActionLabel actionLabel = new ActionLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Datasource_Other_Attributes"));
actionLabel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//其他属性弹窗
JDialog wDialog = createJDialog();
wDialog.setVisible(true);
}
});
otherAttributePanel.add(actionLabel, BorderLayout.EAST);
//注意描述
JPanel jndiDesPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jndiDesPanel.add(new JScrollPane(new FRExplainLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Datasource_JNDI_DES"))), BorderLayout.WEST);
//JNDI面板
JPanel centerPanel = column(LayoutConstants.VERTICAL_GAP,
row(cell(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Datasource_JNDI_Name"))).weight(0.15), cell(jndiNameTextField).weight(0.85)),
row(cell(getTopAlignLabelPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Datasource_Context"))).weight(0.15), cell(contextPane).weight(0.85)),
cell(otherAttributePanel),
cell(jndiDesPanel)
).getComponent();
this.add(wrapComponentWithTitle(centerPanel,"JNDI"));
}
private JPanel getTopAlignLabelPane(String labelText) {
return column(LayoutConstants.VERTICAL_GAP, cell(new UILabel(labelText)))
.with(it -> it.setBorder(new ScaledEmptyBorder(2,0,0,0))).getComponent();
}
public void populate(JNDIDatabaseConnection jndiDatabase) {
if (jndiDatabase == null) {
jndiDatabase = new JNDIDatabaseConnection();
}
// Properties.
Map<String, String> contextHashtable = jndiDatabase.getContextHashtable();
Object INITIAL_CONTEXT_FACTORY = contextHashtable.get(Context.INITIAL_CONTEXT_FACTORY);
this.JNDIFactoryComboBox.setSelectedItem(INITIAL_CONTEXT_FACTORY == null ? "" : INITIAL_CONTEXT_FACTORY);
this.jndiNameTextField.setText(jndiDatabase.getJNDIName() == null ? "" : jndiDatabase.getJNDIName());
populateContextAttributes(contextHashtable, this.PROVIDER_URL_TF, Context.PROVIDER_URL);
populateContextAttributes(contextHashtable, this.SECURITY_PRINCIPAL_TF, Context.SECURITY_PRINCIPAL);
populateContextAttributes(contextHashtable, this.SECURITY_CREDENTIALS_TF, Context.SECURITY_CREDENTIALS);
populateContextAttributes(contextHashtable, this.OBJECT_FACTORIES_TF, Context.OBJECT_FACTORIES);
populateContextAttributes(contextHashtable, this.STATE_FACTORIES_TF, Context.STATE_FACTORIES);
populateContextAttributes(contextHashtable, this.URL_PKG_PREFIXES_TF, Context.URL_PKG_PREFIXES);
populateContextAttributes(contextHashtable, this.DNS_URL_TF, Context.DNS_URL);
populateContextAttributes(contextHashtable, this.AUTHORITATIVE_TF, Context.AUTHORITATIVE);
populateContextAttributes(contextHashtable, this.BATCHSIZE_TF, Context.BATCHSIZE);
populateContextAttributes(contextHashtable, this.REFERRAL_TF, Context.REFERRAL);
populateContextAttributes(contextHashtable, this.SECURITY_PROTOCOL_TF, Context.SECURITY_PROTOCOL);
populateContextAttributes(contextHashtable, this.SECURITY_AUTHENTICATION_TF, Context.SECURITY_AUTHENTICATION);
populateContextAttributes(contextHashtable, this.LANGUAGE_TF, Context.LANGUAGE);
populateContextAttributes(contextHashtable, this.APPLET_TF, Context.APPLET);
}
private void populateContextAttributes(Map<String, String> properties, UITextField textField, String contextAttr) {
String PROVIDER_URL = properties.get(contextAttr);
if (PROVIDER_URL != null) {
textField.setText(PROVIDER_URL);
}
}
public JNDIDatabaseConnection update() {
JNDIDatabaseConnection jndiDatabase = new JNDIDatabaseConnection();
jndiDatabase.setJNDIName(this.jndiNameTextField.getText());
Map<String, String> contextHashtable = jndiDatabase.getContextHashtable();
String factoryString = (String)this.JNDIFactoryComboBox.getEditor().getItem();
if (factoryString != null && factoryString.trim().length() > 0) {
contextHashtable.put(Context.INITIAL_CONTEXT_FACTORY, factoryString);
}
updateContextAttributes(contextHashtable, this.PROVIDER_URL_TF, Context.PROVIDER_URL);
updateContextAttributes(contextHashtable, this.SECURITY_PRINCIPAL_TF, Context.SECURITY_PRINCIPAL);
updateContextAttributes(contextHashtable, this.SECURITY_CREDENTIALS_TF, Context.SECURITY_CREDENTIALS);
updateContextAttributes(contextHashtable, this.OBJECT_FACTORIES_TF, Context.OBJECT_FACTORIES);
updateContextAttributes(contextHashtable, this.STATE_FACTORIES_TF, Context.STATE_FACTORIES);
updateContextAttributes(contextHashtable, this.URL_PKG_PREFIXES_TF, Context.URL_PKG_PREFIXES);
updateContextAttributes(contextHashtable, this.DNS_URL_TF, Context.DNS_URL);
updateContextAttributes(contextHashtable, this.AUTHORITATIVE_TF, Context.AUTHORITATIVE);
updateContextAttributes(contextHashtable, this.BATCHSIZE_TF, Context.BATCHSIZE);
updateContextAttributes(contextHashtable, this.REFERRAL_TF, Context.REFERRAL);
updateContextAttributes(contextHashtable, this.SECURITY_PROTOCOL_TF, Context.SECURITY_PROTOCOL);
updateContextAttributes(contextHashtable, this.SECURITY_AUTHENTICATION_TF, Context.SECURITY_AUTHENTICATION);
updateContextAttributes(contextHashtable, this.LANGUAGE_TF, Context.LANGUAGE);
updateContextAttributes(contextHashtable, this.APPLET_TF, Context.APPLET);
return jndiDatabase;
}
private void updateContextAttributes(Map<String, String> contextHashtable, UITextField textField, String contextAttr) {
String tValue = textField.getText();
if (tValue != null && tValue.trim().length() > 0) {
contextHashtable.put(contextAttr, tValue);
}
}
ActionListener jndiListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object o = JNDIFactoryComboBox.getSelectedItem();
if (o == null || ComparatorUtils.equals(o, StringUtils.EMPTY)) {
PROVIDER_URL_TF.setText("");
return;
}
PROVIDER_URL_TF.setText(jndiMap.get(o));
}
};
private JDialog createJDialog() {
if (this.otherAttrDialog == null) {
this.otherAttrDialog = new OtherAttrPane().showWindow(SwingUtilities.getWindowAncestor(JNDIDefPane.this));
}
return this.otherAttrDialog;
}
class OtherAttrPane extends BasicPane {
public OtherAttrPane() {
// JPanel northFlowPane
JPanel northFlowPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
northFlowPane.setBorder(new ScaledEmptyBorder(10,10,10,10));
// ContextPane
northFlowPane.add(column(LayoutConstants.VERTICAL_GAP,
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("OBJECT_FACTORIES")).weight(0.35), cell(OBJECT_FACTORIES_TF)).weight(0.65),
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("STATE_FACTORIES")).weight(0.35), cell(STATE_FACTORIES_TF)).weight(0.65),
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("URL_PKG_PREFIXES")).weight(0.35), cell(URL_PKG_PREFIXES_TF)).weight(0.65),
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("DNS_URL")).weight(0.35), cell(DNS_URL_TF)).weight(0.65),
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("AUTHORITATIVE")).weight(0.35), cell(AUTHORITATIVE_TF)).weight(0.65),
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("BATCHSIZE")).weight(0.35), cell(BATCHSIZE_TF)).weight(0.65),
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("REFERRAL")).weight(0.35), cell(REFERRAL_TF)).weight(0.65),
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("SECURITY_PROTOCOL")).weight(0.35), cell(SECURITY_PROTOCOL_TF)).weight(0.65),
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("SECURITY_AUTHENTICATION")).weight(0.35), cell(SECURITY_AUTHENTICATION_TF)).weight(0.65),
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("LANGUAGE")).weight(0.35), cell(LANGUAGE_TF)).weight(0.65),
row(LayoutConstants.HORIZONTAL_GAP, cell(new UILabel("APPLET")).weight(0.35), cell(APPLET_TF)).weight(0.65)
).getComponent());
this.add(northFlowPane, BorderLayout.NORTH);
}
@Override
protected String title4PopupWindow() {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Datasource_Other_Attributes");
}
}
// 主力Context属性
class ContextTextField extends UITextField {
private String contextName;
public ContextTextField(String contextName) {
this.setContextName(contextName);
this.setColumns(24);
}
public String getContextName() {
return contextName;
}
public void setContextName(String contextName) {
this.contextName = contextName;
}
/*
* 更新Properties.
*/
public void applyProperties(Properties properties) {
properties.put(contextName, this.getText());
}
}
}

2
designer-base/src/main/java/com/fr/design/data/tabledata/datacenter/DCTableDataPane.java

@ -32,7 +32,7 @@ import static com.fr.design.ui.ModernUIConstants.SCHEME_HEADER;
*/
public class DCTableDataPane extends AbstractTableDataPane<DCTableData> {
private static final JxEngine JX_ENGINE = JxEngine.newInstance(false);
private static final JxEngine JX_ENGINE = JxEngine.newInstance(true);
private static final String DATA_CENTER = "dc";
private static final String LANGUAGE = "language";

16
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java

@ -10,7 +10,6 @@ import com.fr.data.core.db.TableProcedure;
import com.fr.data.impl.Connection;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.impl.JNDIDatabaseConnection;
import com.fr.data.impl.NameDatabaseConnection;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.actions.UpdateAction;
@ -63,11 +62,8 @@ import com.fr.stable.ArrayUtils;
import com.fr.stable.ParameterProvider;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
@ -80,7 +76,6 @@ import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@ -88,11 +83,13 @@ import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import static com.fine.theme.utils.FineClientProperties.COMBO_BOX_TYPE;
import static com.fine.theme.utils.FineClientProperties.ADAPTIVE_COMBO_BOX;
import static com.fine.theme.utils.FineClientProperties.COMBO_BOX_TYPE;
/**
* @author rinoux
@ -194,8 +191,7 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> implemen
@Override
protected void filter(Connection connection, String conName, List<String> nameList) {
connection.addConnection(nameList, conName, new Class[]{
JDBCDatabaseConnection.class,
JNDIDatabaseConnection.class
JDBCDatabaseConnection.class
});
}
@ -562,7 +558,9 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> implemen
}
//保存
this.configHandler.save(this.dbTableData, this.strategyConfig);
if (this.configHandler != null) {
this.configHandler.save(this.dbTableData, this.strategyConfig);
}
}
private void updateDBTableData() {

2
designer-base/src/main/java/com/fr/design/remote/ui/debug/HeaderRenderer.java → designer-base/src/main/java/com/fr/design/debug/remote/HeaderRenderer.java

@ -1,4 +1,4 @@
package com.fr.design.remote.ui.debug;
package com.fr.design.debug.remote;
import com.fine.theme.icon.LazyIcon;
import com.fine.theme.light.ui.FineTableHeaderUI;

14
designer-base/src/main/java/com/fr/design/remote/ui/debug/RemoteDesignNetWorkAction.java → designer-base/src/main/java/com/fr/design/debug/remote/RemoteDesignNetWorkAction.java

@ -1,22 +1,19 @@
package com.fr.design.remote.ui.debug;
package com.fr.design.debug.remote;
import com.fine.theme.utils.FineUIUtils;
import com.fr.design.actions.UpdateAction;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.workspace.WorkContext;
import javax.swing.JDialog;
import javax.swing.KeyStroke;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import static com.fine.theme.utils.FineUIScale.createScaleDimension;
import static com.fine.theme.utils.FineUIScale.unscale;
import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER;
/**
@ -42,7 +39,7 @@ public class RemoteDesignNetWorkAction extends UpdateAction {
return;
}
JDialog jDialog = new JDialog(DesignerContext.getDesignerFrame(), TITLE);
jDialog.setSize(calculatePaneDimension());
jDialog.setSize(FineUIUtils.calPaneDimensionByContext(0.8, 0.6));
RemoteDesignNetWorkTablePane netWorkPane = new RemoteDesignNetWorkTablePane();
jDialog.add(netWorkPane);
jDialog.addWindowListener(new WindowAdapter() {
@ -56,10 +53,5 @@ public class RemoteDesignNetWorkAction extends UpdateAction {
jDialog.setVisible(true);
}
private static Dimension calculatePaneDimension() {
DesignerFrame parent = DesignerContext.getDesignerFrame();
return createScaleDimension((int) (unscale(parent.getWidth()) * 0.8),
(int) (unscale(parent.getHeight()) * 0.6));
}
}

2
designer-base/src/main/java/com/fr/design/remote/ui/debug/RemoteDesignNetWorkHelper.java → designer-base/src/main/java/com/fr/design/debug/remote/RemoteDesignNetWorkHelper.java

@ -1,4 +1,4 @@
package com.fr.design.remote.ui.debug;
package com.fr.design.debug.remote;
import com.fr.stable.StringUtils;

8
designer-base/src/main/java/com/fr/design/remote/ui/debug/RemoteDesignNetWorkTablePane.java → designer-base/src/main/java/com/fr/design/debug/remote/RemoteDesignNetWorkTablePane.java

@ -1,4 +1,4 @@
package com.fr.design.remote.ui.debug;
package com.fr.design.debug.remote;
import com.fanruan.workplace.http.debug.RequestInfo;
import com.fine.theme.icon.LazyIcon;
@ -24,9 +24,9 @@ import java.awt.Component;
import java.util.concurrent.atomic.AtomicLong;
import static com.fanruan.workplace.http.debug.RemoteDesignDebugEvent.REMOTE_HTTP_REQUEST;
import static com.fr.design.remote.ui.debug.RemoteDesignNetWorkHelper.dateFormat;
import static com.fr.design.remote.ui.debug.RemoteDesignNetWorkHelper.simpleSize;
import static com.fr.design.remote.ui.debug.RemoteDesignNetWorkHelper.simpleTime;
import static com.fr.design.debug.remote.RemoteDesignNetWorkHelper.dateFormat;
import static com.fr.design.debug.remote.RemoteDesignNetWorkHelper.simpleSize;
import static com.fr.design.debug.remote.RemoteDesignNetWorkHelper.simpleTime;
/**
* 远程设计网络调试面板

2
designer-base/src/main/java/com/fr/design/remote/ui/debug/RemoteDesignNetWorkTableRowSorter.java → designer-base/src/main/java/com/fr/design/debug/remote/RemoteDesignNetWorkTableRowSorter.java

@ -1,4 +1,4 @@
package com.fr.design.remote.ui.debug;
package com.fr.design.debug.remote;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;

4
designer-base/src/main/java/com/fr/design/remote/ui/debug/SizeColorCellRenderer.java → designer-base/src/main/java/com/fr/design/debug/remote/SizeColorCellRenderer.java

@ -1,10 +1,10 @@
package com.fr.design.remote.ui.debug;
package com.fr.design.debug.remote;
import com.fine.theme.light.ui.FineTableHeaderUI;
import java.awt.Color;
import static com.fr.design.remote.ui.debug.RemoteDesignNetWorkHelper.DEFAULT_COLOR;
import static com.fr.design.debug.remote.RemoteDesignNetWorkHelper.DEFAULT_COLOR;
/**
* 大小多颜色渲染

4
designer-base/src/main/java/com/fr/design/remote/ui/debug/TimeColorCellRenderer.java → designer-base/src/main/java/com/fr/design/debug/remote/TimeColorCellRenderer.java

@ -1,10 +1,10 @@
package com.fr.design.remote.ui.debug;
package com.fr.design.debug.remote;
import com.fine.theme.light.ui.FineTableHeaderUI;
import java.awt.Color;
import static com.fr.design.remote.ui.debug.RemoteDesignNetWorkHelper.DEFAULT_COLOR;
import static com.fr.design.debug.remote.RemoteDesignNetWorkHelper.DEFAULT_COLOR;
/**
* 时间多颜色渲染

48
designer-base/src/main/java/com/fr/design/debug/ui/LatencyInfo.java

@ -0,0 +1,48 @@
package com.fr.design.debug.ui;
/**
* UI卡顿信息Bean
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/07
*/
public class LatencyInfo {
// swing事件编号
private long seq;
// 耗时 ms
private long cost;
// 堆栈信息
private StackTraceElement[] detailStack;
public LatencyInfo(long seq, long cost, StackTraceElement[] detailStack) {
this.seq = seq;
this.cost = cost;
this.detailStack = detailStack;
}
public long getCost() {
return cost;
}
public void setCost(long cost) {
this.cost = cost;
}
public StackTraceElement[] getDetailStack() {
return detailStack;
}
public void setDetailStack(StackTraceElement[] detailStack) {
this.detailStack = detailStack;
}
public long getSeq() {
return seq;
}
public void setSeq(long seq) {
this.seq = seq;
}
}

17
designer-base/src/main/java/com/fr/design/debug/ui/LatencyMonitorEvent.java

@ -0,0 +1,17 @@
package com.fr.design.debug.ui;
import com.fr.event.Event;
/**
* UI性能监控事件
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/08
*/
public enum LatencyMonitorEvent implements Event<LatencyInfo> {
/**
* 超出卡顿阈值
*/
OFF_THRESHOLD_EVENT
}

56
designer-base/src/main/java/com/fr/design/debug/ui/UIInspectorHolder.java

@ -0,0 +1,56 @@
package com.fr.design.debug.ui;
import com.fanruan.gui.UiInspector;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* UIInspectorHolder 单例管理
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/08
*/
public class UIInspectorHolder {
private UiInspector uiInspector;
private final AtomicBoolean installed = new AtomicBoolean(false);
private final static class InstanceHolder {
static final UIInspectorHolder INSTANCE = new UIInspectorHolder();
}
/**
* 单例
*/
public static UIInspectorHolder getInstance() {
return UIInspectorHolder.InstanceHolder.INSTANCE;
}
/**
* 是否已启用UIInspector
* @return 是否启用
*/
public boolean isInstalled() {
return installed.get();
}
/**
* 启用UIInspector
*/
public void install() {
if (installed.compareAndSet(false, true)) {
uiInspector = new UiInspector();
}
}
/**
* 注销UIInspector
*/
public void uninstall() {
if (uiInspector != null) {
uiInspector.dispose();
installed.set(false);
}
}
}

46
designer-base/src/main/java/com/fr/design/debug/ui/UILatencyInfoHandler.java

@ -0,0 +1,46 @@
package com.fr.design.debug.ui;
import com.fr.design.carton.DispatchInfo;
import com.fr.design.carton.latency.AbstractUIDispatchHandler;
/**
* UI卡顿实时监控Handler
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/07
*/
public class UILatencyInfoHandler extends AbstractUIDispatchHandler {
private long threshold = 200;
private final static class InstanceHolder {
static final UILatencyInfoHandler INSTANCE = new UILatencyInfoHandler();
}
/**
* 单例
*/
public static UILatencyInfoHandler getInstance() {
return UILatencyInfoHandler.InstanceHolder.INSTANCE;
}
public long getThreshold() {
return threshold;
}
public void setThreshold(long threshold) {
this.threshold = threshold;
}
@Override
protected boolean accept(DispatchInfo info) {
return info.timeSoFar() > threshold;
}
@Override
protected void doHandle(DispatchInfo info) {
LatencyInfo infoBean = new LatencyInfo(info.getEventSeq(), info.timeSoFar(), info.getEventDispatchThread().getStackTrace());
UILatencyWorker.getInstance().submit(infoBean);
}
}

124
designer-base/src/main/java/com/fr/design/debug/ui/UILatencyWorker.java

@ -0,0 +1,124 @@
package com.fr.design.debug.ui;
import com.fr.design.carton.latency.UIDispatchManager;
import com.fr.event.EventDispatcher;
import com.fr.third.guava.cache.Cache;
import com.fr.third.guava.cache.CacheBuilder;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/**
* UI性能监控Worker
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/07
*/
public class UILatencyWorker {
private ExecutorService executorService;
private final AtomicBoolean initialized = new AtomicBoolean(false);
// 默认允许存储300卡顿信息
private final Cache<Long, LatencyInfo> infoContainer = CacheBuilder.newBuilder()
.maximumSize(300).build();
private final static class InstanceHolder {
static final UILatencyWorker INSTANCE = new UILatencyWorker();
}
/**
* 单例
*/
public static UILatencyWorker getInstance() {
return InstanceHolder.INSTANCE;
}
/**
* 开始监控: 启动异步提交线程启动定时堆栈检测任务
*/
public void start() {
if (initialized.compareAndSet(false, true)) {
executorService = Executors.newSingleThreadExecutor();
UIDispatchManager.getInstance().registerHandler(UILatencyInfoHandler.getInstance());
UIDispatchManager.getInstance().startScheduler();
}
}
/**
* 停止监控关闭异步提交线程及定时堆栈任务
*/
public void stop() {
UIDispatchManager.getInstance().unregisterHandler(UILatencyInfoHandler.getInstance());
UIDispatchManager.getInstance().stopSchedulerIfNecessary();
if (this.executorService != null) {
this.executorService.shutdown();
}
initialized.set(false);
}
/**
* 是否监控中
*
* @return 是否监控中
*/
public boolean isMonitoring() {
return initialized.get();
}
/**
* 设置UI卡顿堆栈阈值
* @param threshold 阈值 ms
*/
public void resetThreshold(long threshold) {
UILatencyInfoHandler.getInstance().setThreshold(threshold);
}
/**
* 提交卡顿堆栈信息
* @param latencyInfo 卡顿信息
*/
public void submit(LatencyInfo latencyInfo) {
executorService.submit(() -> {
if (UIMonitorHelper.isIgnoreEvent(latencyInfo.getDetailStack())) {
return;
}
LatencyInfo existInfo = infoContainer.getIfPresent(latencyInfo.getSeq());
// 确保记录的是最深的堆栈信息
if (existInfo == null || latencyInfo.getDetailStack().length > existInfo.getDetailStack().length) {
infoContainer.put(latencyInfo.getSeq(), latencyInfo);
EventDispatcher.fire(LatencyMonitorEvent.OFF_THRESHOLD_EVENT, latencyInfo);
}
});
}
/**
* 输出卡顿文本信息
*
* @return 卡顿文本信息
*/
public String getLatencyData() {
return getAllLatencyInfo().stream().map(info -> "seq:" + info.getSeq() + "\n" +
"cost:" + info.getCost() + "ms\n" +
"stack:" + UIMonitorHelper.convertStack(info.getDetailStack()) + "\n").collect(Collectors.joining("\n"));
}
/**
* 获取当前记录的所有卡顿信息
* @return 全量卡顿信息
*/
public Collection<LatencyInfo> getAllLatencyInfo() {
return infoContainer.asMap().values();
}
/**
* 清空全量卡顿信息
*/
public void clearData() {
infoContainer.invalidateAll();
}
}

40
designer-base/src/main/java/com/fr/design/debug/ui/UIMonitorAction.java

@ -0,0 +1,40 @@
package com.fr.design.debug.ui;
import com.fine.theme.utils.FineUIUtils;
import com.fr.design.actions.UpdateAction;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.utils.gui.GUICoreUtils;
import javax.swing.JDialog;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER;
/**
* UI实时监控
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/07
*/
public class UIMonitorAction extends UpdateAction {
public static final String TITLE = "UI Monitor";
public UIMonitorAction() {
this.setName(TITLE);
this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, DEFAULT_MODIFIER));
}
@Override
public void actionPerformed(ActionEvent e) {
JDialog jDialog = new JDialog(DesignerContext.getDesignerFrame(), TITLE);
jDialog.setSize(FineUIUtils.calPaneDimensionByContext(0.5, 0.7));
UIMonitorPane monitorPane = new UIMonitorPane();
jDialog.add(monitorPane);
GUICoreUtils.centerWindow(jDialog);
jDialog.setVisible(true);
}
}

44
designer-base/src/main/java/com/fr/design/debug/ui/UIMonitorHelper.java

@ -0,0 +1,44 @@
package com.fr.design.debug.ui;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
* UI性能监控工具类
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/08
*/
public class UIMonitorHelper {
/**
* 判断是否特定的堆栈
*/
public static boolean stackTraceElementIs(StackTraceElement e, String className, String methodName, boolean isNative) {
return e.getClassName().equals(className) && e.getMethodName().equals(methodName) && e.isNativeMethod() == isNative;
}
/**
* 用于判断是否为需要忽略记录的堆栈信息
*/
public static boolean isIgnoreEvent(StackTraceElement[] currentStack) {
return currentStack != null && currentStack.length >= 1 && (
stackTraceElementIs(currentStack[0], "java.lang.Object", "wait", true)
|| stackTraceElementIs(currentStack[0], "sun.misc.Unsafe", "park", true)
);
}
/**
* 堆栈格式化
* @param stackTrace 堆栈信息
*
* @return 格式化后的堆栈信息
*/
public static String convertStack(StackTraceElement[] stackTrace) {
return Arrays.stream(stackTrace)
.map(st -> "\t" + st.toString()).collect(Collectors.joining("\n"));
}
}

274
designer-base/src/main/java/com/fr/design/debug/ui/UIMonitorPane.java

@ -0,0 +1,274 @@
package com.fr.design.debug.ui;
import com.fine.swing.ui.layout.Row;
import com.fine.theme.icon.LazyIcon;
import com.fine.theme.utils.FineClientProperties;
import com.fine.theme.utils.FineUIUtils;
import com.formdev.flatlaf.util.ScaledEmptyBorder;
import com.fr.base.extension.FileExtension;
import com.fr.design.border.FineBorderFactory;
import com.fr.design.carton.latency.LatencyLevel;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.icontainer.UITableScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itable.FineUITable;
import com.fr.design.gui.itextarea.UITextArea;
import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.mainframe.DesignerContext;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.file.FILE;
import com.fr.file.FILEChooserPane;
import com.fr.file.filter.ChooseFileFilter;
import com.fr.general.GeneralUtils;
import com.fr.log.FineLoggerFactory;
import org.jetbrains.annotations.NotNull;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.Arrays;
import java.util.Date;
import static com.fine.swing.ui.layout.Layouts.cell;
import static com.fine.swing.ui.layout.Layouts.column;
import static com.fine.swing.ui.layout.Layouts.row;
/**
* UI监控面板
*
* @author Levy.Xie
* @since 11.0
* Created on 2024/11/07
*/
public class UIMonitorPane extends JPanel {
private DefaultTableModel model;
private UICheckBox inspector;
private UICheckBox monitor;
public UIMonitorPane() {
setLayout(new BorderLayout());
setBorder(new ScaledEmptyBorder(10, 10, 10, 10));
initComponent();
}
private void initComponent() {
UITableScrollPane tablePane = initLatencyTable();
Row topSettingRow = initTopSettingRow();
inspector = new UICheckBox("Open UI Inspector");
monitor = new UICheckBox("Open Latency Monitor");
JPanel monitorPane = column(10,
cell(monitor), cell(topSettingRow), cell(tablePane).weight(1)
).getComponent();
add(column(10,
cell(FineUIUtils.wrapComponentWithTitle(inspector, "UI Inspector")),
cell(FineUIUtils.wrapComponentWithTitle(monitorPane, "UI Latency Monitor"))
).getComponent(), BorderLayout.CENTER);
topSettingRow.setVisible(false);
tablePane.setVisible(false);
initMonitorStatus(topSettingRow, tablePane);
}
private void initMonitorStatus(Row topSettingRow, UITableScrollPane tablePane) {
inspector.setSelected(UIInspectorHolder.getInstance().isInstalled());
monitor.setSelected(UILatencyWorker.getInstance().isMonitoring());
// 注册事件监听
inspector.addChangeListener(e -> {
if (inspector.isSelected()) {
UIInspectorHolder.getInstance().install();
} else {
UIInspectorHolder.getInstance().uninstall();
}
});
monitor.addChangeListener(e -> {
topSettingRow.setVisible(monitor.isSelected());
tablePane.setVisible(monitor.isSelected());
if (monitor.isSelected()) {
startMonitor();
} else {
stopMonitor();
}
});
// 初始化卡顿堆栈表
if (monitor.isSelected()) {
SwingUtilities.invokeLater(() -> UILatencyWorker.getInstance().getAllLatencyInfo()
.forEach(info -> model.addRow(parseInfo2Row(info))));
}
}
private Row initTopSettingRow() {
UIComboBox comboBox = initThresholdComboBox();
UIButton export = new UIButton(new LazyIcon("export"));
export.setToolTipText("Export latency log");
UIButton clear = new UIButton(new LazyIcon("remove"));
clear.setToolTipText("Clear latency log");
JToolBar toolbar = new UIToolbar();
toolbar.add(comboBox);
toolbar.add(clear);
toolbar.add(export);
export.addActionListener(e -> exportData());
clear.addActionListener(e -> {
model.setRowCount(0);
UILatencyWorker.getInstance().clearData();
});
return row(5, cell(new UILabel("Latency Threshold")), cell(toolbar)).getComponent();
}
private static @NotNull UIComboBox initThresholdComboBox() {
UIComboBox comboBox = new UIComboBox(Arrays.stream(LatencyLevel.values())
.filter(it -> it != LatencyLevel.FLASH).map(LatencyLevel::getStart).toArray());
comboBox.putClientProperty(FineClientProperties.COMBO_BOX_TYPE, FineClientProperties.ADAPTIVE_COMBO_BOX);
comboBox.setSelectedItem(UILatencyInfoHandler.getInstance().getThreshold());
comboBox.addActionListener(e -> {
if (comboBox.getSelectedItem() != null) {
UILatencyWorker.getInstance().resetThreshold((Long) comboBox.getSelectedItem());
}
});
// 阈值初始化
comboBox.setSelectedItem(comboBox.getSelectedItem());
return comboBox;
}
private UITableScrollPane initLatencyTable() {
model = new DefaultTableModel();
model.addColumn("seq");
model.addColumn("cost(ms)");
model.addColumn("stack");
FineUITable table = new FineUITable(model) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
UITableScrollPane tablePane = new UITableScrollPane(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
if (row >= 0) {
String stack = (String) table.getValueAt(row, 2);
StackPane stackPane = new StackPane(stack);
BasicDialog dialog = stackPane.showLargeWindow(SwingUtilities.getWindowAncestor(e.getComponent()), null);
dialog.setAlwaysOnTop(true);
dialog.setVisible(true);
}
}
});
TableColumnModel columnModel = table.getColumnModel();
adjustColumnWidth(columnModel.getColumn(0));
adjustColumnWidth(columnModel.getColumn(1));
return tablePane;
}
private void adjustColumnWidth(TableColumn column) {
column.setPreferredWidth(100);
column.setMinWidth(100);
column.setMaxWidth(100);
}
/**
* 开启性能监控
*/
public void startMonitor() {
EventDispatcher.listen(LatencyMonitorEvent.OFF_THRESHOLD_EVENT, latencyInfoListener);
UILatencyWorker.getInstance().start();
}
/**
* 关闭性能监控
*/
public void stopMonitor() {
UILatencyWorker.getInstance().stop();
EventDispatcher.stopListen(latencyInfoListener);
model.setRowCount(0);
}
private void exportData() {
// 导出为txt文件
FILEChooserPane fileChooserPane = FILEChooserPane.getMultiEnvInstance(true, false);
String fileName = "latency_log_" + GeneralUtils.objectToString(new Date()).replaceAll(":", "_");
fileChooserPane.setFileNameTextField(fileName, ".txt");
fileChooserPane.addChooseFILEFilter(new ChooseFileFilter(FileExtension.TXT));
int saveValue = fileChooserPane.showSaveDialog(DesignerContext.getDesignerFrame());
if (saveValue == FILEChooserPane.JOPTIONPANE_OK_OPTION || saveValue == FILEChooserPane.OK_OPTION) {
FILE target = fileChooserPane.getSelectedFILE();
try {
target.mkfile();
try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(target.getPath(), true))) {
bufferedWriter.write(UILatencyWorker.getInstance().getLatencyData());
}
} catch (Exception exp) {
FineLoggerFactory.getLogger().error("[Latency] Error export latency log.", exp);
}
}
}
private final Listener<LatencyInfo> latencyInfoListener = new Listener<LatencyInfo>() {
@Override
public void on(Event event, LatencyInfo latencyInfo) {
SwingUtilities.invokeLater(() -> {
// 存量卡顿堆栈信息更新
for (int i = 0; i < model.getRowCount(); i++) {
if (latencyInfo.getSeq() == (Long) model.getValueAt(i, 0)) {
model.removeRow(i);
break;
}
}
model.addRow(parseInfo2Row(latencyInfo));
});
}
};
private Object[] parseInfo2Row(LatencyInfo latencyInfo) {
return new Object[]{
latencyInfo.getSeq(),
latencyInfo.getCost(),
UIMonitorHelper.convertStack(latencyInfo.getDetailStack())};
}
static class StackPane extends BasicPane {
public StackPane(String stack) {
setLayout(new BorderLayout());
UITextArea textArea = new UITextArea();
textArea.setBorder(null);
textArea.setEditable(false);
textArea.setText(stack);
UIScrollPane scrollPane = new UIScrollPane(textArea);
scrollPane.setBorder(FineBorderFactory.createWrappedRoundBorder());
add(scrollPane);
SwingUtilities.invokeLater(() -> scrollPane.getViewport().setViewPosition(new Point(0, 0)));
}
@Override
protected String title4PopupWindow() {
return "Latency Stack";
}
}
}

3
designer-base/src/main/java/com/fr/design/editor/editor/ColumnSelectedEditor.java

@ -35,7 +35,7 @@ public class ColumnSelectedEditor extends Editor<SimpleDSColumn> implements Prep
public ColumnSelectedEditor() {
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS_Column"));
this.setLayout(new BorderLayout());
tableDataComboBox = new TableDataComboBox(DesignTableDataManager.getEditingTableDataSource());
tableDataComboBox = new TableDataComboBox();
columnNames = new String[0];
tableDataComboBox.addItemListener(new ItemListener() {
@ -117,6 +117,5 @@ public class ColumnSelectedEditor extends Editor<SimpleDSColumn> implements Prep
@Override
public void registerDSChangeListener() {
tableDataComboBox.registerGlobalDSChangeListener();
}
}

3
designer-base/src/main/java/com/fr/design/env/HttpWorkspaceConnector.java vendored

@ -3,6 +3,7 @@ package com.fr.design.env;
import com.fanruan.workplace.http.HttpConstants;
import com.fanruan.workplace.http.HttpServiceMap;
import com.fanruan.workplace.http.RepositoryManager;
import com.fanruan.workplace.http.exception.RemoteServiceErrorException;
import com.fanruan.workplace.http.info.Stub;
import com.fanruan.workplace.network.RemoteNetworkRepository;
import com.fr.decision.webservice.bean.authentication.LoginRequestInfoBean;
@ -86,7 +87,7 @@ public class HttpWorkspaceConnector implements WorkspaceConnector {
client.setTimeout(timeout);
try {
return RemoteNetworkRepository.getInstance().testConnect();
} catch (RemoteDesignNoAuthException e) {
} catch (RemoteDesignNoAuthException | RemoteServiceErrorException e) {
throw e;
} catch (Exception e) {
throw new RemoteDesignConnectionException(e, StringUtils.EMPTY);

10
designer-base/src/main/java/com/fr/design/jxbrowser/JxEngine.java

@ -51,7 +51,6 @@ public class JxEngine {
EngineOptions.Builder builder = EngineOptions
.newBuilder(RenderingMode.HARDWARE_ACCELERATED)
.addSwitch("--disable-google-traffic")
.addSwitch("--disable-web-security")
.addScheme(Scheme.of(ModernUIConstants.EMB_TAG),
new NxInterceptRequestCallback(this::getComponent, this::getParameterMap));
if (disableWebSecurity) {
@ -144,6 +143,15 @@ public class JxEngine {
return ENGINE.getValue();
}
/**
* 是否禁用安全属性
* 对客户端来说安全属性可以忽略
*
* @return 是否禁用
*/
public boolean isDisableWebSecurity() {
return disableWebSecurity;
}
/**
* 添加XHR请求头

6
designer-base/src/main/java/com/fr/design/jxbrowser/JxUIPane.java

@ -13,6 +13,7 @@ import com.fr.stable.collections.combination.Pair;
import com.fr.stable.os.OperatingSystem;
import com.fr.web.struct.AssembleComponent;
import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.browser.callback.CertificateErrorCallback;
import com.teamdev.jxbrowser.browser.callback.InjectJsCallback;
import com.teamdev.jxbrowser.event.Observer;
import com.teamdev.jxbrowser.frame.Frame;
@ -81,6 +82,11 @@ public class JxUIPane<T> extends BasicPane {
}
initDebugIfNeeded();
browser = jxEngine.getEngine().newBrowser();
if (jxEngine.isDisableWebSecurity()) {
// 忽略证书验证,兼容有些情况下自定义证书与实际域名不匹配的情况。
// 虽然不是个正确的方式,但真有这么用的还是兼容一下
browser.set(CertificateErrorCallback.class, (params, action) -> action.allow());
}
add(BrowserView.newInstance(browser), BorderLayout.CENTER);
}

33
designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java

@ -1,8 +1,10 @@
package com.fr.design.mainframe;
import com.fanruan.repository.TemplateRepository;
import com.fine.swing.ui.layout.Layouts;
import com.fine.theme.icon.LazyIcon;
import com.fine.theme.utils.FineLayoutBuilder;
import com.fine.theme.utils.FineUIScale;
import com.fine.theme.utils.FineUIStyle;
import com.formdev.flatlaf.util.ScaledEmptyBorder;
import com.fr.base.BaseUtils;
@ -641,11 +643,7 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
this.setModal(true);
// 输入框前提示
UILabel newNameLabel = new UILabel(Toolkit.i18nText(
"Fine-Design_Basic_Enter_New_Folder_Name")
);
newNameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
newNameLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
UILabel newNameLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Enter_New_Folder_Name"));
// 文件名输入框
nameField = new UITextField();
@ -667,12 +665,9 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
}
});
nameField.selectAll();
nameField.setPreferredSize(new Dimension(180, 20));
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 5));
topPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 0, 15));
topPanel.add(newNameLabel);
topPanel.add(nameField);
JPanel topPanel = Layouts.row(10, Layouts.cell(newNameLabel), Layouts.cell(nameField).weight(1)).getComponent();
topPanel.setBorder(new ScaledEmptyBorder(15, 10, 0, 10));
// 增加enter以及esc快捷键的支持
nameField.addKeyListener(new KeyAdapter() {
@ -689,15 +684,14 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
});
// 重名提示
warnLabel = new UILabel();
warnLabel.setPreferredSize(new Dimension(300, 50));
warnLabel.setHorizontalAlignment(SwingConstants.LEFT);
warnLabel.setVerticalAlignment(SwingConstants.TOP);
warnLabel.setForeground(Color.RED);
warnLabel.setVisible(false);
FineUIStyle.setStyle(warnLabel, FineUIStyle.LABEL_WARNING_TIP);
JPanel midPanel = new JPanel(new BorderLayout());
midPanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 15));
midPanel.add(warnLabel, BorderLayout.WEST);
midPanel.setBorder(new ScaledEmptyBorder(0, 10, 0, 10));
midPanel.add(Layouts.column(Layouts.flex(), Layouts.cell(warnLabel), Layouts.flex()).getComponent());
// 确认按钮
confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Confirm"));
@ -719,10 +713,8 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
}
});
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0));
bottomPanel.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 10));
bottomPanel.add(confirmButton);
bottomPanel.add(cancelButton);
JPanel bottomPanel = Layouts.row(10, Layouts.flex(), Layouts.cell(confirmButton), Layouts.cell(cancelButton)).getComponent();
bottomPanel.setBorder(new ScaledEmptyBorder(10, 10, 10, 10));
this.add(
TableLayoutHelper.createTableLayoutPane(
@ -731,13 +723,12 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
new Component[]{midPanel},
new Component[]{bottomPanel}
},
new double[]{TableLayout.FILL, TableLayout.PREFERRED, TableLayout.PREFERRED},
new double[]{TableLayout.PREFERRED, TableLayout.FILL, TableLayout.PREFERRED},
new double[]{TableLayout.FILL}
),
BorderLayout.CENTER);
this.setSize(380, 200);
this.setSize(FineUIScale.createScaleDimension(380, 200));
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Mkdir"));
this.setResizable(false);
this.setAlwaysOnTop(true);

20
designer-base/src/main/java/com/fr/design/mainframe/toolbar/DebugModeMenuDef.java

@ -1,13 +1,11 @@
package com.fr.design.mainframe.toolbar;
import com.fanruan.gui.UiInspector;
import com.fine.theme.light.ui.laf.FineDarkLaf;
import com.fine.theme.light.ui.laf.FineLightLaf;
import com.fr.design.actions.UpdateAction;
import com.fr.design.gui.UILookAndFeel;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.menu.MenuDef;
import com.fr.design.remote.ui.debug.RemoteDesignNetWorkAction;
import com.fr.design.debug.remote.RemoteDesignNetWorkAction;
import com.fr.design.debug.ui.UIMonitorAction;
import java.awt.event.ActionEvent;
@ -24,15 +22,7 @@ public class DebugModeMenuDef extends MenuDef {
super("Debug");
addLookAndFeelMenu();
addRemotePane();
}
private void addUIInspect() {
this.addShortCut(new UpdateAction() {
@Override
public void actionPerformed(ActionEvent e) {
new UiInspector().showInspector(DesignerContext.getDesignerFrame());
}
});
addUIMonitorPane();
}
private void addLookAndFeelMenu() {
@ -48,4 +38,8 @@ public class DebugModeMenuDef extends MenuDef {
private void addRemotePane() {
this.addShortCut(new RemoteDesignNetWorkAction());
}
private void addUIMonitorPane() {
this.addShortCut(new UIMonitorAction());
}
}

2
designer-base/src/main/java/com/fr/design/mainframe/widget/editors/DataBindingEditor.java

@ -65,7 +65,7 @@ public class DataBindingEditor extends Editor<DataBinding> {
int vgap = UIManager.getInt("DataBindingEditor.vgap");
int hgap = UIManager.getInt("DataBindingEditor.hgap");
this.setLayout(new BorderLayout(FineUIScale.scale(hgap), FineUIScale.scale(vgap)));
tableDataComboBox = new TableDataComboBox(getTableDataSource());
tableDataComboBox = new TableDataComboBox();
tableDataComboBox.setPreferredSize(new Dimension(55, 20));
tableDataComboBox.addItemListener(tableDataComboBoxListener);

2
designer-base/src/main/java/com/fr/design/mainframe/widget/editors/DataTableEditor.java

@ -29,7 +29,7 @@ public class DataTableEditor extends Editor<DataTableConfig> {
private void initCompontents() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
tableDataComboBox = new TableDataComboBox(getTableDataSource());
tableDataComboBox = new TableDataComboBox();
tableDataComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent evt) {

3
designer-base/src/main/java/com/fr/design/present/dict/TableDataDictPane.java

@ -78,7 +78,7 @@ public class TableDataDictPane extends FurtherBasicBeanPane<TableDataDictionary>
}
private void initBasicComponets() {
tableDataNameComboBox = new TableDataComboBox(DesignTableDataManager.getEditingTableDataSource());
tableDataNameComboBox = new TableDataComboBox();
tableDataNameComboBox.addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
tdChange(e);
@ -362,6 +362,5 @@ public class TableDataDictPane extends FurtherBasicBeanPane<TableDataDictionary>
@Override
public void registerDSChangeListener() {
tableDataNameComboBox.registerGlobalDSChangeListener();
}
}

158
designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java

@ -1,158 +0,0 @@
package com.fr.design.record.analyzer;
import com.fr.base.OptimizeUtil;
import com.fr.collect.Collect;
import com.fr.design.record.analyzer.Interceptor.CollectInterceptor;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.design.record.analyzer.advice.CollectAdvice;
import com.fr.design.record.analyzer.advice.DBMonitorAdvice;
import com.fr.design.record.analyzer.advice.FaultToleranceAdvice;
import com.fr.design.record.analyzer.advice.FocusAdvice;
import com.fr.design.record.analyzer.advice.MonitorAdvice;
import com.fr.design.record.analyzer.advice.PerformancePointAdvice;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.intelli.metrics.Compute;
import com.fr.intelli.record.Focus;
import com.fr.intelli.record.PerformancePoint;
import com.fr.jvm.assist.FineAssist;
import com.fr.module.Activator;
import com.fr.module.extension.Prepare;
import com.fr.record.analyzer.AnalyzerConfiguration;
import com.fr.record.analyzer.AnalyzerKey;
import com.fr.record.analyzer.Assistant;
import com.fr.record.analyzer.DBMetrics;
import com.fr.record.analyzer.FineAnalyzer;
import com.fr.record.analyzer.advice.AnalyzerAdviceKey;
import com.fr.record.analyzer.advice.FineAdviceAssistant;
import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory;
import com.fr.record.analyzer.configuration.FineAnalyzerAssemblyFactory;
import com.fr.stable.collections.CollectionUtils;
import com.fr.third.net.bytebuddy.description.type.TypeDescription;
import com.fr.third.net.bytebuddy.dynamic.DynamicType;
import com.fr.third.net.bytebuddy.implementation.MethodDelegation;
import com.fr.third.net.bytebuddy.matcher.ElementMatchers;
import com.fr.third.net.bytebuddy.utility.JavaModule;
import com.fr.tolerance.FaultTolerance;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.concurrent.ExecutorService;
/**
* created by Harrison on 2022/03/04
**/
public class DesignerAnalyzerActivator extends Activator implements Prepare {
@Override
public void start() {
OptimizeUtil.open(OptimizeUtil.Module.ANALYZER,() -> {
AnalyzerAssemblyFactory basicFactory = createBasicFactory();
// 兼容逻辑
List<AnalyzerConfiguration> backwardsConfigurations = findMutableBackwards(AnalyzerKey.KEY);
if (!CollectionUtils.isEmpty(backwardsConfigurations)) {
// 直接初始化,不添加默认值,防止和下面的冲突
FineAnalyzer.initDirectly(FineAssist.findInstrumentation(), basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0]));
}
// 等页面完全打开后,再进行 retransform, 别影响了启动速度
EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
ExecutorService es = newSingleThreadExecutor(new NamedThreadFactory("designer-analyzer", true));
try {
// 加入 retransform 部分的逻辑
List<FineAdviceAssistant> adviceConfigurations = findMutable(AnalyzerAdviceKey.KEY);
if (!CollectionUtils.isEmpty(adviceConfigurations)) {
AnalyzerConfiguration[] configurations = convertConfigurations(adviceConfigurations);
es.submit(() -> {
DesignerAnalyzer.init(basicFactory, configurations);
});
}
} finally {
es.shutdown();
}
}
});
});
}
@NotNull
private AnalyzerConfiguration[] convertConfigurations(List<FineAdviceAssistant> list) {
return list.stream()
.map(AnalyzerConfiguration::create)
.toArray(AnalyzerConfiguration[]::new);
}
@Override
public void stop() {
}
@Override
public void prepare() {
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(Focus.class),
FocusAdvice.class
));
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(Compute.class),
MonitorAdvice.class
));
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(DBMetrics.class),
DBMonitorAdvice.class
));
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(PerformancePoint.class),
PerformancePointAdvice.class
));
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(FaultTolerance.class),
FaultToleranceAdvice.class
));
// 保持M1 可用
addMutable(AnalyzerKey.KEY, AnalyzerConfiguration.create(new Assistant() {
@Override
public DynamicType.Builder<?> supply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
return builder
.method(ElementMatchers.isAnnotatedWith(Collect.class))
.intercept(MethodDelegation.to(CollectInterceptor.class));
}
}));
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(Collect.class),
CollectAdvice.class
));
}
private AnalyzerAssemblyFactory createBasicFactory() {
AnalyzerAssemblyFactory factory = findSingleton(AnalyzerAssemblyFactory.class);
FineAnalyzerAssemblyFactory basicFactory = new FineAnalyzerAssemblyFactory();
basicFactory.prepare(factory);
return basicFactory;
}
}

6
designer-base/src/main/java/com/fr/design/utils/DesignUtils.java

@ -1,8 +1,8 @@
package com.fr.design.utils;
import com.fanruan.workplace.http.HttpConstants;
import com.fine.theme.light.ui.laf.FineLightLaf;
import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
import com.fanruan.workplace.http.HttpConstants;
import com.fr.base.FeedBackInfo;
import com.fr.base.ServerConfig;
import com.fr.base.Utils;
@ -377,10 +377,10 @@ public class DesignUtils {
}
/**
* 访问服务器环境-空参数
* 默认情况下访问服务器环境
*/
public static void visitEnvServer() {
visitEnvServerByParameters(StringUtils.EMPTY, new String[]{}, new String[]{});
visitEnvServerByParameters(ServerStarter.DEFAULT_SERVER_BASE_ROUTE, new String[]{}, new String[]{});
}
/**

27
designer-base/src/main/java/com/fr/env/EnvPrepare.java vendored

@ -1,27 +0,0 @@
package com.fr.env;
import com.fr.env.detect.EnvDetectorCenter;
import com.fr.module.Activator;
/**
* 设计器环境准备
* 更多的是一些钩子需要在环境启动切换时进行处理
* 使用监听 {@link com.fr.workspace.WorkspaceEvent} 只能满足
* before -> stop -> start -> after
* 现在支持 =>
* before -> stop -> prepare -> start -> after
*
* created by Harrison on 2022/05/29
**/
public class EnvPrepare extends Activator {
@Override
public void start() {
EnvDetectorCenter.getInstance().init();
}
@Override
public void stop() {
EnvDetectorCenter.getInstance().destroy();
}
}

2
designer-base/src/main/java/com/fr/env/RemoteEnvPane.java vendored

@ -336,7 +336,7 @@ public class RemoteEnvPane extends BasicBeanPane<RemoteDesignerWorkspaceInfo> {
@Override
public RemoteDesignerWorkspaceInfo updateBean() {
String url = removeSpaces(this.remoteWorkspaceURL.getURL());
String url = removeSpaces(this.remoteWorkspaceURL.getStandardURL());
String username = removeSpaces(this.usernameInput.getText());
String password = new String(this.passwordInput.getPassword());
boolean rememberPwd = this.rememberPwdCheckbox.isSelected();

28
designer-base/src/main/java/com/fr/env/RemoteWorkspaceURL.java vendored

@ -1,17 +1,17 @@
package com.fr.env;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.AssistUtils;
import com.fr.stable.FCloneable;
import com.fr.stable.StringUtils;
import java.net.URI;
import java.net.URISyntaxException;
import com.fr.third.guava.base.Strings;
/**
* @author yaohwu
*/
public class RemoteWorkspaceURL implements FCloneable {
private static final String SLASH = "/";
private static final String IPV6_JUDGE_SYMBOL = "[";
private static final String IPV6_JUDGE_SYMBOL2 = "]";
@ -126,25 +126,41 @@ public class RemoteWorkspaceURL implements FCloneable {
this.servlet = servlet != null ? servlet.trim() : StringUtils.EMPTY;
}
/**
* 用于UI联动的URL不一定是标准远程设计URL
*
* @return 原始或生成的URL
*/
public String getURL() {
if (this.url != null) {
return url;
}
String prefix = isHttps ? HTTPS : HTTP;
String portColon = StringUtils.isNotEmpty(port) ? ":" : StringUtils.EMPTY;
String webAppNameSlash = StringUtils.isNotEmpty(web) ? "/" : StringUtils.EMPTY;
String servletNameSlash = "/";
this.url = prefix + host + portColon + port + webAppNameSlash + web + servletNameSlash;
String webAppNameSlash = StringUtils.isNotEmpty(web) ? SLASH : StringUtils.EMPTY;
this.url = prefix + host + portColon + port + webAppNameSlash + web + SLASH + servlet;
return this.url;
}
/**
* 获取用于远程连接的可用URL
*
* @return 远程连接的可用URL
*/
public String getStandardURL() {
String prefix = isHttps ? HTTPS : HTTP;
String portColon = StringUtils.isNotEmpty(port) ? ":" : StringUtils.EMPTY;
String webAppNameSlash = StringUtils.isNotEmpty(web) ? SLASH : StringUtils.EMPTY;
return prefix + host + portColon + port + webAppNameSlash + web + SLASH;
}
/**
* IPV6地址格式不同,处理字符串的方式不同,需要处理的是port和host
* 形如 http://[XXXX::XXXX:XXXX:XXXX:XXXX]:8080/webroot/decision
*/
public void refreshIPV6Format() {
String url = this.url;
if (Strings.isNullOrEmpty(url)) {
if (StringUtils.isEmpty(url)) {
return;
}
if (!url.contains(IPV6_JUDGE_SYMBOL) || !url.contains(IPV6_JUDGE_SYMBOL2)) {

3
designer-base/src/main/java/com/fr/start/ServerStarter.java

@ -15,6 +15,9 @@ import java.util.concurrent.Executors;
public class ServerStarter {
// FBP 下默认进入管理系统
public static final String DEFAULT_SERVER_BASE_ROUTE = "#/management";
/**
* 预览Demo
* 找默认工作目录不应该按照名字去找而应该按照安装路径因为默认工作目录的名字可能会改变

7
designer-base/src/main/java/com/fr/start/server/DesignEmbedHelper.java

@ -7,6 +7,7 @@ import com.fr.design.DesignerEnvManager;
import com.fr.log.FineLoggerFactory;
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;
@ -16,7 +17,8 @@ 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.io.File;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
@ -25,6 +27,8 @@ import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
;
/**
* 内置服务器工具类
*
@ -100,6 +104,7 @@ public class DesignEmbedHelper {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(EmbedWebApplicationInitializer.class);
context.addServletContainerInitializer(initializer, classes);
context.addServletContainerInitializer(new WsSci(), Sets.newHashSet(WebSocketEndpoint.class));
}
/**

156
designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java

@ -1,156 +0,0 @@
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.Activator;
import com.fr.module.ModuleRole;
import com.fr.stable.EncodeConstants;
import com.fanruan.product.ProductConstants;
import com.fr.stable.StringUtils;
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.util.HashSet;
import java.util.Set;
/**
* Created by juhaoyu on 2018/6/5.
*/
@Deprecated
public class FineEmbedServerActivator extends Activator {
private static final String TOMCAT_MAX_HEADER_SIZE = "tomcat-maxHttpHeaderSize";
private Tomcat tomcat;
@Override
public synchronized void start() {
try {
FineEmbedServerMonitor.getInstance().reset();
//初始化tomcat
initTomcat();
tomcat.start();
} catch (LifecycleException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} finally {
FineEmbedServerMonitor.getInstance().setComplete();
}
}
@Override
public synchronized void stop() {
try {
stopSpring();
stopServerActivator();
stopTomcat();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private 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", "[]|{}^&#x5c;&#x60;&quot;&lt;&gt;");
setMaxPostSize();
setMaxHttpHeaderSize();
String docBase = new File(WorkContext.getCurrent().getPath()).getParent();
//内置的上下文使用工程目录比如webroot
String contextPath = "/" + ProductConstants.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<?>>();
/// 该Initializer已去除
//classes.add(FineWebApplicationInitializer.class);
context.addServletContainerInitializer(initializer, classes);
// 后面本地设计的内置服务器考虑用XST
// context.addServletContainerInitializer(new WsSci(), Sets.newHashSet(WebSocketEndpoint.class));
}
// tomcat的maxPostSize会影响到post参数获取,默认2M
private 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 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 void stopServerActivator() {
ModuleRole.ServerRoot.stop();
}
private void stopSpring() {
AnnotationConfigWebApplicationContext context = ModuleRole.ServerRoot.findSingleton(AnnotationConfigWebApplicationContext.class);
if (context != null) {
context.stop();
context.destroy();
}
}
private 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();
}
}
}

98
designer-base/src/main/resources/com/fr/design/data/tabledata/datacenter/web/data-choose.main.js

File diff suppressed because one or more lines are too long

18
designer-base/src/test/java/com/fr/env/RemoteWorkspaceURLTest.java vendored

@ -243,6 +243,24 @@ public class RemoteWorkspaceURLTest {
//others begin
}
@Test
public void testStandardURL(){
assertEquals("https://www.baidu.com/web/",
new RemoteWorkspaceURL("https://www.baidu.com/web//dfsaf/fdsafds").getStandardURL());
assertEquals("https://www.baidu.com/中文·o((⊙﹏⊙))o囖/",
new RemoteWorkspaceURL("https://www.baidu.com/中文·o((⊙﹏⊙))o囖//dfsaf/fdsafds").getStandardURL());
assertEquals("https://www.baidu.com/web/",
new RemoteWorkspaceURL("https://www.baidu.com/web").getStandardURL());
assertEquals("https://www.baidu.com/web/",
new RemoteWorkspaceURL("https://www.baidu.com/web//").getStandardURL());
assertEquals("https://www.baidu.com/web/",
new RemoteWorkspaceURL("https://www.baidu.com/web/servlet").getStandardURL());
}
@Test
public void testIPV6Url() {
String trueUrl = "http://[fe80::4d83:cc10:9f6f:3303]:8080/webroot/decision";

2
designer-chart/src/main/java/com/fr/design/chart/AutoChartTypePane.java

@ -141,7 +141,7 @@ public class AutoChartTypePane extends ChartWizardPane implements CallbackEvent
}
private void initDataFiledBox() {
tableNameComboBox = new TableDataComboBox(DesignTableDataManager.getEditingTableDataSource());
tableNameComboBox = new TableDataComboBox();
tableNameComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {

2
designer-chart/src/main/java/com/fr/design/chartx/component/MapAreaMatchPane.java

@ -126,7 +126,7 @@ public class MapAreaMatchPane extends BasicBeanPane<MapMatchResult> {
}
private void initButtonGroup() {
tableNameCombox = new TableDataComboBox(DesignTableDataManager.getEditingTableDataSource());
tableNameCombox = new TableDataComboBox();
tableNameCombox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {

6
designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartOtherPane.java

@ -17,6 +17,7 @@ import com.fr.design.mainframe.chart.info.ChartInfoCollector;
import com.fr.van.chart.designer.component.richText.VanChartRichEditorPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.util.ArrayList;
import java.util.List;
import java.awt.BorderLayout;
@ -114,7 +115,10 @@ public class ChartOtherPane extends AbstractChartAttrPane {
if (ChartOtherPane.this.isHaveCondition()) {
VanChartRichEditorPane.refreshCommonChartFieldNames(chart);
ColSelectedWithSummaryMethodEditor.refreshCommonChartFieldNames(chart);
conditionAttrPane.populateBean(chart);
SwingUtilities.invokeLater(() -> {
conditionAttrPane.populateBean(chart);
initListener(conditionAttrPane);
});
}
}

15
designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartStylePane.java

@ -30,6 +30,7 @@ public class ChartStylePane extends AbstractChartAttrPane {
private Chart chart;
private AttributeChangeListener listener;
private BasicPane chartAxisPane;
private boolean chartStyleInitialized = false;
protected Chart getChart() {
return chart;
@ -64,11 +65,15 @@ public class ChartStylePane extends AbstractChartAttrPane {
@Override
public void populate(ChartCollection collection) {
this.chart = collection.getSelectedChart();
this.remove(leftContentPane);
initContentPane();
this.removeAttributeChangeListener();
stylePane.populateBean(chart);
this.addAttributeChangeListener(listener);
// 子组件布局初始化,只在第一次进入的时候绘制
if (!chartStyleInitialized) {
this.remove(leftContentPane);
initContentPane();
this.removeAttributeChangeListener();
this.addAttributeChangeListener(listener);
this.initAllListeners();
chartStyleInitialized = true;
}
this.initAllListeners();
}

2
designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/DatabaseTableDataPane.java

@ -75,7 +75,7 @@ public class DatabaseTableDataPane extends BasicPane{
}
private void initTableCombox() {
tableNameCombox = new TableDataComboBox(DesignTableDataManager.getEditingTableDataSource()){
tableNameCombox = new TableDataComboBox(){
//图表的数据集选择下拉框,不需要注册监听,chartEditPane已经注册了。
public void registerDSChangeListener() {

14
designer-realize/src/main/java/com/fanruan/boot/adaptation/DesignServerSupportModule.java

@ -1,10 +1,13 @@
package com.fanruan.boot.adaptation;
import com.fanruan.carina.Carina;
import com.fanruan.carina.context.ContextListener;
import com.fanruan.carina.event.CarinaLifecycleEvent;
import com.fanruan.portal.authority.PortalAuthorityItems;
import com.fanruan.portal.module.PortalModule;
import com.fanruan.portal.module.PortalModuleManager;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.third.guava.collect.Sets;
@ -94,14 +97,17 @@ public class DesignServerSupportModule {
* 启动入口重建一下展示的module
*/
public static void rebuild() {
Carina.getApplicationContext().addListener(new ContextListener() {
EventDispatcher.listen(CarinaLifecycleEvent.AFTER_START, new Listener() {
@Override
public void onStart() {
public void on(Event event, Object o) {
FineLoggerFactory.getLogger().info("start unregister module for embed design server");
PortalModuleManager.allModules().values().stream()
.filter(m -> !StringUtils.equals(m.getParentID(), PortalAuthorityItems.PORTAL_ROOT_ID))
.map(PortalModule::getId)
.filter(m -> !SUPPORT_MODULE.contains(m))
.forEach(PortalModuleManager::unregister);
FineLoggerFactory.getLogger().info("unregister module for embed design server done");
}
});
}

44
designer-realize/src/main/java/com/fanruan/boot/adaptation/ReportAdaptationComponent.java

@ -4,6 +4,7 @@ import com.fanruan.carina.Carina;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.Start;
import com.fanruan.carina.context.ContextListener;
import com.fanruan.plugins.resource.PluginResourceHelper;
import com.fanruan.portal.FinePortal;
import com.fanruan.portal.module.PortalModule;
@ -12,9 +13,9 @@ import com.fr.decision.ExtraDecisionClassManager;
import com.fr.decision.base.VirtualFilterChain;
import com.fr.decision.fun.EmbedRequestFilterProvider;
import com.fr.decision.fun.GlobalRequestFilterProvider;
import com.fr.decision.fun.PluginPortalModuleDevice;
import com.fr.decision.fun.SystemOptionProvider;
import com.fr.decision.plugin.PluginControllerManager;
import com.fr.decision.portal.PluginPortalModuleDevice;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
@ -23,7 +24,6 @@ import com.fr.general.InterProviderImpl;
import com.fr.locale.InterMutableKey;
import com.fr.locale.LocaleMarker;
import com.fr.locale.LocaleScope;
import com.fr.plugin.ExtraClassManager;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.injectable.PluginModule;
import com.fr.plugin.observer.PluginEventType;
@ -167,25 +167,31 @@ public class ReportAdaptationComponent {
}
private void registerPluginModules() {
// 注册插件模块
try {
Set<SystemOptionProvider> systemOptionProviders = ExtraClassManager.getInstance().getArray(SystemOptionProvider.XML_TAG);
if (!CollectionUtils.isEmpty(systemOptionProviders)) {
// 资源引入采用新的方式,WebCoalition接口不再继承使用,这里只处理模块注册
for (SystemOptionProvider optionProvider : systemOptionProviders) {
PortalModule portalModule = PortalModule.create(optionProvider.id(), optionProvider.displayName())
.sortIndex(optionProvider.sortIndex())
.dynamicControl(m -> new PluginPortalModuleDevice(optionProvider.parentId(), m));
FinePortal.registerModule(optionProvider.parentId(), portalModule);
// 插件资源注册
PluginResourceHelper.getInstance().registerAtom2Portal(optionProvider);
Carina.getApplicationContext().addListener(new ContextListener() {
@Override
public void onStart() {
// 注册插件模块
try {
Set<SystemOptionProvider> systemOptionProviders = ExtraDecisionClassManager.getInstance().getArray(SystemOptionProvider.XML_TAG);
if (!CollectionUtils.isEmpty(systemOptionProviders)) {
// 资源引入采用新的方式,WebCoalition接口不再继承使用,这里只处理模块注册
for (SystemOptionProvider optionProvider : systemOptionProviders) {
PortalModule portalModule = PortalModule.create(optionProvider.id(), optionProvider.displayName())
.sortIndex(optionProvider.sortIndex())
.dynamicControl(m -> new PluginPortalModuleDevice(optionProvider.parentId(), m));
FinePortal.registerModule(optionProvider.parentId(), portalModule);
// 插件资源注册
PluginResourceHelper.getInstance().registerAtom2Portal(optionProvider);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
private void checkI18n() {
for (LocaleMarker marker : Carina.getApplicationContext().group(InterMutableKey.class).getAll()) {

42
designer-realize/src/main/java/com/fanruan/boot/env/DesignCorePluginComponent.java vendored

@ -1,42 +0,0 @@
package com.fanruan.boot.env;
import com.fanruan.boot.CorePluginComponent;
import com.fanruan.carina.Carina;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.Start;
import com.fanruan.carina.annotions.Supplemental;
import com.fanruan.plugin.autonomy.AutonomyClassManagerGroup;
import com.fanruan.plugin.autonomy.AutonomyClassManagerProvider;
import com.fr.plugin.ExtraClassManager;
/**
* DesignCorePluginComponent
*
* @author Destiny.Lin
* @since 11.0
* Created on 2024/8/9
*/
@FineComponent(name = "design_plugin_core")
@DependsOn(dependencies = {"design_plugin"})
public class DesignCorePluginComponent extends CorePluginComponent {
/**
* prepare
*/
@Supplemental
public void supportFunctionDef() {
super.supportFunctionDef();
}
/**
* start
*/
@Start
public void start() {
/// 插件下沉不能直接调用fbp的逻辑,此时内置服务器未启动,一部分逻辑要拆到内置服务器启动的时候再做
// super.start();
}
}

2
designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvComponent.java vendored

@ -250,7 +250,7 @@ public class DesignEnvComponent {
// 获取本地的日志级别配置
Level localLogPreferLevel = Log4jConfig.getInstance().getRootLevel();
// 刷新到本地配置
Log4jConfigFactory.getInstance().setRootLevel(localLogPreferLevel);
Log4jConfigFactory.getInstance().updateConfigLoggerLevel(localLogPreferLevel.name());
URI uri = Log4jUtils.buildUserConfigURI(StringUtils.EMPTY);
FRLogger.getLogger().config(uri);
// 刷新到carina的配置,防止 portal service 启动的时候覆盖了

109
designer-realize/src/main/java/com/fanruan/boot/env/DesignPluginComponent.java vendored

@ -7,15 +7,39 @@ import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.Start;
import com.fanruan.carina.annotions.Stop;
import com.fanruan.carina.annotions.Supplemental;
import com.fanruan.plugin.autonomy.AutonomyClassManagerFactory;
import com.fanruan.plugin.autonomy.AutonomyClassManagerGroup;
import com.fanruan.plugin.autonomy.AutonomyClassManagerProvider;
import com.fr.config.ConfigContext;
import com.fr.invoke.ClassFactory;
import com.fr.json.JSONObject;
import com.fr.plugin.ExtraClassManager;
import com.fr.plugin.beforeload.embed.PluginEmbedInfo;
import com.fr.plugin.config.PluginConfigContext;
import com.fr.plugin.injectable.LevelChecker;
import com.fr.plugin.db.PluginDBManager;
import com.fr.plugin.injectable.PluginInjectionFilter;
import com.fr.plugin.injectable.PluginInjectionValidator;
import com.fr.plugin.injectable.SpecialLevel;
import com.fr.plugin.manage.PluginManager;
import com.fr.plugin.manage.PluginSyncModuleType;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.plugin.observer.PluginListenerRegistration;
import com.fr.plugin.validate.PluginValidator;
import com.fr.stable.CommonUtils;
import com.fr.stable.fun.Level;
import com.fr.stable.project.ProjectConstants;
import com.fr.stable.resource.ResourceLoader;
import com.fr.startup.web.annotation.MappingJackson2HttpMessageConverter;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.repository.plugin.PluginRepository;
import javax.servlet.ServletContext;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
@ -27,7 +51,7 @@ import java.util.function.Supplier;
* Created on 2024/5/17
*/
@FineComponent(name = "design_plugin")
@DependsOn(dependencies = {"design_env_prepare"})
@DependsOn(dependencies = {"design_version"})
public class DesignPluginComponent extends PluginComponent {
@ -43,13 +67,50 @@ public class DesignPluginComponent extends PluginComponent {
*/
@Start
public void start() {
ExtraClassManager.getInstance().registerAutonomyClassManager(Carina.getApplicationContext().group(AutonomyClassManagerGroup.class).getAll().toArray(new AutonomyClassManagerProvider[0]));
//收集插件对象的过滤器
Collection<PluginInjectionFilter> filters = Carina.getApplicationContext().group(PluginInjectionFilter.GroupKey.class).getAll();
for (PluginInjectionFilter filter: filters) {
PluginManager.addInjectionFilter(filter);
}
//装备外部的验证器
assembleValidator();
// 注册内置插件信息
registerEmbedPluginInfo();
// 注册插件配置类Provider
registerPluginConfigProvider();
PluginInjectionValidator.setLevelChecker(new LevelChecker() {
@Override
public boolean isStandard(String name) {
//不在特殊表中的Level
return SpecialLevel.convert(name) == null;
}
@Override
public boolean validateSpecificLevel(String name, Level injectionObject) {
SpecialLevel specialLevel = SpecialLevel.convert(name);
return specialLevel == null || specialLevel.getCurrentLevel() <= injectionObject.currentAPILevel();
}
});
AutonomyClassManagerFactory.getInstance().registerAutonomyClassManager(Carina.getApplicationContext().group(AutonomyClassManagerGroup.class).getAll().toArray(new AutonomyClassManagerProvider[0]));
Supplier<List<JSONObject>> supplier = () -> PluginRepository.getInstance().getPluginStatus();
PluginManager.registerRemotePluginSupplier(supplier);
PluginManager.setSyncModuleType(PluginSyncModuleType.DESIGN);
//PluginManager要在环境切换和模块启动之前初始化
PluginManager.startEngine();
super.start();
PluginListenerRegistration.getInstance().listenRunningChanged(new PluginEventListener() {
@Override
public void on(PluginEvent event) {
MappingJackson2HttpMessageConverter.KEY.refreshObjectMapper();
}
});
registerPluginClassFinder();
PluginDBManager.getInstance().init();
}
@Override
@ -57,11 +118,51 @@ public class DesignPluginComponent extends PluginComponent {
// do nothing
}
private void registerEmbedPluginInfo() {
Collection<PluginEmbedInfo> pluginEmbedInfos = Carina.getApplicationContext().group(PluginEmbedInfo.class).getAll();
PluginManager.getPluginEmbedManager().addPluginEmbedInfos(pluginEmbedInfos);
}
private void registerPluginConfigProvider() {
ConfigContext.setPluginConfigContextProvider(new PluginConfigContext());
}
private void assembleValidator() {
PluginManager.getValidatorManager().register(Carina.getApplicationContext().group(PluginValidator.GroupKey.class).getAll());
}
private void registerPluginClassFinder() {
ClassFactory.getInstance().addFinder(className -> {
//再找.
// alex:currentEnv可能是null
String envPath = WorkContext.getCurrent().getPath();
if (envPath == null) {
throw new ClassNotFoundException(className);
}
File clssesFile = new File(CommonUtils.pathJoin(envPath, ProjectConstants.CLASSES_NAME));
ClassLoader urlClassLoader;
try {
urlClassLoader = new URLClassLoader(new URL[]{clssesFile.toURI().toURL()}, CommonUtils.class.getClassLoader());
} catch (MalformedURLException malformedURLException) {
urlClassLoader = ClassLoader.getSystemClassLoader();
}
return Class.forName(className, true, urlClassLoader);
});
//从插件中拿
ClassFactory.getInstance().addFinder(ResourceLoader::classForName);
//从插件引擎中拿
ClassFactory.getInstance().addFinder(className -> Class.forName(className, true, PluginManager.getController().getClass().getClassLoader()));
}
/**
* stop
*/
@Stop
public void stop() {
super.stop();
PluginDBManager.getInstance().destroy();
}
}

31
designer-realize/src/main/java/com/fanruan/boot/env/DesignVersionComponent.java vendored

@ -0,0 +1,31 @@
package com.fanruan.boot.env;
import com.fanruan.boot.VersionComponent;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.Start;
import com.fanruan.version.ServiceVersion;
import com.fanruan.version.VersionCenter;
import com.fanruan.version.VersionConstants;
/**
* 设计器版本模块
*
* @author Leo.Qin
* @since 11.0
* Created on 2024/11/11
*/
@FineComponent(name = "design_version")
@DependsOn(dependencies = {"design_env_prepare"})
public class DesignVersionComponent extends VersionComponent {
@Start
@Override
public void start() {
super.start();
ServiceVersion serviceVersion = VersionCenter.getInstance().getServiceVersion();
serviceVersion.setName(VersionConstants.SERVICE_NAME_FR);
VersionCenter.getInstance().register(serviceVersion);
}
}

12
designer-realize/src/main/java/com/fanruan/boot/env/function/DesignComponent.java vendored

@ -17,15 +17,12 @@ import com.fr.base.process.ProcessOperator;
import com.fr.base.theme.migrator.FormThemeConfigMigrator;
import com.fr.base.theme.migrator.ReportThemeConfigMigrator;
import com.fr.chart.chartattr.ChartCollection;
import com.fr.config.ServerPreferenceConfig;
import com.fr.data.core.db.dml.Update;
import com.fr.decision.update.backup.RecoverManager;
import com.fr.decision.webservice.v10.plugin.helper.category.impl.PluginResourceLoader;
import com.fr.decision.webservice.v10.plugin.helper.category.impl.UpmResourceLoader;
import com.fr.design.DesignerEnvManager;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.RPCConnectHandlerCenter;
import com.fr.design.actions.NewFormAction;
import com.fr.design.actions.UpdateAction;
import com.fr.design.actions.core.ActionFactory;
import com.fr.design.actions.insert.cell.BiasCellAction;
@ -128,7 +125,6 @@ import com.fr.quickeditor.cellquick.CellImageQuickEditor;
import com.fr.quickeditor.cellquick.CellRichTextEditor;
import com.fr.quickeditor.cellquick.CellStringQuickEditor;
import com.fr.quickeditor.cellquick.CellSubReportEditor;
import com.fr.quickeditor.chartquick.BasicChartQuickEditor;
import com.fr.quickeditor.chartquick.FloatChartQuickEditor;
import com.fr.quickeditor.floatquick.FloatImageQuickEditor;
import com.fr.quickeditor.floatquick.FloatStringQuickEditor;
@ -141,7 +137,6 @@ import com.fr.report.cell.painter.CellImagePainter;
import com.fr.stable.ArrayUtils;
import com.fr.stable.ParameterProvider;
import com.fr.stable.bridge.StableFactory;
import com.fr.stable.os.support.OSBasedAction;
import com.fr.stable.os.support.OSSupportCenter;
import com.fr.stable.plugin.ExtraDesignClassManagerProvider;
import com.fr.stable.script.CalculatorProviderContext;
@ -149,7 +144,6 @@ import com.fr.stable.script.ValueConverter;
import com.fr.stable.xml.ObjectTokenizer;
import com.fr.stable.xml.ObjectXMLWriterFinder;
import com.fr.start.BBSGuestPaneProvider;
import com.fr.start.common.DesignerStartupExecutor;
import com.fr.start.common.DesignerStartupPool;
import com.fr.task.Once;
import com.fr.workspace.WorkContext;
@ -198,8 +192,10 @@ public class DesignComponent {
}
}
CompletableFuture<Void> themeConfigPrepare = CompletableFuture.runAsync(() -> {
FormThemeConfigMigrator.getInstance().upgrade();
ReportThemeConfigMigrator.getInstance().upgrade();
if (WorkContext.getCurrent().isLocal()) {
FormThemeConfigMigrator.getInstance().upgrade();
ReportThemeConfigMigrator.getInstance().upgrade();
}
}, DesignerStartupPool.common());
CompletableFuture<Void> mainDesignerPrepare = CompletableFuture.runAsync(this::designerModuleStart, DesignerStartupPool.common());
CompletableFuture<Void> extendDesignerPrepare = CompletableFuture.runAsync(this::designerExtendStart, DesignerStartupPool.common());

2
designer-realize/src/main/java/com/fanruan/boot/env/function/DesignDatasourceComponent.java vendored

@ -39,7 +39,6 @@ import com.fr.decision.webservice.v10.datasource.connection.processor.impl.Conne
import com.fr.decision.webservice.v10.datasource.connection.processor.impl.ConnectionProcessorFactory;
import com.fr.decision.webservice.v10.datasource.connection.processor.impl.JDBCConnectionProcessor;
import com.fr.decision.webservice.v10.datasource.connection.processor.impl.JDYConnectionProcessor;
import com.fr.decision.webservice.v10.datasource.connection.processor.impl.JNDIConnectionProcessor;
import com.fr.decision.webservice.v10.datasource.dataset.processor.impl.DataSetProcessorFactory;
import com.fr.design.data.datapane.connect.LocalConnectionSource;
import com.fr.design.data.tabledata.LocalTableDataSource;
@ -113,7 +112,6 @@ public class DesignDatasourceComponent extends DatasourceComponent {
*/
private void initConnectionProcessor() {
ConnectionProcessorFactory.register(JDBCConnectionProcessor.KEY);
ConnectionProcessorFactory.register(JNDIConnectionProcessor.KEY);
ConnectionProcessorFactory.register(ConnectionPluginProcessor.KEY);
ConnectionProcessorFactory.register(JDYConnectionProcessor.KEY);
ConnectionProcessorFactory.register(new KafkaConnectionProcessor());

2
designer-realize/src/main/java/com/fanruan/boot/env/function/DesignUpdateComponent.java vendored

@ -38,7 +38,7 @@ import java.util.List;
* Created on 2024/7/2
*/
@FineComponent(name = "design_function_update")
@DependsOn(dependencies = "design_plugin_core")
@DependsOn(dependencies = "design_plugin")
public class DesignUpdateComponent {
/**

3
designer-realize/src/main/java/com/fanruan/boot/init/DesignPreLoadComponent.java

@ -1,6 +1,5 @@
package com.fanruan.boot.init;
import com.fanruan.boot.ClassFindComponent;
import com.fanruan.boot.ExtraLocaleClassManager;
import com.fanruan.boot.key.StartupArgsShell;
import com.fanruan.carina.Carina;
@ -205,7 +204,7 @@ public class DesignPreLoadComponent {
ProjectConstants.CLASSES_NAME));
ClassLoader urlClassLoader;
try {
urlClassLoader = new URLClassLoader(new URL[]{clssesFile.toURI().toURL()}, ClassFindComponent.class.getClassLoader());
urlClassLoader = new URLClassLoader(new URL[]{clssesFile.toURI().toURL()}, DesignPreLoadComponent.class.getClassLoader());
} catch (MalformedURLException malformedURLException) {
urlClassLoader = ClassLoader.getSystemClassLoader();
}

2
designer-realize/src/main/java/com/fanruan/boot/init/DesignWorkContextComponent.java

@ -15,6 +15,7 @@ import com.fanruan.workplace.http.RepositoryManager;
import com.fanruan.workplace.http.WorkspaceHeartBeatShell;
import com.fanruan.workplace.http.exception.DefaultRemoteExceptionHandler;
import com.fanruan.workplace.http.exception.RemoteExceptionConvert;
import com.fanruan.workplace.http.exception.RemoteServiceErrorExceptionHandler;
import com.fanruan.workplace.network.RemoteNetworkRepository;
import com.fanruan.workplace.standard.ServerInfo;
import com.fanruan.workplace.standard.ServerInfoOperator;
@ -162,6 +163,7 @@ public class DesignWorkContextComponent {
RemoteExceptionConvert.registerException(HttpConstants.LOGIN_LOCK, new RemoteDesignLoginLockHandler());
RemoteExceptionConvert.registerException(HttpConstants.TPL_HAS_BEAN_UNLOCK, new UnLockedHandler());
RemoteExceptionConvert.registerException(HttpConstants.DRIVER_NOT_EXIST, new RemoteDriverUnExistHandler());
RemoteExceptionConvert.registerException(HttpConstants.SERVICE_ERROR, new RemoteServiceErrorExceptionHandler());
DefaultRemoteExceptionHandler.getInstance().registerMatchMsg(ERROR_CODE, new RemoteProcedureErrorHandler());
}

2
designer-realize/src/main/java/com/fr/design/dscolumn/SelectedDataColumnPane.java

@ -324,7 +324,7 @@ public class SelectedDataColumnPane extends BasicPane {
protected void initTableNameComboBox() {
tableNameComboBox = new TableDataComboBox(DesignTableDataManager.getEditingTableDataSource());
tableNameComboBox = new TableDataComboBox();
}
@Override

12
designer-realize/src/main/java/com/fr/start/CarinaDesigner.java

@ -6,12 +6,10 @@ import com.fanruan.carina.Carina;
import com.fanruan.carina.context.CarinaApplicationContext;
import com.fanruan.carina.standard.PartitionManager;
import com.fanruan.carina.standard.PartitionManagerImpl;
import com.fanruan.gui.UiInspector;
import com.fr.base.StateHubContext;
import com.fr.design.backup.DesignContext;
import com.fr.design.carton.SwitchForSwingChecker;
import com.fr.design.carton.latency.DesignerLatencyMetric;
import com.fr.design.mainframe.DesignerUIModeConfig;
import com.fr.log.FineLoggerFactory;
import com.fr.runtime.FineRuntime;
import com.fr.start.common.DesignerStartupContext;
@ -39,7 +37,6 @@ public class CarinaDesigner extends MainDesigner{
* main
*/
public static void main(String[] args) {
installUIDevModeTools();
DesignerStartupContext.getRecorder().start();
PartitionManager manager = new PartitionManagerImpl();
StateHubContext.setReady(false);
@ -68,13 +65,4 @@ public class CarinaDesigner extends MainDesigner{
DesignerLatencyMetric.getInstance().start();
}
/**
* 进入UI开发者模式
*/
private static void installUIDevModeTools() {
if (DesignerUIModeConfig.getInstance().isUIDevMode()) {
new UiInspector();
}
}
}

2
designer-realize/src/main/java/com/fr/start/Designer.java

@ -49,6 +49,6 @@ public class Designer {
* @param args 参数
*/
private static void runNonGuardianDesigner(String[] args) {
MainDesigner.main(args);
//MainDesigner.main(args);
}
}

2
designer-realize/src/main/java/com/fr/start/Designer4Debug.java

@ -6,6 +6,6 @@ package com.fr.start;
public class Designer4Debug {
public static void main(String... args) {
org.swingexplorer.Launcher.main(new String[]{"com.fr.start.MainDesigner"});
//org.swingexplorer.Launcher.main(new String[]{"com.fr.start.MainDesigner"});
}
}

21
designer-realize/src/main/java/com/fr/start/MainDesigner.java

@ -2,6 +2,7 @@ package com.fr.start;
import com.fanruan.gui.UiInspector;
import com.fanruan.product.ProductConstants;
import com.fine.theme.icon.LazyIcon;
import com.fr.base.function.UITerminator;
import com.fr.base.vcs.DesignerMode;
@ -13,10 +14,7 @@ import com.fr.design.actions.server.ServerConfigManagerAction;
import com.fr.design.actions.server.TemplateThemeManagerAction;
import com.fr.design.actions.server.WidgetManagerAction;
import com.fr.design.base.mode.DesignModeContext;
import com.fr.design.carton.latency.DesignerLatencyMetric;
import com.fr.design.carton.SwitchForSwingChecker;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.design.deeplink.DeepLinkManager;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.file.MultiTemplateTabPane;
@ -48,7 +46,6 @@ import com.fr.design.menu.ShortCut;
import com.fr.design.module.ChartEmptyDataStyleAction;
import com.fr.design.module.ChartPreStyleAction;
import com.fr.design.module.DesignModuleFactory;
import com.fr.design.monitor.DesignerLifecycleMonitorContext;
import com.fr.design.notification.ui.NotificationCenterPane;
import com.fr.design.share.SharableManager;
import com.fr.design.ui.util.UIUtil;
@ -56,26 +53,14 @@ import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.DesignerPort;
import com.fr.design.utils.concurrent.ThreadFactoryBuilder;
import com.fr.env.utils.DesignerInteractionHistory;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.log.SystemOutLoggerProvider;
import com.fr.module.Module;
import com.fr.module.ModuleContext;
import com.fr.module.engine.event.LifecycleErrorEvent;
import com.fr.runtime.FineRuntime;
import com.fanruan.product.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.lifecycle.FineLifecycleFatalError;
import com.fr.stable.xml.XMLTools;
import com.fr.start.common.DesignerStartupContext;
import com.fr.start.common.SplashCommon;
import com.fr.start.module.StartupArgs;
import com.fr.start.preload.PreLoadService;
import com.fr.start.server.ServerTray;
import com.fr.van.chart.map.server.ChartMapEditorAction;
import com.fr.workspace.WorkContext;
@ -115,7 +100,7 @@ public class MainDesigner extends BaseDesigner {
*
* @param args 参数
*/
public static void main(String[] args) {
/* public static void main(String[] args) {
DesignerStartupContext.getRecorder().start();
// 设置一下默认的logger,启动后再Reset
FineLoggerFactory.setLogger(SystemOutLoggerProvider.getInstance());
@ -162,7 +147,7 @@ public class MainDesigner extends BaseDesigner {
DesignerLatencyMetric.getInstance().start();
installUIDevModeTools();
}
}*/
/**
* 进入UI开发者模式

591
designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java

@ -1,591 +0,0 @@
package com.fr.start.module;
import com.fanruan.carina.Carina;
import com.fanruan.config.bbs.FineBBSConfigProvider;
import com.fine.theme.icon.LazyIcon;
import com.fr.base.BaseFormula;
import com.fr.base.Formula;
import com.fr.base.MultiFieldParameter;
import com.fr.base.OptimizeUtil;
import com.fr.base.password.FinePassportListenerAdapter;
import com.fr.base.password.FinePassportManager;
import com.fr.base.process.ProcessOperator;
import com.fr.base.theme.migrator.FormThemeConfigMigrator;
import com.fr.base.theme.migrator.ReportThemeConfigMigrator;
import com.fr.chart.chartattr.ChartCollection;
import com.fr.config.ServerPreferenceConfig;
import com.fr.decision.update.backup.RecoverManager;
import com.fr.decision.webservice.v10.plugin.helper.category.impl.PluginResourceLoader;
import com.fr.decision.webservice.v10.plugin.helper.category.impl.UpmResourceLoader;
import com.fr.design.DesignerEnvManager;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.RPCConnectHandlerCenter;
import com.fr.design.actions.NewFormAction;
import com.fr.design.actions.UpdateAction;
import com.fr.design.actions.core.ActionFactory;
import com.fr.design.actions.insert.cell.BiasCellAction;
import com.fr.design.actions.insert.cell.ChartCellAction;
import com.fr.design.actions.insert.cell.DSColumnCellAction;
import com.fr.design.actions.insert.cell.FormulaCellAction;
import com.fr.design.actions.insert.cell.GeneralCellAction;
import com.fr.design.actions.insert.cell.ImageCellAction;
import com.fr.design.actions.insert.cell.RichTextCellAction;
import com.fr.design.actions.insert.cell.SubReportCellAction;
import com.fr.design.actions.insert.flot.ChartFloatAction;
import com.fr.design.actions.insert.flot.FormulaFloatAction;
import com.fr.design.actions.insert.flot.ImageFloatAction;
import com.fr.design.actions.insert.flot.TextBoxFloatAction;
import com.fr.design.actions.replace.ITReplaceAction;
import com.fr.design.actions.replace.utils.ReplaceOperator;
import com.fr.design.bridge.DesignToolbarProvider;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.design.env.DesignerWorkspaceLoader;
import com.fr.design.fit.NewJForm;
import com.fr.design.fit.common.TemplateTool;
import com.fr.design.form.parameter.FormParaDesigner;
import com.fr.design.fun.ElementUIProvider;
import com.fr.design.gui.controlpane.NameObjectCreator;
import com.fr.design.gui.controlpane.NameableCreator;
import com.fr.design.gui.frpane.HyperlinkGroupPaneActionProvider;
import com.fr.design.hyperlink.ReportletHyperlinkPane;
import com.fr.design.hyperlink.WebHyperlinkPane;
import com.fr.design.hyperlink.popup.MobilePopupPane;
import com.fr.design.i18n.DesignI18nImpl;
import com.fr.design.javascript.EmailPane;
import com.fr.design.javascript.JavaScriptImplPane;
import com.fr.design.javascript.ParameterJavaScriptPane;
import com.fr.design.javascript.ProcessTransitionAdapter;
import com.fr.design.lock.TemplateLockInfoReSave;
import com.fr.design.login.DesignerLoginType;
import com.fr.design.login.guide.DesignerGuideHelper;
import com.fr.design.login.message.DesignerMessageHelper;
import com.fr.design.login.socketio.LoginAuthServer;
import com.fr.design.mainframe.BaseJForm;
import com.fr.design.mainframe.FormHierarchyTreePane;
import com.fr.design.mainframe.HyperlinkGroupPaneActionImpl;
import com.fr.design.mainframe.InformationCollector;
import com.fr.design.mainframe.JTemplateEvent;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.design.mainframe.WidgetToolBarPane;
import com.fr.design.mainframe.alphafine.AlphaFineHelper;
import com.fr.design.mainframe.alphafine.question.QuestionWindow;
import com.fr.design.mainframe.alphafine.search.manager.impl.ProductNewsSearchManager;
import com.fr.design.mainframe.bbs.BBSGuestPane;
import com.fr.design.mainframe.bbs.UserInfoPane;
import com.fr.design.mainframe.form.FormECCompositeProvider;
import com.fr.design.mainframe.form.FormECDesignerProvider;
import com.fr.design.mainframe.form.FormElementCaseDesigner;
import com.fr.design.mainframe.form.FormReportComponentComposite;
import com.fr.design.mainframe.guide.GuideRegister;
import com.fr.design.mainframe.loghandler.DesignerLogAppender;
import com.fr.design.mainframe.share.constants.ShareEntryKey;
import com.fr.design.mainframe.socketio.DesignerSocketIO;
import com.fr.design.mod.ContentReplacerCenter;
import com.fr.design.module.DesignModuleFactory;
import com.fr.design.os.impl.SupportOSImpl;
import com.fr.design.parameter.FormParameterReader;
import com.fr.design.parameter.ParameterPropertyPane;
import com.fr.design.parameter.WorkBookParameterReader;
import com.fr.design.share.SharableManager;
import com.fr.design.share.ui.config.ShareConfigPane;
import com.fr.design.share.ui.generate.ShareGeneratePane;
import com.fr.design.update.actions.RecoverForDesigner;
import com.fr.design.update.push.DesignerPushUpdateManager;
import com.fr.design.widget.ui.btn.FormSubmitButtonDetailPane;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.general.GeneralContext;
import com.fr.general.xml.GeneralXMLTools;
import com.fr.js.EmailJavaScript;
import com.fr.js.JavaScriptImpl;
import com.fr.js.MobilePopupHyperlink;
import com.fr.js.ParameterJavaScript;
import com.fr.js.ReportletHyperlink;
import com.fr.js.WebHyperlink;
import com.fr.locale.InterMutableKey;
import com.fr.locale.LocaleMarker;
import com.fr.locale.LocaleScope;
import com.fr.log.FineLoggerFactory;
import com.fr.log.LogHandler;
import com.fr.module.Activator;
import com.fr.module.extension.Prepare;
import com.fr.plugin.beforeload.embed.DefaultPluginEmbedInfo;
import com.fr.plugin.beforeload.embed.PluginEmbedInfo;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.injectable.PluginModule;
import com.fr.plugin.manage.PluginFilter;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.quickeditor.cellquick.CellBiasTextPainterEditor;
import com.fr.quickeditor.cellquick.CellDSColumnEditor;
import com.fr.quickeditor.cellquick.CellFormulaQuickEditor;
import com.fr.quickeditor.cellquick.CellImageQuickEditor;
import com.fr.quickeditor.cellquick.CellRichTextEditor;
import com.fr.quickeditor.cellquick.CellStringQuickEditor;
import com.fr.quickeditor.cellquick.CellSubReportEditor;
import com.fr.quickeditor.chartquick.BasicChartQuickEditor;
import com.fr.quickeditor.chartquick.FloatChartQuickEditor;
import com.fr.quickeditor.floatquick.FloatImageQuickEditor;
import com.fr.quickeditor.floatquick.FloatStringQuickEditor;
import com.fr.report.cell.CellElementValueConverter;
import com.fr.report.cell.cellattr.core.RichText;
import com.fr.report.cell.cellattr.core.SubReport;
import com.fr.report.cell.cellattr.core.group.DSColumn;
import com.fr.report.cell.painter.BiasTextPainter;
import com.fr.report.cell.painter.CellImagePainter;
import com.fr.stable.ParameterProvider;
import com.fr.stable.bridge.StableFactory;
import com.fr.stable.os.support.OSBasedAction;
import com.fr.stable.os.support.OSSupportCenter;
import com.fr.stable.plugin.ExtraDesignClassManagerProvider;
import com.fr.stable.script.CalculatorProviderContext;
import com.fr.stable.script.ValueConverter;
import com.fr.stable.xml.ObjectTokenizer;
import com.fr.stable.xml.ObjectXMLWriterFinder;
import com.fr.start.BBSGuestPaneProvider;
import com.fr.start.common.DesignerStartupExecutor;
import com.fr.start.common.DesignerStartupPool;
import com.fr.strongest.WidgetThemeListenerStarter;
import com.fr.task.Once;
import com.fr.workspace.WorkContext;
import com.fr.xml.ReportXMLUtils;
import javax.swing.SwingWorker;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
/**
* Created by juhaoyu on 2018/1/31.
* 触发原来的DesignerModule的启动
* 之后慢慢将DesignerModule拆成Activator
*/
public class DesignerActivator extends Activator implements Prepare {
private LogHandler<DesignerLogAppender> logHandler = null;
private static final String PLUGIN_EXPORT_IMAGE_SETTING = "com.fr.plugin.exportimagesettings.v11";
private final Once pushUpdateTask = new Once(new Runnable() {
@Override
public void run() {
DesignerPushUpdateManager.getInstance().preparePushUpdate();
DesignerGuideHelper.prepareShowGuideDialog();
DesignerMessageHelper.getInstance().prepareShowMessage();
}
});
private boolean hasUpdated = false;
@Override
public void start() {
List<LocaleMarker> markers = findMutable(InterMutableKey.Path);
for (LocaleMarker marker : markers) {
if (marker.match(LocaleScope.DESIGN)) {
DesignI18nImpl.getInstance().addResource(marker.getPath());
}
}
CompletableFuture<Void> themeConfigPrepare = CompletableFuture.runAsync(() -> {
if (WorkContext.getCurrent().isLocal()) {
FormThemeConfigMigrator.getInstance().upgrade();
ReportThemeConfigMigrator.getInstance().upgrade();
}
}, DesignerStartupPool.common());
CompletableFuture<Void> mainDesignerPrepare = CompletableFuture.runAsync(this::designerModuleStart, DesignerStartupPool.common());
CompletableFuture<Void> extendDesignerPrepare = CompletableFuture.runAsync(this::designerExtendStart, DesignerStartupPool.common());
CompletableFuture<Void> otherFeaturesPrepare = CompletableFuture.runAsync(() -> {
startBBSLoginAuthServer();
migrateBBSInfoFromFineDB();
OSSupportCenter.buildAction(new OSBasedAction() {
@Override
public void execute(Object... objects) {
UserInfoPane.getInstance().updateBBSUserInfo();
}
}, SupportOSImpl.BBS_USER_LOGIN_PANE);
loadLogAppender();
//DesignerSocketIO.update();
DesignerWorkspaceLoader.init();
storePassport();
AlphaFineHelper.switchConfig4Locale();
RecoverManager.register(new RecoverForDesigner());
WidgetThemeListenerStarter.start();
TemplateLockInfoReSave.startListener();
RPCConnectHandlerCenter.startListener();
}, DesignerStartupPool.common());
CompletableFuture<Void> resourcePrepare = CompletableFuture.runAsync(() -> {
pushUpdateTask.run();
if (WorkContext.getCurrent().isLocal()) {
PluginResourceLoader.INSTANCE.checkOldShopFile();
UpmResourceLoader.INSTANCE.checkOldShopFile();
}
}, DesignerStartupPool.common());
CompletableFuture
.allOf(mainDesignerPrepare, extendDesignerPrepare, themeConfigPrepare, otherFeaturesPrepare, resourcePrepare)
.join();
}
@Override
public void afterAllStart() {
DesignerStartupExecutor.getInstance().execute(() -> DesignerLaunchStatus.setStatus(DesignerLaunchStatus.DESIGNER_INIT_COMPLETE));
//生成BasicChartQuickEditor对象,需要用到ChartDesignerActivator的注册信息(DesignModuleFactory.registerChartPropertyPaneClass(ChartPropertyPane.class);)
//所以不能在registerCellEditor函数中进行注册
ActionFactory.registerCellEditor(ChartCollection.class, new BasicChartQuickEditor());
if (DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter() && WorkContext.getCurrent().isLocal()) {
ServerPreferenceConfig.getInstance().setUseOptimizedUPM(DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter());
}
}
private void loadLogAppender() {
logHandler = new LogHandler<DesignerLogAppender>() {
final DesignerLogAppender logAppender = DesignerLogAppender.createDesignerLogAppender();
@Override
public DesignerLogAppender getHandler() {
return logAppender;
}
};
logHandler.getHandler().start();
FineLoggerFactory.getLogger().addLogAppender(logHandler);
}
private void unloadLogAppender() {
if (logHandler != null) {
logHandler.getHandler().stop();
FineLoggerFactory.getLogger().removeLogAppender(logHandler);
}
}
private void designerModuleStart() {
StableFactory.registerMarkedClass(ExtraDesignClassManagerProvider.XML_TAG, ExtraDesignClassManager.class);
ActionFactory.registerCellInsertActionClass(actionsForInsertCellElement());
ActionFactory.registerFloatInsertActionClass(actionsForInsertFloatElement());
DesignModuleFactory.registerCreators4Hyperlink(hyperlinkTypes());
createPluginListener();
justStartModules4Designer();
CalculatorProviderContext.setValueConverter(valueConverter());
GeneralXMLTools.Object_Tokenizer = startXMLReadObjectTokenizer();
GeneralXMLTools.Object_XML_Writer_Finder = startObjectXMLWriterFinder();
addAdapterForPlate();
designerRegister();
}
private void designerExtendStart() {
SharableManager.start();
InformationCollector.getInstance().collectStartTime();
GuideRegister.register();
}
private void createPluginListener() {
GeneralContext.listenPluginRunningChanged(new PluginEventListener() {
@Override
public void on(PluginEvent event) {
ActionFactory.referCellInsertActionClass(actionsForInsertCellElement());
ActionFactory.referFloatInsertActionClass(actionsForInsertFloatElement());
}
}, new PluginFilter() {
@Override
public boolean accept(PluginContext context) {
return context.contain(PluginModule.ExtraDesign, ElementUIProvider.MARK_STRING);
}
});
}
private static Class<? extends UpdateAction>[] actionsForInsertCellElement() {
List<Class<?>> classes = new ArrayList<>();
classes.add(DSColumnCellAction.class);
classes.add(GeneralCellAction.class);
classes.add(RichTextCellAction.class);
classes.add(FormulaCellAction.class);
classes.add(ChartCellAction.class);
classes.add(ImageCellAction.class);
classes.add(BiasCellAction.class);
classes.add(SubReportCellAction.class);
Set<ElementUIProvider> providers = ExtraDesignClassManager.getInstance().getArray(ElementUIProvider.MARK_STRING);
for (ElementUIProvider provider : providers) {
classes.add(provider.actionForInsertCellElement());
}
return classes.toArray(new Class[0]);
}
private static Class<? extends UpdateAction>[] actionsForInsertFloatElement() {
List<Class<? extends UpdateAction>> classes = new ArrayList<>();
classes.add(TextBoxFloatAction.class);
classes.add(FormulaFloatAction.class);
classes.add(ChartFloatAction.class);
classes.add(ImageFloatAction.class);
Set<ElementUIProvider> providers = ExtraDesignClassManager.getInstance().getArray(ElementUIProvider.MARK_STRING);
for (ElementUIProvider provider : providers) {
classes.add(provider.actionForInsertFloatElement());
}
return classes.toArray(new Class[0]);
}
private static NameableCreator[] hyperlinkTypes() {
return new NameableCreator[]{
new NameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Hyperlink_Reportlet"), ReportletHyperlink.class, ReportletHyperlinkPane.ChartNoRename.class),
new NameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Email"), EmailJavaScript.class, EmailPane.class),
new NameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Hyperlink_Web_Link"), WebHyperlink.class, WebHyperlinkPane.ChartNoRename.class),
new NameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_JavaScript_Dynamic_Parameters"), ParameterJavaScript.class, ParameterJavaScriptPane.ChartNoRename.class),
new NameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_JavaScript"), JavaScriptImpl.class, JavaScriptImplPane.ChartNoRename.class),
new NameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup"), MobilePopupHyperlink.class, MobilePopupPane.class),
};
}
private static void justStartModules4Designer() {
formDesignerRegister();
}
/**
* CellElementValueConverter用来处理设计器格子里的值将公式/数组/其他元素转换成对应的值
*
* @return 返回处理格子值的转换器
*/
private static ValueConverter valueConverter() {
return new CellElementValueConverter();
}
/*
* 针对不同的对象在读取Object对象的xml的时候需要使用不同的对象生成器
* @return 返回对象生成器
*/
private static ObjectTokenizer startXMLReadObjectTokenizer() {
return new ReportXMLUtils.ReportObjectTokenizer();
}
/**
* 针对不同的对象在写对象的XML时需要使用不同的XML生成器
*
* @return 返回xml生成器
*/
private static ObjectXMLWriterFinder startObjectXMLWriterFinder() {
return new ReportXMLUtils.ReportObjectXMLWriterFinder();
}
//wei:fs的模块中可能有需要设计器界面做设置的地方,在这边添加
private static void addAdapterForPlate() {
ProcessTransitionAdapter.setProcessTransitionAdapter(new ProcessTransitionAdapter() {
@Override
protected String[] getTransitionNamesByBook(String book) {
return StableFactory.getMarkedObject(ProcessOperator.MARK_STRING, ProcessOperator.class, ProcessOperator.EMPTY).getTransitionNamesByBook(book);
}
@Override
protected String[] getParaNames(String book) {
return StableFactory.getMarkedObject(ProcessOperator.MARK_STRING, ProcessOperator.class, ProcessOperator.EMPTY).getParaNames(book);
}
@Override
protected ParameterProvider[] getParas(String book) {
return StableFactory.getMarkedObject(ProcessOperator.MARK_STRING, ProcessOperator.class, ProcessOperator.EMPTY).getParas(book);
}
@Override
protected MultiFieldParameter[] getAllMultiFieldParas(String book) {
return StableFactory.getMarkedObject(ProcessOperator.MARK_STRING, ProcessOperator.class, ProcessOperator.EMPTY).getAllMultiFieldParas(book);
}
});
}
private static void designerRegister() {
registerCellEditor();
registerFloatEditor();
registerData4Form();
registerOtherPane();
}
private static void registerOtherPane() {
StableFactory.registerMarkedClass(BBSGuestPaneProvider.XML_TAG, BBSGuestPane.class);
StableFactory.registerMarkedObject(HyperlinkGroupPaneActionProvider.XML_TAG, HyperlinkGroupPaneActionImpl.getInstance());
}
/**
* kunsnat:注册单元格选中Editor
*/
private static void registerCellEditor() {
ActionFactory.registerAsyncInitCellEditorClass(String.class, CellStringQuickEditor.class);
ActionFactory.registerAsyncInitCellEditorClass(Number.class, CellStringQuickEditor.class);
ActionFactory.registerAsyncInitCellEditorClass(BaseFormula.class, CellFormulaQuickEditor.class);
ActionFactory.registerAsyncInitCellEditorClass(SubReport.class, CellSubReportEditor.class);
ActionFactory.registerAsyncInitCellEditorClass(RichText.class, CellRichTextEditor.class);
ActionFactory.registerAsyncInitCellEditorClass(DSColumn.class, CellDSColumnEditor.class);
ActionFactory.registerAsyncInitCellEditorClass(Image.class, CellImageQuickEditor.class);
ActionFactory.registerAsyncInitCellEditorClass(BiasTextPainter.class, CellBiasTextPainterEditor.class);
ActionFactory.registerAsyncInitCellEditorClass(BufferedImage.class, CellImageQuickEditor.class);
ActionFactory.registerAsyncInitCellEditorClass(CellImagePainter.class, CellImageQuickEditor.class);
Set<ElementUIProvider> providers = ExtraDesignClassManager.getInstance().getArray(ElementUIProvider.MARK_STRING);
for (ElementUIProvider provider : providers) {
try {
if (provider.quickEditor() == null) {
continue;
}
ActionFactory.registerAsyncInitCellEditorClass(provider.targetObjectClass(), provider.quickEditor());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}
/**
* kunnat: 注册悬浮选中Editor
*/
private static void registerFloatEditor() {
ActionFactory.registerFloatEditor(String.class, new FloatStringQuickEditor());
ActionFactory.registerFloatEditor(Formula.class, new FloatStringQuickEditor());
ActionFactory.registerFloatEditor(Image.class, new FloatImageQuickEditor());
ActionFactory.registerFloatEditor(BufferedImage.class, new FloatImageQuickEditor());
ActionFactory.registerFloatEditor(CellImagePainter.class, new FloatImageQuickEditor());
//todo 图表编辑器populate没能实现刷新面板显示
ActionFactory.registerFloatEditorClass(ChartCollection.class, FloatChartQuickEditor.class);
}
private static void registerData4Form() {
StableFactory.registerMarkedClass(FormECDesignerProvider.XML_TAG, FormElementCaseDesigner.class);
StableFactory.registerMarkedClass(FormECCompositeProvider.XML_TAG, FormReportComponentComposite.class);
StableFactory.registerMarkedClass(ShareEntryKey.SHARE_GENERATE, ShareGeneratePane.class);
StableFactory.registerMarkedClass(ShareEntryKey.SHARE_CONFIG, ShareConfigPane.class);
DesignModuleFactory.registerParameterReader(new WorkBookParameterReader());
}
private static void formDesignerRegister() {
StableFactory.registerMarkedObject(DesignToolbarProvider.STRING_MARKED, WidgetToolBarPane.getInstance());
DesignModuleFactory.registerNewFormActionClass(NewFormAction.class);
DesignModuleFactory.registerReplaceActionClass(ITReplaceAction.class);
DesignModuleFactory.registerFormParaDesignerClass(FormParaDesigner.class);
DesignModuleFactory.registerParaPropertyPaneClass(ParameterPropertyPane.class);
DesignModuleFactory.registerFormHierarchyPaneClass(FormHierarchyTreePane.class);
DesignModuleFactory.registerWidgetPropertyPaneClass(WidgetPropertyPane.class);
DesignModuleFactory.registerButtonDetailPaneClass(FormSubmitButtonDetailPane.class);
DesignModuleFactory.registerReplace(new ReplaceOperator());
DesignModuleFactory.registerParameterReader(new FormParameterReader());
StableFactory.registerMarkedClass(BaseJForm.XML_TAG, NewJForm.class);
registerJTemplateEvent();
}
private static void registerJTemplateEvent(){
EventDispatcher.listen(JTemplateEvent.BEFORE_TEMPLATE_INIT, TemplateTool.getSwitchListener());
EventDispatcher.listen(JTemplateEvent.BEFORE_TEMPLATE_ACTIVE, TemplateTool.getSwitchListener());
}
private static void storePassport() {
FinePassportManager.getInstance().storePassport(DesignerEnvManager.getEnvManager().getDesignerLoginUsername(), DesignerEnvManager.getEnvManager().getActivationKey());
FinePassportManager.getInstance().addPassportListener(new FinePassportListenerAdapter() {
@Override
public void onLoginSuccess() {
FinePassportManager.getInstance().storePassport(DesignerEnvManager.getEnvManager().getDesignerLoginUsername(), DesignerEnvManager.getEnvManager().getActivationKey());
}
});
}
private void migrateBBSInfoFromFineDB() {
if (!WorkContext.getCurrent().isLocal()) {
return;
}
DesignerEnvManager manager = DesignerEnvManager.getEnvManager();
if (manager.isCurrentVersionFirstLaunch()) {
int newUid = manager.getDesignerLoginUid();
if (newUid > 0) {
return;
}
int oldUid = Carina.config(FineBBSConfigProvider.class).getBbsUid();
if (oldUid > 0) {
manager.setDesignerLoginUid(oldUid);
manager.setDesignerLoginUsername(Carina.config(FineBBSConfigProvider.class).getBbsUsername());
manager.setDesignerLoginAppId(Carina.config(FineBBSConfigProvider.class).getBbsAppId());
manager.setDesignerLoginRefreshToken(Carina.config(FineBBSConfigProvider.class).getBbsRefreshToken());
manager.setDesignerLastLoginTime(System.currentTimeMillis());
manager.setLastLoginType(DesignerLoginType.NORMAL_LOGIN);
manager.setLastLoginAccount(Carina.config(FineBBSConfigProvider.class).getBbsUsername());
manager.setCurrentVersionFirstLaunch(false);
DesignerEnvManager.getEnvManager().saveXMLFile();
}
}
}
@Override
public void stop() {
unloadLogAppender();
DesignerSocketIO.close();
TemplateLockInfoReSave.stopListener();
RPCConnectHandlerCenter.stopListener();
}
@Override
public void prepare() {
if (!OptimizeUtil.isOpen()) {
LoginAuthServer.getInstance().compatibleStart();
}
ContentReplacerCenter.getInstance().register();
EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
// 触发下cid 搜索
ProductNewsSearchManager.getInstance().getProductNewsList();
return null;
}
@Override
protected void done() {
QuestionWindow.getInstance().setVisible(true);
}
}.execute();
}
});
prepareDefaultEmbedPluginInfo();
}
private void prepareDefaultEmbedPluginInfo() {
Carina.getApplicationContext().group(PluginEmbedInfo.class).add(DefaultPluginEmbedInfo.create(PLUGIN_EXPORT_IMAGE_SETTING));
}
private void startBBSLoginAuthServer() {
OptimizeUtil.open(() -> {
// 设计器启动后启动
EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
LoginAuthServer.getInstance().start();
}
});
});
}
}

26
designer-realize/src/main/java/com/fr/start/module/DesignerESDActivator.java

@ -1,26 +0,0 @@
package com.fr.start.module;
import com.fr.esd.cache.manager.RecommendManager;
import com.fr.esd.core.strategy.config.service.StrategyConfigService;
import com.fr.esd.core.strategy.recomend.EnabledTemplateService;
import com.fr.esd.core.strategy.recomend.EnabledTemplateServiceProvider;
import com.fr.esd.impl.strategy.config.service.DefaultStrategyConfigServiceProvider;
import com.fr.module.Activator;
/**
* @author rinoux
* @version 10.0
* Created by rinoux on 2021/8/3
*/
public class DesignerESDActivator extends Activator {
@Override
public void start() {
StrategyConfigService.setService(new DefaultStrategyConfigServiceProvider());
EnabledTemplateService.getInstance().registerService(path -> RecommendManager.getInstance().findByPath(path) != null);
}
@Override
public void stop() {
//ignore
}
}

38
designer-realize/src/main/java/com/fr/start/module/DesignerInitActivator.java

@ -1,38 +0,0 @@
package com.fr.start.module;
import com.fanruan.boot.key.StartupArgsShell;
import com.fanruan.carina.Carina;
import com.fr.design.PluginClassRefreshManager;
import com.fanruan.boot.env.function.app.DesignerAppUtils;
import com.fr.io.repository.base.fs.FileSystemRepository;
import com.fr.io.utils.ResourceIOUtils;
import com.fr.module.Activator;
import com.fr.module.extension.Prepare;
import com.fr.start.DesignerInitial;
/**
* 设计器界面初始化
*
* @author vito
* @since 10.0
* Created on 2019/9/25
*/
public class DesignerInitActivator extends Activator implements Prepare {
@Override
public void prepare() {
ResourceIOUtils.setUnderlying(FileSystemRepository.getSingleton());
}
@Override
public void start() {
PluginClassRefreshManager.getInstance().load();
DesignerAppUtils.initPluginAllActiveListener();
DesignerInitial.init(Carina.getApplicationContext().singleton(StartupArgsShell.class).get().get());
}
@Override
public void stop() {
// void
}
}

24
designer-realize/src/main/java/com/fr/start/module/DesignerShowActivator.java

@ -1,24 +0,0 @@
package com.fr.start.module;
import com.fr.design.i18n.Toolkit;
import com.fr.event.EventDispatcher;
import com.fr.module.Activator;
import com.fr.start.DesignerInitial;
/**
* Created by juhaoyu on 2019-06-14.
*/
public class DesignerShowActivator extends Activator {
@Override
public void start() {
/// 后续换成其他进度方式
//EventDispatcher.asyncFire(ModuleEvent.MajorModuleStarting, Toolkit.i18nText("Fine-Design_Module_Name_Designer"));
DesignerInitial.prepare();
}
@Override
public void stop() {
// void
}
}

200
designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java

@ -1,200 +0,0 @@
package com.fr.start.module;
import com.fanruan.product.BuildContext;
import com.fr.base.OptimizeUtil;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.config.dao.DaoSelectorFactory;
import com.fr.config.dao.PropertiesConstants;
import com.fr.decision.webservice.v10.encryption.EncryptionConstants;
import com.fr.design.DesignerEnvManager;
import com.fr.design.RestartHelper;
import com.fr.design.dialog.TipDialog;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.env.DesignerWorkspaceType;
import com.fr.design.fun.impl.GlobalListenerProviderManager;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.messagecollect.StartErrorMessageCollector;
import com.fr.design.mainframe.messagecollect.StartupMessageCollector;
import com.fr.design.mainframe.messagecollect.entity.DesignerErrorMessage;
import com.fr.design.utils.DesignUtils;
import com.fr.env.utils.WorkspaceUtils;
import com.fr.event.Event;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.exit.DesignerExiter;
import com.fr.log.FineLoggerFactory;
import com.fr.module.Activator;
import com.fr.record.analyzer.EnableMetrics;
import com.fr.record.analyzer.Metrics;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.start.DesignerProcessType;
import com.fr.start.ServerStarter;
import com.fr.start.common.DesignerStartupContext;
import com.fr.start.event.LazyStartupEvent;
import com.fr.start.preload.PreLoadService;
import com.fr.start.server.FineEmbedServer;
import com.fr.third.guava.base.Stopwatch;
import com.fr.value.NotNullLazyValue;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Created by juhaoyu on 2018/1/8.
*/
@EnableMetrics
public class DesignerStartup extends Activator {
private NotNullLazyValue<StartupArgs> startupArgsValue = new NotNullLazyValue<StartupArgs>() {
@NotNull
@Override
protected StartupArgs compute() {
return findSingleton(StartupArgs.class);
}
};
@Override
public void beforeAllStart() {
BuildContext.setBuildFilePath("/com/fr/stable/build.properties");
registerDaoSelector();
Stopwatch beforeWatch = Stopwatch.createStarted();
PreLoadService.getInstance().waitForCommon();
FineLoggerFactory.getLogger().debug( "DesignerStartup cost {} ms to wait load", beforeWatch.elapsed(TimeUnit.MILLISECONDS));
if (DesignUtils.isStarted()) {
// 如果端口被占用了 说明程序已经运行了一次,也就是说,已经建立一个监听服务器,现在只要给服务器发送命令就好了
final String[] args = startupArgsValue.getValue().get();
if (ArrayUtils.isNotEmpty(args)) {
DesignUtils.clientSend(args);
}
FineLoggerFactory.getLogger().info("The Designer Has Been Started");
if (args.length == 0) {
TipDialog dialog = new TipDialog(null,
DesignerProcessType.INSTANCE.obtain(),
Toolkit.i18nText("Fine-Design_Last_Designer_Process_Not_Exist"),
Toolkit.i18nText("Fine-Design_End_Occupied_Process"),
Toolkit.i18nText("Fine-Design_Basic_Cancel")) {
@Override
protected void endEvent() {
dispose();
DesignUtils.clientSend(new String[]{"end"});
RestartHelper.restart();
}
@Override
protected void cancelEvent() {
dispose();
}
};
dialog.setVisible(true);
StartErrorMessageCollector.getInstance().record(DesignerErrorMessage.DESIGNER_PROCESS_OCCUPIED.getId(),
DesignerErrorMessage.DESIGNER_PROCESS_OCCUPIED.getMessage(),
StringUtils.EMPTY);
FineLoggerFactory.getLogger().error(DesignerErrorMessage.DESIGNER_PROCESS_OCCUPIED.getId() + ": " + DesignerErrorMessage.DESIGNER_PROCESS_OCCUPIED.getMessage());
}
DesignerExiter.getInstance().execute();
}
}
@Override
@Metrics
public void start() {
startSub(PreStartActivator.class);
startSub("parallel");
//designer模块启动好后,查看demo
browserDemoIfNeeded();
startupEmbedServerIfNeeded();
}
private void startupEmbedServerIfNeeded() {
if (DesignerEnvManager.getEnvManager().isEmbedServerLazyStartup()
|| FineEmbedServer.isRunning()) {
return;
}
if (DaoSelectorFactory.getDaoSelector().useCacheDao() || DesignerStartupContext.getInstance().isOnStartup()) {
listenEvent(LazyStartupEvent.INSTANCE, new Listener<Null>(Integer.MIN_VALUE) {
@Override
public void on(Event event, Null param) {
// 有可能被插件之类的 强制启动了 判断下
if (FineEmbedServer.isRunning() || FineEmbedServer.isOnStarting()) {
return;
}
startEmbeddedServer();
}
});
} else {
startEmbeddedServer();
}
}
private void startEmbeddedServer() {
ExecutorService service = newSingleThreadExecutor(new NamedThreadFactory("FineEmbedServerStart"));
service.submit(() -> {
try {
FineEmbedServer.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
service.shutdown();
}
@Override
public void afterAllStart() {
GlobalListenerProviderManager.getInstance().init();
// 启动日志收集
StartupMessageCollector.getInstance().recordStartupLog();
}
private void browserDemoIfNeeded() {
if (startupArgsValue.getValue().isDemo()) {
ServerStarter.browserDemoURL();
}
}
private void registerDaoSelector() {
// 注入设计器db cache 是否可用
DesignerWorkspaceInfo info = WorkspaceUtils.getWorkspaceInfo();
if (info.getType() == DesignerWorkspaceType.Remote) {
DaoSelectorFactory.registerDaoSelector(() -> false);
} else {
String webInfPath = WorkspaceUtils.getWorkspaceInfo().getPath();
String dbConfigPath = StableUtils.pathJoin(webInfPath, ProjectConstants.CONFIG_DIRECTORY,
EncryptionConstants.PROPERTY_NAME);
String entityPath = generatePath(webInfPath, PropertiesConstants.ENTITY_PROP);
String xmlEntityPath = generatePath(webInfPath, PropertiesConstants.XML_ENTITY_PROP);
String classNamePath = generatePath(webInfPath, PropertiesConstants.CLASS_NAME_PROP);
// 校验 平台迁移文件/缓存文件
boolean existPropCache = new File(entityPath).exists() && new File(xmlEntityPath).exists() && new File(classNamePath).exists();
DaoSelectorFactory.registerDaoSelector(() -> DesignerEnvManager.getEnvManager().isPropertiesUsable()
&& OptimizeUtil.isOpen()
&& existPropCache
// demo启动时 前后目录可能会不一致 造成读取缓存失败
&& !startupArgsValue.getValue().isDemo()
&& !new File(dbConfigPath).exists());
}
}
private String generatePath(String webInfPath, String name) {
return StableUtils.pathJoin(webInfPath, ProjectConstants.EMBED_DB_DIRECTORY,
ProjectConstants.PROPERTIES_CACHE_FOR_CONFIG, name);
}
@Override
public void stop() {
// void
}
}

123
designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceActivator.java

@ -1,123 +0,0 @@
package com.fr.start.module;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.PluginClassRefreshManager;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.event.Event;
import com.fr.event.Listener;
import com.fr.module.Activator;
import com.fr.module.ModuleContext;
import com.fr.module.engine.FineModule;
import com.fr.start.server.FineEmbedServer;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import com.fr.workspace.WorkspaceEvent;
import com.fr.workspace.WorkspaceSwitchProcess;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
/**
* Created by juhaoyu on 2019-06-14.
*/
public class DesignerWorkspaceActivator extends Activator {
private final Listener<Workspace> stopModuleAction = new Listener<Workspace>(Integer.MIN_VALUE) {
@Override
public void on(Event event, Workspace current) {
stopSub(EnvBasedModule.class);
recordModuleStop();
}
private void recordModuleStop() {
WorkspaceSwitchProcess process = WorkContext.getSwitcher().getProcess();
Optional.ofNullable(process)
.ifPresent((e) -> e.recordModuleStopUsed(() -> {
FineModule module = (FineModule) ModuleContext.getModule(EnvBasedModule.class);
return module.profileStop();
}));
}
};
private final Listener<Workspace> startModuleAction = new Listener<Workspace>(Integer.MAX_VALUE) {
@Override
public void on(Event event, Workspace current) {
startSub(EnvBasedModule.class);
recordModuleStart();
}
private void recordModuleStart() {
WorkspaceSwitchProcess process = WorkContext.getSwitcher().getProcess();
Optional.ofNullable(process)
.ifPresent((e) -> e.recordModuleStartUsed(() -> {
FineModule module = (FineModule) ModuleContext.getModule(EnvBasedModule.class);
return module.profile();
}));
}
};
@Override
public void start() {
registerEnvListener();
}
/**
* 注册切换环境前后事件监听
*/
private void registerEnvListener() {
/*切换环境前,关闭所有相关模块,最后执行*/
listenEvent(WorkspaceEvent.BeforeSwitch, stopModuleAction);
/*切换环境后,重新启动所有相关模块,最先执行*/
listenEvent(WorkspaceEvent.AfterSwitch, startModuleAction);
/*切换环境前,存储一下打开的所有文件对象,要先于 关闭相关模块部分 被触发*/
listenEvent(WorkspaceEvent.BeforeSwitch, new Listener<Workspace>(Integer.MAX_VALUE) {
@Override
public void on(Event event, Workspace workspace) {
PluginClassRefreshManager.getInstance().removePluginListener();
HistoryTemplateListCache.getInstance().stash();
PluginClassRefreshManager.getInstance().fireTabChange();
}
});
/*切换环境后,装载一下打开的所有文件对象,优先级低于默认优先级,要后于 启动相关模块部分 被触发*/
listenEvent(WorkspaceEvent.AfterSwitch, new Listener<Workspace>(Integer.MIN_VALUE) {
@Override
public void on(Event event, Workspace workspace) {
HistoryTemplateListCache.getInstance().load();
PluginClassRefreshManager.getInstance().addPluginListener();
}
});
}
private void startServer(Workspace current) {
// 切换后的环境是本地环境才启动内置服务器
if (current.isLocal()) {
ExecutorService service = newSingleThreadExecutor(
new NamedThreadFactory("DesignerWorkspaceActivator"));
service.submit(() -> {
try {
FineEmbedServer.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
service.shutdown();
}
}
@Override
public void stop() {
}
}

99
designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java

@ -1,99 +0,0 @@
package com.fr.start.module;
import com.fanruan.boot.key.StartupArgsShell;
import com.fanruan.carina.Carina;
import com.fr.design.DesignerEnvManager;
import com.fr.design.EnvChangeEntrance;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.design.editlock.ConnectionLockChangeChecker;
import com.fr.design.editlock.ServerTableDataLockChangeChecker;
import com.fr.design.env.DesignerWorkspaceGenerator;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.plugin.remind.PluginErrorDesignReminder;
import com.fr.env.utils.WorkspaceUtils;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.module.Activator;
import com.fr.design.backup.DesignContext;
import com.fr.value.NotNullLazyValue;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import org.jetbrains.annotations.NotNull;
/**
* Created by juhaoyu on 2018/1/8.
* 设计器启动时的环境相关模块activator
*/
public class DesignerWorkspaceProvider extends Activator {
private NotNullLazyValue<StartupArgs> startupArgs = new NotNullLazyValue<StartupArgs>() {
@NotNull
@Override
protected StartupArgs compute() {
return Carina.getApplicationContext().singleton(StartupArgsShell.class).get();
}
};
@Override
public void start() {
//检查环境
DesignerEnvManager.checkNameEnvMap();
if (startupArgs.getValue().isDemo()) {
DesignerEnvManager.getEnvManager().setCurrentEnv2Default();
} else {
DesignerWorkspaceInfo workspaceInfo = null;
try {
String current = DesignerEnvManager.getEnvManager().getCurEnvName();
workspaceInfo = WorkspaceUtils.getWorkspaceInfo();
((DesignContext)Carina.getApplicationContext()).setDesignWebInfPath(workspaceInfo.getPath());
Workspace workspace = DesignerWorkspaceGenerator.generate(workspaceInfo);
boolean checkValid = workspace != null && workspaceInfo.checkValid();
if (!checkValid) {
EnvChangeEntrance.getInstance().dealEvnExceptionWhenStartDesigner(null, workspaceInfo);
} else {
WorkContext.switchTo(workspace);
}
} catch (Throwable e) {
EnvChangeEntrance.getInstance().dealEvnExceptionWhenStartDesigner(e, workspaceInfo);
}
}
pluginErrorRemind();
editLockCheckerStart();
}
private void editLockCheckerStart() {
ConnectionLockChangeChecker.getInstance().start();
ServerTableDataLockChangeChecker.getInstance().start();
}
private void pluginErrorRemind() {
EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null aNull) {
PluginErrorDesignReminder.getInstance().remindStartFailedPlugins();
PluginErrorDesignReminder.getInstance().remindInvalidatePlugins();
}
});
}
@Override
public void stop() {
// void
editLockCheckerStop();
}
private void editLockCheckerStop() {
ConnectionLockChangeChecker.getInstance().stop();
ServerTableDataLockChangeChecker.getInstance().stop();
}
@Override
public void afterAllStart() {
DesignerLaunchStatus.setStatus(DesignerLaunchStatus.WORKSPACE_INIT_COMPLETE);
}
}

21
designer-realize/src/main/java/com/fr/start/module/EnvBasedModule.java

@ -1,21 +0,0 @@
package com.fr.start.module;
import com.fr.module.Activator;
import com.fr.start.server.FineEmbedServer;
/**
* Created by juhaoyu on 2018/6/6.
* 基于env的模块启动关闭
*/
public class EnvBasedModule extends Activator {
@Override
public void start() {
}
@Override
public void stop() {
//先关闭tomcat(如果已经启动了的话)
FineEmbedServer.stop();
}
}

59
designer-realize/src/main/java/com/fr/start/module/PreStartActivator.java

@ -1,59 +0,0 @@
package com.fr.start.module;
import com.fr.design.DesignerEnvManager;
import com.fr.design.RestartHelper;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.design.file.TemplateResourceManager;
import com.fr.design.utils.DesignUtils;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.file.TmpFileUtils;
import com.fr.general.CloudCenter;
import com.fr.general.GeneralContext;
import com.fr.module.Activator;
import com.fr.start.common.DesignerStartupPool;
/**
* Created by juhaoyu on 2018/1/8.
*/
public class PreStartActivator extends Activator {
@Override
public void start() {
//清空临时文件
Runtime.getRuntime().addShutdownHook(new Thread(TmpFileUtils::cleanUpInnerTmpFiles));
RestartHelper.deleteRecordFilesWhenStart();
//初始化起始画面放到 SplashContext 里面
//EventDispatcher.fire(ModuleEvent.MajorModuleStarting, Toolkit.i18nText("Fine-Design_Basic_Initializing"));
// 完成初始化
//noinspection ResultOfMethodCallIgnored
CloudCenter.getInstance();
// 创建监听服务
DesignUtils.createListeningServer(DesignUtils.getPort(), startFileSuffix());
// 在插件引擎模块起来前 初始化下插件接口监听
TemplateResourceManager.getResource();
initLanguage();
}
@Override
public void stop() {
// void
}
private void initLanguage() {
//这两句的位置不能随便调换,因为会影响语言切换的问题
GeneralContext.setLocale(DesignerEnvManager.getEnvManager(false).getLanguage());
}
private String[] startFileSuffix() {
return new String[]{".cpt", ".xls", ".xlsx", ".frm", ".form", ".cht", ".chart", ".fvs"};
}
}

36
designer-realize/src/main/java/com/fr/start/module/optimized/BaseDBActivator4Designer.java

@ -1,36 +0,0 @@
package com.fr.start.module.optimized;
import com.fr.config.activator.BaseDBActivator;
import com.fr.config.dao.DaoSelectorFactory;
import com.fr.event.Event;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.stable.lifecycle.FineLifecycleFatalError;
import com.fr.start.LifecycleFatalErrorHandler;
import com.fr.start.event.LazyStartupEvent;
/**
* @author hades
* @version 11.0
* Created by hades on 2022/3/7
*/
public class BaseDBActivator4Designer extends BaseDBActivator {
@Override
public void start() {
if (DaoSelectorFactory.getDaoSelector().useCacheDao()) {
listenEvent(LazyStartupEvent.INSTANCE, new Listener<Null>(Integer.MAX_VALUE) {
@Override
public void on(Event event, Null param) {
try {
BaseDBActivator4Designer.super.start();
} catch (FineLifecycleFatalError error) {
LifecycleFatalErrorHandler.getInstance().handle(error);
}
}
});
} else {
super.start();
}
}
}

23
designer-realize/src/main/java/com/fr/start/module/optimized/ConfigurationActivator4Designer.java

@ -1,23 +0,0 @@
package com.fr.start.module.optimized;
import com.fr.config.activator.ConfigurationActivator;
import com.fr.config.dao.DaoSelectorFactory;
import com.fr.transaction.PropertiesTransactor;
import com.fr.transaction.TransactorFactory;
/**
* @author hades
* @version 11.0
* Created by hades on 2022/3/7
*/
public class ConfigurationActivator4Designer extends ConfigurationActivator {
@Override
protected void initLocalDao() {
if (DaoSelectorFactory.getDaoSelector().useCacheDao()) {
TransactorFactory.setTransactor(new PropertiesTransactor());
} else {
super.initLocalDao();
}
}
}

25
designer-realize/src/main/java/com/fr/start/module/optimized/DesignUpdateActivator.java

@ -1,25 +0,0 @@
package com.fr.start.module.optimized;
import com.fr.start.common.DesignerStartupContext;
import com.fr.update.activator.BasicUpdateActivator;
import com.fr.update.base.FineUpdateUnit;
/**
* created by Harrison on 2022/08/11
**/
public class DesignUpdateActivator extends BasicUpdateActivator {
@Override
public void start() {
if (DesignerStartupContext.getInstance().onWarmup()) {
try {
prepare4Start();
FineUpdateUnit.makeNew();
} catch (Throwable ignore) {
}
} else {
super.start();
}
}
}

35
designer-realize/src/main/java/com/fr/start/module/optimized/DesignerPluginActivator.java

@ -1,35 +0,0 @@
package com.fr.start.module.optimized;
import com.fr.module.Activator;
import com.fr.module.ModuleContext;
import com.fr.plugin.manage.PluginManager;
import com.fr.start.common.DesignerStartupExecutor;
import com.fr.workspace.WorkContext;
import com.fr.workspace.WorkspaceSwitchHelper;
import com.fr.workspace.WorkspaceSwitchProcess;
/**
* created by Harrison on 2022/06/22
**/
public class DesignerPluginActivator extends Activator {
@Override
public void start() {
//WorkspaceSwitchProcess process = WorkContext.getSwitcher().getProcess();
//if (WorkspaceSwitchHelper.supportHotSwitch(process)) {
// PluginManager.getHotModule().start();
//} else {
// DesignerStartupExecutor.getInstance().execute(() -> ModuleContext.getModule(PluginActivator.class).start());
//}
}
@Override
public void stop() {
//WorkspaceSwitchProcess process = WorkContext.getSwitcher().getProcess();
//if (WorkspaceSwitchHelper.supportHotSwitch(process)) {
// PluginManager.getHotModule().stop();
//} else {
// ModuleContext.getModule(PluginActivator.class).stop();
//}
}
}

221
designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.java

@ -1,221 +0,0 @@
package com.fr.start.module.optimized;
import com.fanruan.boot.key.ActivatorContextGroup;
import com.fanruan.boot.key.StartupArgsShell;
import com.fanruan.carina.Carina;
import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.messagecollect.StartErrorMessageCollector;
import com.fr.design.ui.util.UIUtil;
import com.fr.log.FineLoggerFactory;
import com.fr.module.Activator;
import com.fr.module.engine.base.ActivatorContext;
import com.fr.start.SplashContext;
import com.fr.start.common.DesignerStartupContext;
import com.fr.start.module.StartupArgs;
import com.fr.start.preload.PreLoadService;
import com.fr.start.util.DesignerStartupPageUtil;
import com.fr.startup.metric.DesignerMetrics;
import com.fr.startup.metric.DesignerStartupModel;
import com.fr.startup.ui.StartupPageModel;
import com.fr.startup.ui.StartupPageWindow;
import com.fr.startup.ui.StartupWorkspaceBean;
import com.fr.third.org.apache.commons.lang3.time.StopWatch;
import com.fr.value.NotNullLazyValue;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* 设计器起始页启动器
* <a href="https://kms.fineres.com/pages/viewpage.action?pageId=416850313">设计文档</a>
*
* created by Harrison on 2022/07/03
**/
public class DesignerStartupPageActivator extends Activator {
private final NotNullLazyValue<StartupArgs> startupArgsValue = new NotNullLazyValue<StartupArgs>() {
@NotNull
@Override
protected StartupArgs compute() {
return Carina.getApplicationContext().singleton(StartupArgsShell.class).get();
}
};
/**
* 上下文
*/
private final ActivatorContext activatorContext = new ActivatorContext();
private final CountDownLatch LATCH = new CountDownLatch(1);
@Override
public void start() {
DesignerStartupContext context = DesignerStartupContext.getInstance();
context.setStartupArgs(startupArgsValue.getValue());
if (context.isShowStartupPage()) {
showDesignerStartupPage(context);
} else {
startNonStartupPage();
}
}
private void startNonStartupPage() {
StopWatch recorder = DesignerStartupContext.getRecorder();
try {
DesignerStartupPageUtil.enterWorkspace();
} catch (Exception e) {
throw new RuntimeException(e);
}
recordStartupEnd(recorder);
}
private void showDesignerStartupPage(DesignerStartupContext context) {
// 启动页关闭
SplashContext.getInstance().hide();
// 即时暂停
suspendRecorder(context);
Carina.getApplicationContext().group(ActivatorContextGroup.class).add(activatorContext);
PreLoadService.getInstance().waitForUI();
UIUtil.invokeLaterIfNeeded(() -> {
StartupPageModel model = StartupPageModel.create();
context.setStartupPageModel(model);
StopWatch suspendWatch = new StopWatch();
final Runnable recordSuspend = () -> {
long suspendTime = suspendWatch.getTime(TimeUnit.MILLISECONDS);
activatorContext.setSuspendTime(suspendTime);
};
// selectAndOpenLast
model.setOpenLastTemplateRunnable(() -> {
recordSuspend.run();
context.setOpenLastFile(true);
handleModel(model);
launchAfterWarmup();
});
// selectAndOpenEmpty
model.setOpenEmptyTemplateRunnable(() -> {
recordSuspend.run();
context.setOpenEmpty(true);
handleModel(model);
launchAfterWarmup();
});
// selectAndCreateNew
model.setCreateNewTemplateRunnable(() -> {
recordSuspend.run();
context.setCreateNew(true);
handleModel(model);
launchAfterWarmup();
});
StartupPageWindow window = new StartupPageWindow(model);
window.setVisible(true);
context.setOnWaiting(true);
suspendWatch.start();
});
waitSubTask();
}
private void suspendRecorder(DesignerStartupContext context) {
DesignerMetrics designerMetrics = context.getDesignerMetrics();
DesignerStartupModel designerStartupModel = designerMetrics.getModel();
StopWatch recorder = DesignerStartupContext.getRecorder();
recorder.suspend();
long time = recorder.getTime(TimeUnit.MILLISECONDS);
designerStartupModel.setLandingTime(time);
}
private void handleModel(StartupPageModel model) {
// 将选中的环境设置为当前环境
StartupWorkspaceBean selectWorkspaceInfo = model.getSelectWorkspaceInfo();
DesignerEnvManager.getEnvManager().setCurEnvName(selectWorkspaceInfo.getName());
UIUtil.invokeLaterIfNeeded(() -> {
DesignerContext.getDesignerFrame().setTitle();
});
}
private void launchAfterWarmup() {
StopWatch stopWatch = StopWatch.createStarted();
try {
StopWatch recorder = DesignerStartupContext.getRecorder();
if (recorder.isSuspended()) {
recorder.resume();
}
// 等待中切换
DesignerStartupContext.getInstance().setOnWaiting(false);
DesignerStartupContext.getInstance().setOnStartup(true);
try {
DesignerStartupPageUtil.enterWorkspace();
} catch (Exception e) {
throw new RuntimeException(e);
}
} finally {
UIUtil.invokeLaterIfNeeded(() -> {
// 换到 awt 线程中关闭,不然异步会出现问题。
DesignerStartupContext.getInstance().setOnStartup(false);
StartErrorMessageCollector.getInstance().setExtraJudgeStart(true);
recordStartupEnd(stopWatch);
});
markComplete();
}
}
private void recordStartupEnd(StopWatch stopWatch) {
DesignerStartupContext context = DesignerStartupContext.getInstance();
DesignerMetrics designerMetrics = context.getDesignerMetrics();
DesignerStartupModel model = designerMetrics.getModel();
model.setStartingTime(stopWatch.getTime(TimeUnit.MILLISECONDS));
model.fill();
}
/**
* 阻塞住当前的方法
* 只有 UI 交互开始执行的时候才会停止阻塞
*/
private void waitSubTask() {
try {
LATCH.await();
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private void markComplete() {
try {
LATCH.countDown();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
@Override
public void stop() {
}
}

32
designer-realize/src/main/java/com/fr/start/module/optimized/ReportBaseActivator4Designer.java

@ -1,32 +0,0 @@
package com.fr.start.module.optimized;
import com.fr.config.dao.DaoSelectorFactory;
import com.fr.event.Event;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.report.module.ReportBaseActivator;
import com.fr.start.event.LazyStartupEvent;
/**
* @author hades
* @version 11.0
* Created by hades on 2022/3/16
*/
public class ReportBaseActivator4Designer extends ReportBaseActivator {
@Override
protected void vcsInit() {
if (DaoSelectorFactory.getDaoSelector().useCacheDao()) {
listenEvent(LazyStartupEvent.INSTANCE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
ReportBaseActivator4Designer.super.vcsInit();
}
});
} else {
super.vcsInit();
}
}
}

7
designer-realize/src/main/java/com/fr/strongest/WidgetThemeListenerStarter.java

@ -1,5 +1,6 @@
package com.fr.strongest;
import com.fanruan.ComponentUtils;
import com.finebi.cbb.utils.StringUtils;
import com.fr.base.io.BaseBook;
import com.fr.design.constants.DesignerLaunchStatus;
@ -11,7 +12,6 @@ import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.module.ModuleContext;
import com.fr.widgettheme.control.attr.WidgetDisplayEnhanceMarkAttr;
/**
@ -22,7 +22,8 @@ import com.fr.widgettheme.control.attr.WidgetDisplayEnhanceMarkAttr;
* Created on 2023/11/13
*/
public class WidgetThemeListenerStarter {
private WidgetThemeListenerStarter(){}
private WidgetThemeListenerStarter() {
}
/**
* 启动对模版控件主题显示的监听开关
@ -43,7 +44,7 @@ public class WidgetThemeListenerStarter {
dealWithJTemplate4Attr(temp);
}
};
if (ModuleContext.isDesignerStartup()) {
if (ComponentUtils.isDesignerStart()) {
EventDispatcher.listen(JTemplateEvent.BEFORE_TEMPLATE_INIT, attrListener);
}
}

1
designer-realize/src/test/java/com/fr/design/mainframe/app/DesignerAppUtilsTest.java

@ -1,5 +1,6 @@
package com.fr.design.mainframe.app;
import com.fanruan.boot.env.function.app.DesignerAppUtils;
import com.fr.invoke.Reflect;
import com.fr.plugin.context.PluginMarker;
import com.fr.plugin.context.PluginMarkerAdapter;

50
designer-realize/src/test/java/com/fr/start/module/DesignerWorkspaceProviderTest.java

@ -1,50 +0,0 @@
package com.fr.start.module;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.event.EventDispatcher;
import com.fr.invoke.Reflect;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
/**
* @author Lucian.Chen
* @version 10.0
* Created by Lucian.Chen on 2021/1/7
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({WorkContext.class})
public class DesignerWorkspaceProviderTest {
@Test
public void testPluginErrorRemind() {
try {
Workspace workspace = EasyMock.mock(Workspace.class);
EasyMock.expect(workspace.isLocal()).andReturn(false).once();
PowerMock.mockStatic(WorkContext.class);
EasyMock.expect(WorkContext.getCurrent()).andReturn(workspace).anyTimes();
EasyMock.replay(workspace);
PowerMock.replayAll();
DesignerWorkspaceProvider provider = new DesignerWorkspaceProvider();
Reflect.on(provider).call("pluginErrorRemind");
EventDispatcher.fire(DesignerLaunchStatus.STARTUP_COMPLETE);
EasyMock.verify(workspace);
PowerMock.verifyAll();
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
}
Loading…
Cancel
Save