Browse Source

Merge branch 'feature/x' of ssh://code.fineres.com:7999/~roger.chen/design into feature/x

feature/x
roger 2 years ago
parent
commit
a2050fd5f9
  1. 14
      designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java
  2. 28
      designer-base/src/main/java/com/fr/design/carton/CartonFiles.java
  3. 161
      designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java
  4. 45
      designer-base/src/main/java/com/fr/design/carton/CartonUploadMessage.java
  5. 366
      designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java
  6. 330
      designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java
  7. 36
      designer-base/src/main/java/com/fr/design/carton/MonthlyCartonFile.java
  8. 240
      designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java
  9. 6
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java
  10. 35
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  11. 135
      designer-base/src/main/java/com/fr/design/gui/date/UICalendarPanel.java
  12. 59
      designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java
  13. 11
      designer-base/src/main/java/com/fr/design/utils/DesignerPort.java
  14. 2
      designer-base/src/main/java/com/fr/env/detect/ui/EnvDetectorAction.java
  15. 31
      designer-base/src/main/java/com/fr/env/detect/ui/EnvDetectorDialog.java
  16. 2
      designer-base/src/main/java/com/fr/start/common/DesignerOpenEmptyPanel.java
  17. 7
      designer-base/src/main/java/com/fr/start/common/DesignerStartupConfig.java
  18. 10
      designer-base/src/main/java/com/fr/start/common/DesignerStartupContext.java
  19. 22
      designer-base/src/main/java/com/fr/startup/metric/DesignerMetrics.java
  20. 193
      designer-base/src/main/java/com/fr/startup/metric/DesignerStartupModel.java
  21. 71
      designer-base/src/main/java/com/fr/startup/metric/DesignerStartupPageStatistic.java
  22. 2
      designer-realize/src/main/java/com/fr/design/sort/header/HeaderAreaPane.java
  23. 6
      designer-realize/src/main/java/com/fr/start/MainDesigner.java
  24. 24
      designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.java

14
designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java

@ -242,8 +242,8 @@ public class PreferencePane extends BasicPane {
createLanPane(generalPane);
// 先屏蔽下
// createStartupPagePane(generalPane);
createStartupPagePane(generalPane);
createLengthPane(advancePane);
createServerPane(advancePane);
@ -655,13 +655,13 @@ public class PreferencePane extends BasicPane {
// ben:选择版本语言;
JPanel startupPagePaneWrapper = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane();
JPanel startupPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane("启动页配置");
JPanel startupPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Startup_Page_Config"));
generalPane.add(startupPagePaneWrapper);
startupPagePaneWrapper.add(startupPane);
startupPageEnabledCheckBox = new UICheckBox("启动设计器时,自动打开启动页");
startupPageEnabledCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Startup_Page_Config_Check_Text"));
startupPane.add(startupPageEnabledCheckBox);
UILabel descLabel = new UILabel("注意:若在远程环境下直接关闭,再次启动时,启动速度会变慢");
UILabel descLabel = new UILabel(Toolkit.i18nText("Fine-Design_Startup_Page_Config_Desc"));
descLabel.setForeground(new Color(51, 51, 52, (int)Math.round(0.5 * 255)));
startupPane.add(descLabel);
}
@ -854,7 +854,7 @@ public class PreferencePane extends BasicPane {
previewResolutionBtnM.setEnabled(enabled);
this.cloudAnalyticsDelayCheckBox.setSelected(designerEnvManager.isCloudAnalyticsDelay());
// this.startupPageEnabledCheckBox.setSelected(designerEnvManager.isStartupPageEnabled());
this.startupPageEnabledCheckBox.setSelected(designerEnvManager.isStartupPageEnabled());
}
private int chooseCase(int sign) {
@ -921,7 +921,7 @@ public class PreferencePane extends BasicPane {
vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected());
vcsConfigManager.setSaveCommit(this.saveCommitCheckBox.isSelected());
vcsConfigManager.setUseInterval(this.useIntervalCheckBox.isSelected());
// designerEnvManager.setStartupPageEnabled(this.startupPageEnabledCheckBox.isSelected());
designerEnvManager.setStartupPageEnabled(this.startupPageEnabledCheckBox.isSelected());
Configurations.update(new Worker() {
@Override
public void run() {

28
designer-base/src/main/java/com/fr/design/carton/CartonFiles.java

@ -0,0 +1,28 @@
package com.fr.design.carton;
import java.io.File;
public class CartonFiles {
private File easyCheckerFile;
private File timerCheckerFile;
public CartonFiles() {
}
public File getEasyCheckerFile() {
return easyCheckerFile;
}
public void setEasyCheckerFile(File easyCheckerFile) {
this.easyCheckerFile = easyCheckerFile;
}
public File getTimerCheckerFile() {
return timerCheckerFile;
}
public void setTimerCheckerFile(File timerCheckerFile) {
this.timerCheckerFile = timerCheckerFile;
}
}

161
designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java

@ -0,0 +1,161 @@
package com.fr.design.carton;
import com.fr.base.SimpleDateFormatThreadSafe;
import com.fr.design.i18n.Toolkit;
import com.fr.json.JSONObject;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
public class CartonThreadExecutorPool extends ThreadPoolExecutor {
private static final int MAX_LIVE_TIME = 3000;
private static final int MAX_WORKER_THREADS = 10;
/**
* 开启间隔检测后两次检测的相隔时间ms
*/
private static final long CHECK_INTERVAL_MS = 100;
private final ThreadLocal<StackTraceElement[]> startReportedStack = new ThreadLocal<>();
private volatile static CartonThreadExecutorPool cartonThreadExecutorPool;
private static final ConcurrentHashMap<Long, ThreadInfo> concurrentHashMap = new ConcurrentHashMap<>();
private static final SimpleDateFormatThreadSafe simpleDateFormatThreadSafe = new SimpleDateFormatThreadSafe();
private final static AtomicLong hangCount = new AtomicLong(0);
private Timer timer;
/**
* 一个变量用于控制easy监测模式的开关
*/
private boolean easyWitch = false;
public boolean isEasyWitch() {
return easyWitch;
}
public void setEasyWitch(boolean easyWitch) {
this.easyWitch = easyWitch;
}
private static class ThreadInfo {
private ThreadInfo () {
hangNumber = hangCount.getAndAdd(1);
}
private long hangNumber;
private final Thread eventThread = Thread.currentThread();
private StackTraceElement[] lastReportedStack;
private final long startTime = System.currentTimeMillis();
public void checkForHang() {
if (timeSoFar() > MAX_LIVE_TIME) {
examineHang();
}
}
private long timeSoFar() {
return (System.currentTimeMillis() - startTime);
}
private void examineHang() {
StackTraceElement[] currentStack = eventThread.getStackTrace();
if (lastReportedStack!=null && EventDispatchThreadHangMonitor.stacksEqual(currentStack, lastReportedStack)) {
return;
}
lastReportedStack = currentStack;
String stackTrace = EventDispatchThreadHangMonitor.stackTraceToString(currentStack);
JSONObject jsonObject = new JSONObject();
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormatThreadSafe.format(System.currentTimeMillis()));
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "swingWorker_" + hangNumber);
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Duration_Task_Execute"), timeSoFar());
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info"), stackTrace);
EventDispatchThreadHangMonitor.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG);
EventDispatchThreadHangMonitor.checkForDeadlock();
}
}
/**
* 来自SwingWorker类
*/
public static ThreadFactory threadFactory =
new ThreadFactory() {
final ThreadFactory defaultFactory =
Executors.defaultThreadFactory();
@Override
public Thread newThread(final Runnable r) {
Thread thread =
defaultFactory.newThread(r);
thread.setName("SwingWorker-"
+ thread.getName());
thread.setDaemon(true);
return thread;
}
};
public static CartonThreadExecutorPool getTimerThreadExecutorPool () {
if (cartonThreadExecutorPool == null) {
synchronized (CartonThreadExecutorPool.class) {
if (cartonThreadExecutorPool == null) {
cartonThreadExecutorPool =
new CartonThreadExecutorPool(MAX_WORKER_THREADS, MAX_WORKER_THREADS,
10L, TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>(),threadFactory
);
}
}
}
return cartonThreadExecutorPool;
}
private CartonThreadExecutorPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
simpleDateFormatThreadSafe.applyPattern("yyyy-MM-dd HH:mm:ss");
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
startReportedStack.set(t.getStackTrace());
concurrentHashMap.put(t.getId(), new ThreadInfo());
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
long currentThreadId = Thread.currentThread().getId();
long runTime = (System.currentTimeMillis() - concurrentHashMap.get(currentThreadId).startTime);
//加~是为了之后输出的时候换行。
if (isEasyWitch() && runTime > MAX_LIVE_TIME) {
JSONObject jsonObject = new JSONObject();
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormatThreadSafe.format(System.currentTimeMillis()));
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "swingWorker_" + concurrentHashMap.get(currentThreadId).hangNumber);
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Start_Time"), simpleDateFormatThreadSafe.format(concurrentHashMap.get(currentThreadId).startTime));
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), runTime);
EventDispatchThreadHangMonitor.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG);
}
concurrentHashMap.remove(currentThreadId);
}
public class Checker extends TimerTask {
@Override
public void run() {
if (cartonThreadExecutorPool == null || concurrentHashMap.isEmpty()) {
return;
}
for (Map.Entry<Long, ThreadInfo> map : concurrentHashMap.entrySet()) {
map.getValue().checkForHang();
}
}
}
public void initTimer() {
timer = new Timer("CheckerSwingWorker",true);
timer.schedule(new Checker(), 0, CHECK_INTERVAL_MS);
}
public void stopTimer() {
if (timer != null) {
timer.cancel();
}
}
}

45
designer-base/src/main/java/com/fr/design/carton/CartonUploadMessage.java

@ -0,0 +1,45 @@
package com.fr.design.carton;
public class CartonUploadMessage {
private String hangCount;
private String slowTime;
private String threadTime;
private String info;
public CartonUploadMessage() {
}
public String getHangCount() {
return hangCount;
}
public void setHangCount(String hangCount) {
this.hangCount = hangCount;
}
public String getSlowTime() {
return slowTime;
}
public void setSlowTime(String slowTime) {
this.slowTime = slowTime;
}
public String getThreadTime() {
return threadTime;
}
public void setThreadTime(String threadTime) {
this.threadTime = threadTime;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}

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

@ -0,0 +1,366 @@
package com.fr.design.carton;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.ProductConstantsBase;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.third.ibm.icu.text.SimpleDateFormat;
import org.jetbrains.annotations.NotNull;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.AWTEvent;
import java.awt.event.WindowEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
/**
* 参考自git swinghelper
* 用于卡顿检测
* 主要是两块内容
* 1.获取eventQueue中每个事件的执行时间
* 2.用一个Timer定时去检测当前执行任务的线程
*/
public final class EventDispatchThreadHangMonitor extends EventQueue {
/**
* 日期事件格式
*/
private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static final EventDispatchThreadHangMonitor INSTANCE = new EventDispatchThreadHangMonitor();
/**
* 一个timer
*/
private Timer timer;
/**
* 开启间隔检测后两次检测的相隔时间ms
*/
private static final long CHECK_INTERVAL_MS = 100;
/**
* 最大的事件允许执行时间超过该时间则打印堆栈等相关信息
*/
private static final long UNREASONABLE_DISPATCH_DURATION_MS = 1500;
/**
* 事件唯一编码用于方便日志的查看
*/
private static long hangCount = 0;
/**
* 输出日志所在地址
*/
private static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log");
/**
* 类似于一个开关当该值为默认的false启动时定时任务在窗口开启前都不会对执行的事件进行检查
*/
private boolean haveShownSomeComponent = false;
/**
* 该链表为主要的实现定时任务的容器在重写的dispatchEvent中由pre方法将DispatchInfo加入到链表由post方法remove
*/
private final LinkedList<DispatchInfo> dispatches = new LinkedList<DispatchInfo>();
/**
* 一个变量用于控制easy监测模式的开关
*/
private boolean easyWitch = false;
public boolean isEasyWitch() {
return easyWitch;
}
public void setEasyWitch(boolean easyWitch) {
this.easyWitch = easyWitch;
}
/**
* 一个变量用于记录Timer的开关
*/
public boolean isTimerWitch() {
return timerWitch;
}
public void setTimerWitch(boolean timerWitch) {
this.timerWitch = timerWitch;
}
private boolean timerWitch = false;
private synchronized static long getHangCount() {
return hangCount++;
}
/**
* @param a can not be null
* @param b can not be null
* @return
*/
public static boolean stacksEqual(@NotNull StackTraceElement[] a, @NotNull StackTraceElement[] b) {
if (!ArrayUtils.isSameLength(a, b)) {
return false;
}
for (int i = 0; i < a.length; ++i) {
if (!a[i].equals(b[i])) {
return false;
}
}
return true;
}
/**
* 用于判断是不是特定的堆栈
*/
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 isWaitingForNextEvent(StackTraceElement[] currentStack) {
return currentStack != null && currentStack.length >= 3 &&
stackTraceElementIs(currentStack[0], "java.lang.Object", "wait", true)
&& stackTraceElementIs(currentStack[1], "java.lang.Object", "wait", false)
&& stackTraceElementIs(currentStack[2], "java.awt.EventQueue", "getNextEvent", false);
}
/**
* event事件的包装类
*/
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 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 (isWaitingForNextEvent(currentStack)) {
return;
}
//某个事件执行时间很长,定时处理时可能会连续打很多个堆栈,对同一个事件的相同堆栈只打一次
if (lastReportedStack !=null && stacksEqual(lastReportedStack, currentStack)) {
return;
}
String stackTrace = stackTraceToString(currentStack);
lastReportedStack = currentStack;
JSONObject jsonObject = new JSONObject();
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormat.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());
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info"), stackTrace);
outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG);
checkForDeadlock();
}
//记录连续运行了多长时间
private long timeSoFar() {
return (System.currentTimeMillis() - lastDispatchTimeMillis);
}
//记录一个事件从被分发到结束的总运行时间
private long totalTime() {
return (System.currentTimeMillis() - startDispatchTimeMillis);
}
//事件处理完后的时间判断
public void dispose() {
if (totalTime() > UNREASONABLE_DISPATCH_DURATION_MS) {
JSONObject jsonObject = new JSONObject();
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormat.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"), simpleDateFormat.format(startDispatchTimeMillis));
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), totalTime() + "ms");
outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG);
}
}
}
public static void outPutJournalLog(String message, int flag) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String date = simpleDateFormat.format(System.currentTimeMillis());
String filename = flag == SwitchForSwingChecker.EASY_CHECK_FLAG ? SwitchForSwingChecker.EASY_CHECKER_FILE_NAME: SwitchForSwingChecker.TIMER_CHECKER_FILE_NAME;
String[] split = date.split("-");
int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]);
String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date);
File dirFile = new File(dirPath);
File file = new File( StableUtils.pathJoin(dirPath, filename));
try {
if (!file.exists()) {
if (!dirFile.exists()) {
dirFile.mkdirs();
}
file.createNewFile();
}
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, true));
String outputMessage = new StringBuilder(message.replaceAll("~", "\r\n")).append(",").append("\r\n").toString();
bufferedWriter.write(outputMessage);
bufferedWriter.close();
} catch (IOException e) {
FineLoggerFactory.getLogger().error("output fail", e);
}
}
private EventDispatchThreadHangMonitor() {
}
/**
* 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() {
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 (!isEasyWitch() && !isTimerWitch()) {
super.dispatchEvent(event);
} else {
try {
preDispatchEvent();
super.dispatchEvent(event);
} finally {
postDispatchEvent();
if (!haveShownSomeComponent &&
event instanceof WindowEvent && event.getID() == WindowEvent.WINDOW_OPENED) {
haveShownSomeComponent = true;
}
}
}
}
/**
* Starts tracking a dispatch.
*/
private synchronized void preDispatchEvent() {
synchronized (dispatches) {
dispatches.addLast(new DispatchInfo());
}
}
/**
* Stops tracking a dispatch.
*/
private synchronized void postDispatchEvent() {
synchronized (dispatches) {
DispatchInfo justFinishedDispatch = dispatches.removeLast();
if (isEasyWitch()) {
justFinishedDispatch.dispose();
}
//嵌套最深的事件执行完毕后刷新链表中其他事件的lastDispatchTimeMillis
Thread currentEventDispatchThread = Thread.currentThread();
for (DispatchInfo dispatchInfo : dispatches) {
if (dispatchInfo.eventDispatchThread == currentEventDispatchThread) {
dispatchInfo.lastDispatchTimeMillis = System.currentTimeMillis();
}
}
}
}
/**
* 检查死锁
*/
public static void checkForDeadlock() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadBean.findDeadlockedThreads();
if (threadIds == null) {
return;
}
FineLoggerFactory.getLogger().warn("deadlock detected involving the following threads:");
ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE);
for (ThreadInfo info : threadInfos) {
FineLoggerFactory.getLogger().warn("Thread # {} {} ( {} ) waiting on {} held by {} {}", info.getThreadId(), info.getThreadName(),
info.getThreadState(), info.getLockName(), info.getLockOwnerName(), stackTraceToStringForConsole(info.getStackTrace()));
}
}
public static String stackTraceToString(StackTraceElement[] stackTrace) {
StringBuilder result = new StringBuilder();
for (StackTraceElement stackTraceElement : stackTrace) {
String indentation = " ";
result.append("~").append(indentation).append(stackTraceElement);
}
return result.toString();
}
public static String stackTraceToStringForConsole(StackTraceElement[] stackTrace) {
StringBuilder result = new StringBuilder();
for (StackTraceElement stackTraceElement : stackTrace) {
String indentation = " ";
result.append("\r\n").append(indentation).append(stackTraceElement);
}
return result.toString();
}
}

330
designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java

@ -0,0 +1,330 @@
package com.fr.design.carton;
import com.fr.decision.webservice.v10.log.download.utils.LogZipUtils;
import com.fr.design.DesignerEnvManager;
import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.gui.date.UIDatePicker;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.env.detect.ui.EnvDetectorDialog;
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 com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.io.File;
import java.text.ParseException;
import java.util.List;
public class FeedbackToolboxDialog extends JDialog {
private UIDatePicker uiDatePicker;
private JPanel generalSettingPanel = null;
private UICheckBox easyCheckerButton = null;
private UICheckBox timerCheckerButton = null;
private UIButton uploadButton = null;
private UILabel exportLogLabel = null;
private final Color backgroundColor = new Color(240, 240, 243, 1);
private final Color lineColor = new Color(192, 192, 192, 120);
private JPanel body = null;
private static final String WORK_SPACE_PATH = "reportlets";
public FeedbackToolboxDialog(Frame owner) {
super(owner, Toolkit.i18nText("Fine-Design_Basic_Carton_Feedback_ToolBox"));
setResizable(false);
this.setLayout(FRGUIPaneFactory.createBorderLayout());
createBodyPanel();
add(body);
setSize(body.getPreferredSize());
setSwitches(!StringUtils.isEmpty(GeneralUtils.objectToString(uiDatePicker.getSelectedItem())));
repaint();
GUICoreUtils.centerWindow(this);
}
public void createBodyPanel() {
JPanel body = FRGUIPaneFactory.createBorderLayout_L_Pane();
body.setBackground(backgroundColor);
JPanel titlePane = createTitlePane();
JPanel tailPane = createTailPane();
JPanel midPane = createMidPane();
JPanel infoPane = createInfoPane();
body.add(titlePane, BorderLayout.NORTH);
body.add(tailPane, BorderLayout.SOUTH);
body.add(midPane, BorderLayout.CENTER);
midPane.add(infoPane, BorderLayout.NORTH);
Dimension dimension = new Dimension(662, 556);
body.setPreferredSize(dimension);
this.body = body;
}
private JPanel createInfoPane() {
JPanel northPane = FRGUIPaneFactory.createNColumnGridInnerContainer_Pane(2, 10, 10);
UILabel title = new UILabel();
//空格布局会好看一点
title.setText(" " + Toolkit.i18nText("Fine-Design_Basic_Carton_Record_Lag_Time") + ": ");
//判断一下当天是否有卡顿日志记录,如果有将日期设置为当天,如果没有设置为空
boolean cartonExists = SwitchForSwingChecker.isCartonExists();
if (cartonExists) {
this.uiDatePicker = new UIDatePicker(UIDatePicker.STYLE_CN_DATE1, this);
} else {
this.uiDatePicker = new UIDatePicker(UIDatePicker.STYLE_CN_DATE1, null, this);
}
Dimension dimension = new Dimension(160, 100);
uiDatePicker.setPreferredSize(dimension);
northPane.add(GUICoreUtils.createFlowPane(new Component[]{title, uiDatePicker}, FlowLayout.LEFT));
exportLogLabel = new UILabel();
exportLogLabel.setText(Toolkit.i18nText("Fine-Design_Basic_Carton_Export_Carton_Log"));
exportLogLabel.setForeground(UIConstants.FLESH_BLUE);
exportLogLabel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (exportLogLabel.isEnabled()) {
exportLogFile();
}
}
@Override
public void mouseEntered(MouseEvent evt) {
Object source = evt.getSource();
if (source instanceof UILabel) {
((UILabel) source).setCursor(new Cursor(Cursor.HAND_CURSOR));
}
}
});
northPane.add(GUICoreUtils.createFlowPane(exportLogLabel, FlowLayout.RIGHT));
return northPane;
}
private void exportLogFile() {
String selectDate = GeneralUtils.objectToString(uiDatePicker.getSelectedItem());
FILEChooserPane fileChooserPane = FILEChooserPane.getInstance();
StringBuilder fileName = new StringBuilder();
fileName.append(selectDate).append(Toolkit.i18nText("Fine-Design_Basic_Carton_Carton_Log"));
fileChooserPane.setFileNameTextField(fileName.toString(), " ");
fileChooserPane.removeAllFilter();
fileChooserPane.addChooseFILEFilter(new ChooseFileFilter("zip", Toolkit.i18nText("Fine-Design_Basic_Carton_Compile_File")));
int chooseResult = fileChooserPane.showSaveDialog(DesignerContext.getDesignerFrame());
if (chooseResult == 0) {
FILE selectedFile = fileChooserPane.getSelectedFILE();
String path = selectedFile.getPath();
//selectDate 2002-03-09例子
String[] split = selectDate.split("-");
int month = Integer.parseInt(split[1]);
File sourceFile = new File(StableUtils.pathJoin(SwitchForSwingChecker.JOURNAL_FILE_PATH, split[0], "month-" + month, selectDate));
if (sourceFile.exists()) {
File[] files = sourceFile.listFiles();
if (files != null) {
try {
if (path.startsWith(WORK_SPACE_PATH)) {
String curEnvName = DesignerEnvManager.getEnvManager().getCurEnvName();
DesignerWorkspaceInfo workspaceInfo = DesignerEnvManager.getEnvManager().getWorkspaceInfo(curEnvName);
String workspaceInfoPath = workspaceInfo.getPath();
path = new StringBuilder(workspaceInfoPath).append(path.substring(10)).toString();
}
LogZipUtils.compress(files, path, false);
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Report_Exported_Successfully"));
} catch (Exception exception) {
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Report_Export_Failed"), UIManager.getString("OptionPane.messageDialogTitle"), JOptionPane.ERROR_MESSAGE);
FineLoggerFactory.getLogger().error("export file fail", exception);
}
}
}
fileChooserPane.removeAllFilter();
}
}
private JPanel createTailPane() {
JPanel tailPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
tailPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, lineColor));
JPanel actionsPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
actionsPanel.setLayout(FRGUIPaneFactory.createM_BorderLayout());
{
uploadButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Carton_Upload_Carton_Log"));
uploadButton.addActionListener((e) -> {
try {
List<CartonUploadMessage> list = SwitchForSwingChecker.uploadJournalLog(uiDatePicker.getSelectedDate());
if (list.isEmpty()) {
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine_Design_Basic_Upload_Fail"), UIManager.getString("OptionPane.messageDialogTitle"), JOptionPane.ERROR_MESSAGE);
} else {
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Basic_Upload_Success"));
}
} catch (ParseException parseException) {
FineLoggerFactory.getLogger().error("parse error", parseException);
}
});
actionsPanel.add(uploadButton, BorderLayout.WEST);
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel"));
cancelButton.addActionListener((e) -> {
setVisible(false);
EnvDetectorDialog envDetectorDialog = new EnvDetectorDialog(DesignerContext.getDesignerFrame());
envDetectorDialog.setVisible(true);
dispose();
});
actionsPanel.add(cancelButton, BorderLayout.EAST);
}
UIButton currencySetButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Carton_General_Settings"));
currencySetButton.addActionListener((e -> {
createGeneralSettingPanel();
this.remove(body);
this.add(generalSettingPanel);
setSize(generalSettingPanel.getPreferredSize());
repaint();
setVisible(true);
}));
tailPanel.add(actionsPanel, BorderLayout.EAST);
tailPanel.add(currencySetButton, BorderLayout.WEST);
return tailPanel;
}
private JPanel createTitlePane() {
JPanel titlePane = FRGUIPaneFactory.createBorderLayout_M_Pane();
titlePane.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, lineColor));
UILabel uiLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Carton_Carton_Journal_Record"));
uiLabel.setForeground(UIConstants.FLESH_BLUE);
titlePane.add(uiLabel, BorderLayout.WEST);
return titlePane;
}
private JPanel createMidPane() {
JPanel midPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
return midPanel;
}
/**
* 下面是通用设置的面板
*/
private void createGeneralSettingPanel() {
JPanel generalSettingPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
JPanel tailPaneInGeneralSettings = createTailPaneInGeneralSettings();
generalSettingPanel.add(tailPaneInGeneralSettings, BorderLayout.SOUTH);
JPanel titlePaneInGeneralSettings = createTitlePaneInGeneralSettings();
generalSettingPanel.add(titlePaneInGeneralSettings, BorderLayout.NORTH);
JPanel midPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
generalSettingPanel.add(midPanel, BorderLayout.CENTER);
JPanel infoPane = createInfoPanelInGeneralSettings();
midPanel.add(infoPane, BorderLayout.NORTH);
Dimension dimension = new Dimension(662, 556);
generalSettingPanel.setPreferredSize(dimension);
generalSettingPanel.setBackground(backgroundColor);
this.generalSettingPanel = generalSettingPanel;
}
private JPanel createTitlePaneInGeneralSettings() {
JPanel titlePane = FRGUIPaneFactory.createBorderLayout_L_Pane();
titlePane.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, lineColor));
UILabel uiLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Carton_Carton_Journal_Record") + "/");
uiLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
createBodyPanel();
remove(generalSettingPanel);
add(body);
setPreferredSize(body.getPreferredSize());
setSwitches(!StringUtils.isEmpty(GeneralUtils.objectToString(uiDatePicker.getSelectedItem())));
repaint();
setVisible(true);
}
@Override
public void mouseEntered(MouseEvent evt) {
Object source = evt.getSource();
if (source instanceof UILabel) {
((UILabel) source).setCursor(new Cursor(Cursor.HAND_CURSOR));
}
}
});
UILabel uiCurrentLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Carton_General_Settings"));
uiCurrentLabel.setForeground(UIConstants.FLESH_BLUE);
titlePane.add(GUICoreUtils.createFlowPane(new Component[]{uiLabel, uiCurrentLabel}, FlowLayout.LEFT));
return titlePane;
}
private JPanel createTailPaneInGeneralSettings() {
JPanel tailPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
tailPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, lineColor));
JPanel actionsPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
actionsPanel.setLayout(FRGUIPaneFactory.createM_BorderLayout());
{
UIButton confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Save"));
confirmButton.addActionListener((e) -> {
if (easyCheckerButton.isSelected()) {
SwitchForSwingChecker.startEasyChecker();
} else {
SwitchForSwingChecker.stopEasyChecker();
}
if (timerCheckerButton.isSelected()) {
SwitchForSwingChecker.startTimerChecker();
} else {
SwitchForSwingChecker.stopTimerChecker();
}
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Basic_Common_Save_Successfully"));
});
actionsPanel.add(confirmButton, BorderLayout.WEST);
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel"));
cancelButton.addActionListener((e) -> {
createBodyPanel();
remove(generalSettingPanel);
add(body);
setPreferredSize(body.getPreferredSize());
repaint();
setVisible(true);
});
actionsPanel.add(cancelButton, BorderLayout.EAST);
}
tailPanel.add(actionsPanel, BorderLayout.EAST);
return tailPanel;
}
private JPanel createInfoPanelInGeneralSettings() {
JPanel infoPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(1);
easyCheckerButton = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Carton_Operation_Time_Consuming_Detection"));
timerCheckerButton = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Carton_Carton_Operation_Class_Capture"));
easyCheckerButton.setSelected(SwitchForSwingChecker.isEasyChecker());
timerCheckerButton.setSelected(SwitchForSwingChecker.isCheckerTimerSwitch());
infoPane.add(GUICoreUtils.createFlowPane(easyCheckerButton, FlowLayout.LEFT));
infoPane.add(GUICoreUtils.createFlowPane(timerCheckerButton, FlowLayout.LEFT));
return infoPane;
}
@Override
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
EnvDetectorDialog envDetectorDialog = new EnvDetectorDialog(DesignerContext.getDesignerFrame());
envDetectorDialog.setVisible(true);
}
}
/**
* 上传和导出卡顿日志的可用化处理如果没有选择日期就不可用
*/
public void setSwitches(boolean flag) {
uploadButton.setEnabled(flag);
exportLogLabel.setEnabled(flag);
}
}

36
designer-base/src/main/java/com/fr/design/carton/MonthlyCartonFile.java

@ -0,0 +1,36 @@
package com.fr.design.carton;
import java.io.File;
public class MonthlyCartonFile {
private File currentMonthFile;
private File lastMonthFile;
private File nextMonthFile;
public MonthlyCartonFile() {
}
public File getCurrentMonthFile() {
return currentMonthFile;
}
public void setCurrentMonthFile(File currentMonthFile) {
this.currentMonthFile = currentMonthFile;
}
public File getLastMonthFile() {
return lastMonthFile;
}
public void setLastMonthFile(File lastMonthFile) {
this.lastMonthFile = lastMonthFile;
}
public File getNextMonthFile() {
return nextMonthFile;
}
public void setNextMonthFile(File nextMonthFile) {
this.nextMonthFile = nextMonthFile;
}
}

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

@ -0,0 +1,240 @@
package com.fr.design.carton;
import com.fr.design.i18n.Toolkit;
import com.fr.general.GeneralUtils;
import com.fr.json.JSON;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ProductConstantsBase;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import sun.awt.AppContext;
import javax.swing.SwingWorker;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Date;
import java.util.Calendar;
public class SwitchForSwingChecker {
/**
* /定时任务的开关
*/
private static boolean checkerTimerSwitch = false;
/**
* /简单记录事件执行时间的开关
*/
private static boolean easyChecker = false;
/**
* 一个标识位用于区分耗时任务时长检测(简单检测)和timer检测
*/
public static final int TIMER_CHECK_FLAG = 0;
public static final int EASY_CHECK_FLAG = 1;
/**
* /日志存储地址
*/
public static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log");
public static final String EASY_CHECKER_FILE_NAME = "easy_check_log.csv";
public static final String TIMER_CHECKER_FILE_NAME = "timer_check_log.csv";
public static boolean isCheckerTimerSwitch() {
return checkerTimerSwitch;
}
public static boolean isEasyChecker() {
return easyChecker;
}
public static void startTimerChecker() {
if (!checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.initTimer();
CartonThreadExecutorPool.getTimerThreadExecutorPool().initTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(true);
checkerTimerSwitch = true;
}
}
public static void stopTimerChecker() {
if (checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.stopTimer();
CartonThreadExecutorPool.getTimerThreadExecutorPool().stopTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(false);
checkerTimerSwitch = false;
}
}
public static void startEasyChecker() {
if (!easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(true);
CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(true);
easyChecker = true;
}
}
public static void stopEasyChecker() {
if (easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(false);
CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(false);
easyChecker = false;
}
}
/**
* 获取文件名字以及判断文件是否存在
*/
private static CartonFiles getFiles(String date) {
String[] split = date.split("-");
int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]);
String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date);
File file1 = new File(StableUtils.pathJoin(dirPath, EASY_CHECKER_FILE_NAME));
File file2 = new File(StableUtils.pathJoin(dirPath, TIMER_CHECKER_FILE_NAME));
File[] files = new File[2];
files[0] = file1;
files[1] = file2;
CartonFiles cartonFiles = new CartonFiles();
cartonFiles.setEasyCheckerFile(file1);
cartonFiles.setTimerCheckerFile(file2);
return cartonFiles;
}
/**
*处理文件
* 一共四种情况
* 两个文件都不存在
* 文件一存在文件二不存在
* 文件二存在文件一不存在
* 两个文件都存在
*/
private static List<CartonUploadMessage> getCartonLog(File easyFile, File timerFile) {
List<CartonUploadMessage> res = new ArrayList<>();
List<CartonUploadMessage> easyFileCartonLog = getEasyFileCartonLog(easyFile);
List<CartonUploadMessage> timerFileCartonLog = getTimerFileCartonLog(timerFile);
Map<String, CartonUploadMessage> easyFileMap = new HashMap<>();
for (CartonUploadMessage cartonUploadMessage : easyFileCartonLog) {
easyFileMap.put(cartonUploadMessage.getHangCount(), cartonUploadMessage);
res.add(cartonUploadMessage);
}
for (CartonUploadMessage cartonUploadMessage : timerFileCartonLog) {
String hangCount = cartonUploadMessage.getHangCount();
if (easyFileMap.containsKey(hangCount)) {
cartonUploadMessage.setThreadTime(easyFileMap.get(hangCount).getThreadTime());
}
res.add(cartonUploadMessage);
}
return res;
}
private static List<CartonUploadMessage> getTimerFileCartonLog(File file) {
List<CartonUploadMessage> res = new ArrayList<>();
try {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[");
BufferedReader bufferedReader1 = new BufferedReader(new FileReader(file));
String line1;
while ((line1 = bufferedReader1.readLine()) != null) {
stringBuilder.append(line1);
}
bufferedReader1.close();
stringBuilder.append("]");
JSONArray easyCheckerJSON = JSON.ARRAY.createJSON(GeneralUtils.objectToString(stringBuilder));
for (Object jsonObject : easyCheckerJSON) {
CartonUploadMessage cartonUploadMessage = new CartonUploadMessage();
JSONObject x = (JSONObject) jsonObject;
cartonUploadMessage.setHangCount(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number")));
cartonUploadMessage.setSlowTime(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time")) + "ms");
cartonUploadMessage.setThreadTime("undefined");
//这个跟输出到文件中的格式匹配,参考EventDis里的stackTraceToString方法
String indentation = " ";
String logMessage = x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info")).replaceAll(indentation, "\r\n ");
cartonUploadMessage.setInfo(logMessage);
res.add(cartonUploadMessage);
}
} catch (IOException e) {
FineLoggerFactory.getLogger().error("upload fail", e);
}
return res;
}
private static List<CartonUploadMessage> getEasyFileCartonLog(File file) {
List<CartonUploadMessage> res = new ArrayList<>();
try {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[");
BufferedReader bufferedReader1 = new BufferedReader(new FileReader(file));
String line1;
while ((line1 = bufferedReader1.readLine()) != null) {
stringBuilder.append(line1);
}
bufferedReader1.close();
stringBuilder.append("]");
JSONArray timerCheckerJSON = JSON.ARRAY.createJSON(GeneralUtils.objectToString(stringBuilder));
for (Object jsonObject : timerCheckerJSON) {
JSONObject x = (JSONObject) jsonObject;
CartonUploadMessage cartonUploadMessage = new CartonUploadMessage();
cartonUploadMessage.setHangCount(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number")));
cartonUploadMessage.setSlowTime(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time")));
cartonUploadMessage.setThreadTime(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time")));
cartonUploadMessage.setInfo("undefined");
res.add(cartonUploadMessage);
}
} catch (IOException e) {
FineLoggerFactory.getLogger().error("upload fail", e);
}
return res;
}
/**
* /埋点方法上传卡顿信息入口
date为 2022-09-08的格式
*/
public static List<CartonUploadMessage> uploadJournalLog(Date dateTime) {
List<CartonUploadMessage> res = new ArrayList<>();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
CartonFiles files = getFiles(simpleDateFormat.format(dateTime));
File easyCheckerFile = files.getEasyCheckerFile();
File timerCheckerFile = files.getTimerCheckerFile();
if (easyCheckerFile.exists() && timerCheckerFile.exists()) {
return getCartonLog(easyCheckerFile, timerCheckerFile);
} else if (easyCheckerFile.exists()) {
return getEasyFileCartonLog(easyCheckerFile);
} else if (timerCheckerFile.exists()) {
return getTimerFileCartonLog(timerCheckerFile);
} else {
return res;
}
}
/**
* 初始化监控任务主要是替换EventQueue以及SwingWorker执行任务的线程池
*/
public static void initThreadMonitoring () {
EventDispatchThreadHangMonitor.initMonitoring();
AppContext.getAppContext().put(SwingWorker.class, CartonThreadExecutorPool.getTimerThreadExecutorPool());
}
/**
* 判断是否有指定日期的卡顿日志没有就返回false
*/
public static boolean isCartonExists(Date date) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String format = simpleDateFormat.format(date);
Calendar calendar = Calendar.getInstance();
int month = calendar.get(Calendar.MONTH) + 1;
int year = calendar.get(Calendar.YEAR);
File file = new File(StableUtils.pathJoin(JOURNAL_FILE_PATH, String.valueOf(year), "month-" + month, format));
return file.exists();
}
public static boolean isCartonExists() {
return isCartonExists(new Date());
}
}

6
designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java

@ -3,9 +3,9 @@ package com.fr.design.data.datapane;
import com.fr.base.TableData;
import com.fr.base.TableDataBean;
import com.fr.config.RemoteConfigEvent;
import com.fr.data.MultiResultTableData;
import com.fr.data.TableDataSource;
import com.fr.data.api.StoreProcedureAssist;
import com.fr.data.impl.storeproc.StoreProcedure;
import com.fr.design.data.BasicTableDataUtils;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.dialog.FineJOptionPane;
@ -69,10 +69,10 @@ public class TableDataPaneListPane extends JListControlPane implements TableData
return;
}
if (editingType instanceof StoreProcedure && isIncludeUnderline(tempName)) {
if (editingType instanceof MultiResultTableData<?> && isIncludeUnderline(tempName)) {
isNamePermitted = false;
nameableList.stopEditing();
FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataPaneListPane.this), Toolkit.i18nText("Fine-Design_Basic_Stored_Procedure_Name_Tips"));
FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataPaneListPane.this), Toolkit.i18nText("Fine-Design_Basic_Multi_Result_Table_Data_Name_Tips"));
setIllegalIndex(editingIndex);
return;
}

35
designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java

@ -1,7 +1,9 @@
package com.fr.design.data.datapane;
import com.fr.base.TableData;
import com.fr.data.MultiResultTableData;
import com.fr.data.TableDataSource;
import com.fr.data.api.StoreProcedureAssist;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.TableDataSourceDependent;
import com.fr.design.DesignModelAdapter;
@ -15,10 +17,10 @@ import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.StrategyConfigAttrUtils;
import com.fr.design.data.datapane.auth.TableDataAuthHelper;
import com.fr.design.data.datapane.management.clip.TableDataTreeClipboard;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.datapane.management.search.pane.TableDataSearchRemindPane;
import com.fr.design.data.datapane.management.search.pane.TreeSearchToolbarPane;
import com.fr.design.data.datapane.management.search.searcher.TableDataSearchMode;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.tabledata.StoreProcedureWorkerListener;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
@ -121,6 +123,7 @@ public class TableDataTreePane extends BasicTableDataTreePane {
/**
* 获取不必每次都refreshDockingView的数据集树面板
* 不会主动替换DesignModelAdapter需要保证使用时没有跨模板动作谨慎使用
*
* @param tc
* @return
*/
@ -484,7 +487,7 @@ public class TableDataTreePane extends BasicTableDataTreePane {
tdNamePanel.addPropertyChangeListener(new PropertyChangeAdapter() {
@Override
public void propertyChange() {
doPropertyChange(dg, tdNamePanel, oldName);
checkNameChange(tableDataPane, dg, tdNamePanel, oldName);
}
});
// 有些数据集(DBTableData)面板的初始化过程中是包含了SwingWorker处理(查询数据连接、查表等)的
@ -494,6 +497,34 @@ public class TableDataTreePane extends BasicTableDataTreePane {
});
}
private void checkNameChange(AbstractTableDataPane<?> tableDataPane, BasicDialog dg, BasicPane.NamePane nPanel, final String oldName) {
nPanel.setShowText(StringUtils.BLANK);
dg.setButtonEnabled(true);
String tempName = nPanel.getObjectName();
if (StringUtils.isBlank(tempName)) {
nPanel.setShowText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Table_Data_Empty_Name_Tips"));
dg.setButtonEnabled(false);
} else if (!ComparatorUtils.equals(oldName, tempName) && isDsNameRepeaded(tempName)) {
nPanel.setShowText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Table_Data_Duplicate_Name_Tips", tempName));
dg.setButtonEnabled(false);
} else if (oldName.length() >= PROCEDURE_NAME_INDEX && tableDataPane.updateBean() instanceof MultiResultTableData) {
if (isIncludeUnderline(tempName)) {
nPanel.setShowText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Multi_Result_Table_Data_Name_Tips"));
dg.setButtonEnabled(false);
}
} else if (!BasicTableDataUtils.checkName(tempName)) {
dg.setButtonEnabled(false);
} else {
nPanel.setShowText(StringUtils.BLANK);
dg.setButtonEnabled(true);
}
}
private boolean isIncludeUnderline(String name) {
return !ComparatorUtils.equals(name.indexOf(StoreProcedureAssist.GROUP_MARKER), -1);
}
@Override
public void removeTableData(String sourceName) {
TableDataSource tds = this.tc.getBook();

135
designer-base/src/main/java/com/fr/design/gui/date/UICalendarPanel.java

@ -2,6 +2,8 @@ package com.fr.design.gui.date;
import com.fr.base.BaseUtils;
import com.fr.base.background.GradientBackground;
import com.fr.design.carton.MonthlyCartonFile;
import com.fr.design.carton.SwitchForSwingChecker;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
@ -9,7 +11,10 @@ import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.gui.GUIPaintUtils;
import com.fr.general.GeneralUtils;
import com.fr.stable.Constants;
import com.fr.stable.ProductConstantsBase;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
@ -40,16 +45,20 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.RoundRectangle2D;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
public class UICalendarPanel extends JPanel {
private static final Font FONT_UI = DesignUtils.getDefaultGUIFont().applySize(12);
private static final Font FONT_BLACK = new Font(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Black_Font"), Font.PLAIN, 12);
private static final int WEEKDAY_COUNT = 7;
private static final int TOTAL_DAYS_COUNT = 42;
//卡顿日志所在地址
private static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log");
protected Color selectedBackground;
protected Color selectedForeground;
protected Color background;
@ -63,12 +72,27 @@ public class UICalendarPanel extends JPanel {
private boolean isSupportDateChangeListener = false;
private java.util.Date selectedDate = null;
private boolean isTimePicker;
private final Color LABEL_FORGE_GROUND = new Color(0x6F6F6);
private MouseListener todayListener;
private UIDayLabel lbToday;
/**
* 一个int类型用于判断日历是否是专门用于处理卡顿的设计器反馈箱中的日历
* 0表示是
* -1表示不是
*/
private boolean speciallyForCarton = false;
/**
* 年月格式
*/
final SimpleDateFormat monthFormat
= new SimpleDateFormat("yyyy-MM");
/**
* 年月格式2
*/
final SimpleDateFormat dayFormat
= new SimpleDateFormat("yyyy-MM-dd");
public UICalendarPanel() {
this(new Date(), false);
}
@ -77,6 +101,14 @@ public class UICalendarPanel extends JPanel {
this(new Date(), isTimerPicker);
}
/**
* 构造函数用于给speciallyForCarton赋值
*/
public UICalendarPanel(boolean isTimePicker, boolean speciallyForCarton) {
this(new Date(), isTimePicker);
this.speciallyForCarton = speciallyForCarton;
initTodayListener();
}
public UICalendarPanel(Date selectedDate, boolean isTimerPicker) {
this.selectedDate = selectedDate;
@ -106,7 +138,12 @@ public class UICalendarPanel extends JPanel {
updateHMS();
}
}
private void initTodayListener() {
if (speciallyForCarton && !SwitchForSwingChecker.isCartonExists()) {
lbToday.setEnabled(false);
lbToday.removeMouseListener(todayListener);
}
}
// << < yyyy/MM/dd > >>
private JPanel createNorthPane() {
JPanel pNorth = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane();
@ -187,13 +224,13 @@ public class UICalendarPanel extends JPanel {
GradientPane pToday = new GradientPane(new GradientBackground(new Color(0x097BDA), new Color(0x40A3EE), GradientBackground.TOP2BOTTOM), false);
pToday.setPreferredSize(new Dimension(216, 18));
pToday.setLayout(new BorderLayout());
UIDayLabel lbToday = new UIDayLabel(new Date(), false);
lbToday = new UIDayLabel(new Date(), false);
lbToday.setForeground(new Color(0x000000));
lbToday.addMouseListener(createTodayListener(pToday, lbToday));
todayListener = createTodayListener(pToday, lbToday);
lbToday.addMouseListener(todayListener);
pToday.setBackground(new Color(0xF0F0F0));
pToday.add(lbToday, BorderLayout.CENTER);
pCenter.add(pToday, BorderLayout.SOUTH);
return pCenter;
}
@ -288,10 +325,67 @@ public class UICalendarPanel extends JPanel {
};
}
/**
*根据当月获取下个月
* 圈复杂度比较高就单独拿出来了
*/
private int getNextMonth(int month) {
int num = (month + 1) % 12;
return num == 0 ? 12 : num;
}
private int getYearOfNextMonth(int month, int year) {
return year + (month + 1) / 13;
}
/**
* 将配置目录中已有的所有卡顿日志文件的名字如2022-08-09加入到set中
*/
private void addFileIntoSet(Set<String> set, MonthlyCartonFile monthlyCartonFile) {
File currentMonthFile = monthlyCartonFile.getCurrentMonthFile();
File lastMonthFile = monthlyCartonFile.getLastMonthFile();
File nextMonthFile = monthlyCartonFile.getNextMonthFile();
File[] monthFiles = new File[3];
monthFiles[0] = lastMonthFile;
monthFiles[1] = currentMonthFile;
monthFiles[2] = nextMonthFile;
for (File file : monthFiles) {
if (file.exists() && file.isDirectory()) {
File[] files = file.listFiles();
for (File detailFile : files) {
set.add(detailFile.getName());
}
}
}
}
/**
* 给label设置属性
*/
private void setUIDayLabel(UIDayLabel label, boolean isCurrentMonth,
Calendar setupCalendar, Set<String> logSet) {
/**
* 区分开两种panel
*/
if (speciallyForCarton) {
if (!logSet.contains(GeneralUtils.objectToString(dayFormat.format(setupCalendar.getTime())))) {
label.setEnabled(false);
} else {
label.addMouseListener(dayBttListener);
}
} else {
label.addMouseListener(dayBttListener);
label.setEnabled(isCurrentMonth);
}
if (!isCurrentMonth) {
label.setForeground(LABEL_FORGE_GROUND);
}
}
/**
* 更新日期
*/
protected void updateDays() {
/**
* 用于处理卡顿日志日历的一些工具
*/
Set<String> logSet = new HashSet<>();
//更新月份
monthLabel.setText(monthFormat.format(calendar.getTime()));
days.removeAll();
@ -302,8 +396,29 @@ public class UICalendarPanel extends JPanel {
setupCalendar.set(Calendar.DAY_OF_MONTH, 1);
int first = setupCalendar.get(Calendar.DAY_OF_WEEK);
setupCalendar.add(Calendar.DATE, -first);
boolean isCurrentMonth = false;
if (speciallyForCarton) {
Calendar clone = (Calendar)setupCalendar.clone();
clone.add(Calendar.DATE, 1);
int year = clone.get(Calendar.YEAR);
//日历获取的月份是从0开始的
int month = clone.get(Calendar.MONTH) + 1;
//往后推一个月的年月份
int month2 = getNextMonth(month);
int year2 = getYearOfNextMonth(month, year);
//再往后推一个月的年月份
int month3 = getNextMonth(month2);
int year3 = getYearOfNextMonth(month2, year2);
//文件地址如:"C:\Users\23131\.FineReport110\journal_log\2022\month-9\2022-09-01"
MonthlyCartonFile monthlyCartonFile = new MonthlyCartonFile();
monthlyCartonFile.setCurrentMonthFile
(new File(StableUtils.pathJoin(JOURNAL_FILE_PATH, String.valueOf(year2), "month-" + month2)));
monthlyCartonFile.setLastMonthFile
(new File(StableUtils.pathJoin(JOURNAL_FILE_PATH, String.valueOf(year), "month-" + month)));
monthlyCartonFile.setNextMonthFile
(new File(StableUtils.pathJoin(JOURNAL_FILE_PATH, String.valueOf(year3), "month-" + month3)));
addFileIntoSet(logSet, monthlyCartonFile);
}
for (int i = 0; i < TOTAL_DAYS_COUNT; i++) {
setupCalendar.add(Calendar.DATE, 1);
GradientPane gp = new GradientPane(new GradientBackground(new Color(0xFEFEFE), new Color(0xF3F2F3), GradientBackground.TOP2BOTTOM), true);
@ -313,14 +428,10 @@ public class UICalendarPanel extends JPanel {
UIDayLabel label = new UIDayLabel(setupCalendar.getTime());
label.setHorizontalAlignment(SwingConstants.RIGHT);
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 9));
label.addMouseListener(dayBttListener);
if ("1".equals(label.getText())) {
isCurrentMonth = !isCurrentMonth;
}
label.setEnabled(isCurrentMonth);
if (!isCurrentMonth) {
label.setForeground(new Color(0x6F6F6));
}
setUIDayLabel(label, isCurrentMonth, setupCalendar, logSet);
//当前选择的日期
if (setupCalendar.get(Calendar.DAY_OF_MONTH) == selectedCalendar.get(Calendar.DAY_OF_MONTH) && isCurrentMonth) {
gp.setGradientBackground(new GradientBackground(new Color(0x097BD9), new Color(0x41A3EE), GradientBackground.TOP2BOTTOM));
@ -534,6 +645,7 @@ public class UICalendarPanel extends JPanel {
this.setLayout(new GridLayout(6, 7, 1, 1));
this.setBackground(new Color(0xFFFFFF));
this.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(0xDADADA)));
}
public void paint(Graphics g) {
@ -754,7 +866,6 @@ public class UICalendarPanel extends JPanel {
public static void main(String[] args) {
JFrame frame = new JFrame();
UICalendarPanel calendarPanel = new UICalendarPanel();
final UITextField field = new UITextField();
field.setPreferredSize(new Dimension(120, 25));

59
designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java

@ -7,6 +7,7 @@ import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.design.carton.FeedbackToolboxDialog;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
@ -32,6 +33,11 @@ import java.util.Date;
* UIDatePicker
*/
public class UIDatePicker extends UIComboBox implements Serializable {
/**
* 用于记录本datePicker是否是由设计器卡顿优化箱上打开后续要去调用方法
*/
private FeedbackToolboxDialog feedbackToolboxDialog = null;
/**
* 日期格式类型
*/
@ -40,7 +46,7 @@ public class UIDatePicker extends UIComboBox implements Serializable {
public static final int STYLE_CN_DATETIME = 2;
public static final int STYLE_CN_DATETIME1 = 3;
public static final int STYLE_EN_DATE = 4;
public boolean isWillHide = false;
private boolean willHide = false;
/**
* 日期格式类型
*/
@ -67,25 +73,45 @@ public class UIDatePicker extends UIComboBox implements Serializable {
this(formatStyle, new Date());
}
public UIDatePicker(int formatStyle, Date initialDatetime) throws UnsupportedOperationException {
public UIDatePicker(int formatStyle, FeedbackToolboxDialog feedbackToolboxDialog) throws UnsupportedOperationException {
this(formatStyle, new Date(), feedbackToolboxDialog);
}
/**
*
* @param formatStyle
* @param initialDatetime
* @param feedbackToolboxDialog 判断该日历是否由设计器反馈工具箱打开
* @throws UnsupportedOperationException
*/
public UIDatePicker(int formatStyle, Date initialDatetime, FeedbackToolboxDialog feedbackToolboxDialog) throws UnsupportedOperationException {
this.setStyle(formatStyle);
//设置可编辑
this.setEditable(true);
this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
//设置编辑器属性(只能输入正确日期)
JTextField textField = ((JTextField) getEditor().getEditorComponent());
textField.setHorizontalAlignment(SwingConstants.CENTER);
if (feedbackToolboxDialog != null) {
dateDocument = new JDateDocument(textField, this.dateFormat, StringUtils.EMPTY);
this.feedbackToolboxDialog = feedbackToolboxDialog;
textField.setHorizontalAlignment(SwingConstants.LEFT);
//设置当前选择日期
this.setSelectedItem(initialDatetime);
} else {
dateDocument = new JDateDocument(textField, this.dateFormat);
this.setSelectedItem(initialDatetime == null ? new Date() : initialDatetime);
textField.setHorizontalAlignment(SwingConstants.CENTER);
}
textField.setDocument(dateDocument);
//设置Model为单值Model
this.setModel(model);
//设置当前选择日期
this.setSelectedItem(initialDatetime == null ? new Date() : initialDatetime);
updateUI();
}
public UIDatePicker(int formatStyle, Date initialDatetime) throws UnsupportedOperationException {
this(formatStyle, initialDatetime, null);
}
/**
* 设置日期格式
* STYLE_CN_DATE
@ -182,12 +208,14 @@ public class UIDatePicker extends UIComboBox implements Serializable {
*/
class DatePopup extends BasicComboPopup implements ChangeListener {
UICalendarPanel calendarPanel = null;
public DatePopup(JComboBox box) {
super(box);
setLayout(FRGUIPaneFactory.createBorderLayout());
if (feedbackToolboxDialog != null) {
calendarPanel = new UICalendarPanel(formatStyle > 1, true);
} else {
calendarPanel = new UICalendarPanel(formatStyle > 1);
}
calendarPanel.addDateChangeListener(this);
add(calendarPanel, BorderLayout.CENTER);
setBorder(BorderFactory.createEmptyBorder());
@ -195,14 +223,14 @@ public class UIDatePicker extends UIComboBox implements Serializable {
@Override
public void hide() {
if (isWillHide) {
if (willHide) {
super.hide();
}
}
@Override
public void show() {
if (isWillHide || UIDatePicker.this.isEnabled() == false) {
if (willHide || UIDatePicker.this.isEnabled() == false) {
return;
}
if (calendarPanel != null) {
@ -241,6 +269,7 @@ public class UIDatePicker extends UIComboBox implements Serializable {
super.firePropertyChange(propertyName, oldValue, newValue);
}
@Override
public void stateChanged(ChangeEvent e) {
if (calendarPanel.getSelectedDate() != null && dateFormat != null) {
String strDate = dateFormat.format(calendarPanel.getSelectedDate());
@ -251,6 +280,10 @@ public class UIDatePicker extends UIComboBox implements Serializable {
}
comboBox.repaint();
setVisible(false);
//选择完日期,导出/上传按钮变可用
if (feedbackToolboxDialog != null) {
feedbackToolboxDialog.setSwitches(true);
}
}
}
@ -264,10 +297,10 @@ public class UIDatePicker extends UIComboBox implements Serializable {
@Override
public void mousePressed(MouseEvent e) {
if (UIDatePicker.this.isPopupVisible()) {
isWillHide = true;
willHide = true;
UIDatePicker.this.hidePopup();
} else {
isWillHide = false;
willHide = false;
UIDatePicker.this.showPopup();
}
}

11
designer-base/src/main/java/com/fr/design/utils/DesignerPort.java

@ -4,7 +4,6 @@ import com.fr.common.report.ReportState;
import com.fr.design.DesignerEnvManager;
import com.fr.design.RestartHelper;
import com.fr.design.dialog.TipDialog;
import com.fr.design.fun.DesignerPortProvider;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
@ -18,16 +17,20 @@ import com.fr.general.IOUtils;
import com.fr.process.engine.core.CarryMessageEvent;
import com.fr.process.engine.core.FineProcessContext;
import com.fr.stable.StringUtils;
import com.fr.stable.bridge.StableFactory;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLWriter;
import com.fr.stable.xml.XMLableReader;
import javax.swing.*;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

2
designer-base/src/main/java/com/fr/env/detect/ui/EnvDetectorAction.java vendored

@ -15,7 +15,7 @@ public class EnvDetectorAction extends UpdateAction {
public EnvDetectorAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Detect_Toolbar_Title"));
this.setName(Toolkit.i18nText("Fine-Design_Basic_Carton_Toolbox_Title"));
this.setSmallIcon("com/fr/env/detect/detect_normal.svg");
}

31
designer-base/src/main/java/com/fr/env/detect/ui/EnvDetectorDialog.java vendored

@ -6,12 +6,14 @@ import com.fr.design.components.notification.NotificationDialogProperties;
import com.fr.design.components.notification.NotificationModel;
import com.fr.design.components.table.TablePanel;
import com.fr.design.constants.DesignerColor;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UIButtonUI;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.ui.util.UIUtil;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.design.utils.gui.GUIPaintUtils;
@ -22,6 +24,9 @@ import com.fr.env.detect.bean.DetectorResult;
import com.fr.env.detect.bean.DetectorStatus;
import com.fr.env.detect.bean.DetectorType;
import com.fr.log.FineLoggerFactory;
import com.fr.design.carton.FeedbackToolboxDialog;
import com.fr.stable.ProductConstantsBase;
import com.fr.stable.StableUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
@ -37,8 +42,10 @@ import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Cursor;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.Map;
@ -118,12 +125,12 @@ public class EnvDetectorDialog extends JDialog {
add(body);
Dimension preferredSize = body.getPreferredSize();
setSize(preferredSize);
repaint();
pack();
GUICoreUtils.centerWindow(this);
}
@ -168,6 +175,26 @@ public class EnvDetectorDialog extends JDialog {
detectButton.setContentAreaFilled(false);
headerPanel.add(detectButton, BorderLayout.WEST);
UILabel openUtilBoxLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Carton_Feedback_ToolBox"));
openUtilBoxLabel.setForeground(UIConstants.FLESH_BLUE);
openUtilBoxLabel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
setVisible(false);
FeedbackToolboxDialog myDialog = new FeedbackToolboxDialog(DesignerContext.getDesignerFrame());
myDialog.setVisible(true);
dispose();
}
public void mouseEntered(MouseEvent evt) {
Object source = evt.getSource();
if (source instanceof UILabel) {
((UILabel) source).setCursor(new Cursor(Cursor.HAND_CURSOR));
}
}
});
headerPanel.add(openUtilBoxLabel, BorderLayout.EAST);
return headerPanel;
}
@ -183,7 +210,7 @@ public class EnvDetectorDialog extends JDialog {
detectWorker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
protected Void doInBackground() {
List<EnvDetectorItem> items = model.getItems();
// 执行刷新
for (int i = currentDetectIndex; i < items.size(); i++) {

2
designer-base/src/main/java/com/fr/start/common/DesignerOpenEmptyPanel.java

@ -1,6 +1,7 @@
package com.fr.start.common;
import com.fr.base.svg.IconUtils;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.file.MutilTempalteTabPane;
import com.fr.design.gui.ilable.UILabel;
@ -55,6 +56,7 @@ public class DesignerOpenEmptyPanel extends JPanel {
@Override
public void actionPerformed(ActionEvent e) {
DesignerFrame df = DesignerContext.getDesignerFrame();
HistoryTemplateListCache.getInstance().setCurrentEditingTemplate(null);
df.addAndActivateJTemplate();
// 如果没有模板,则需要确认一下
MutilTempalteTabPane.getInstance().setTemTemplate(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate());

7
designer-base/src/main/java/com/fr/start/common/DesignerStartupConfig.java

@ -20,7 +20,7 @@ public class DesignerStartupConfig implements XMLable {
/**
* 默认值是 false
*/
private boolean enabled = false;
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
@ -30,18 +30,17 @@ public class DesignerStartupConfig implements XMLable {
this.enabled = enabled;
}
@Override
public Object clone() throws CloneNotSupportedException {
DesignerStartupConfig config = new DesignerStartupConfig();
config.setEnabled(true);
config.setEnabled(enabled);
return config;
}
@Override
public void readXML(XMLableReader reader) {
if (reader.isAttr()) {
this.setEnabled(reader.getAttrAsBoolean("isEnabled", false));
this.setEnabled(reader.getAttrAsBoolean("isEnabled", true));
}
}

10
designer-base/src/main/java/com/fr/start/common/DesignerStartupContext.java

@ -4,6 +4,7 @@ import com.fr.design.DesignerEnvManager;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.env.DesignerWorkspaceType;
import com.fr.start.module.StartupArgs;
import com.fr.startup.metric.DesignerMetrics;
import com.fr.startup.ui.StartupPageModel;
import com.fr.third.guava.collect.Lists;
import com.fr.third.org.apache.commons.lang3.time.StopWatch;
@ -28,6 +29,11 @@ public class DesignerStartupContext {
*/
private StartupPageModel startupPageModel;
/**
* 设计器启动埋点
*/
private final DesignerMetrics designerMetrics = new DesignerMetrics();
/**
* 是否在起始页打开的等待过程中
*/
@ -75,6 +81,10 @@ public class DesignerStartupContext {
return STOP_WATCH;
}
public DesignerMetrics getDesignerMetrics() {
return designerMetrics;
}
/* 启动模式 */
/**

22
designer-base/src/main/java/com/fr/startup/metric/DesignerMetrics.java

@ -0,0 +1,22 @@
package com.fr.startup.metric;
/**
* created by Harrison on 2022/08/12
**/
public class DesignerMetrics {
private DesignerStartupModel model = new DesignerStartupModel();
private DesignerStartupPageStatistic statistic = new DesignerStartupPageStatistic();
public DesignerMetrics() {
}
public DesignerStartupModel getModel() {
return model;
}
public DesignerStartupPageStatistic getStatistic() {
return statistic;
}
}

193
designer-base/src/main/java/com/fr/startup/metric/DesignerStartupModel.java

@ -0,0 +1,193 @@
package com.fr.startup.metric;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.manage.PluginManager;
import com.fr.stable.os.AbstractOperatingSystem;
import com.fr.stable.os.OperatingSystem;
import com.fr.start.common.DesignerStartupConfig;
import com.fr.workspace.WorkContext;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.stream.Collectors;
/**
* 设计器启动数据
*
* created by Harrison on 2022/08/12
**/
public class DesignerStartupModel {
/**
* landingTime用户从双击图标/.bat启动等到出现起始页的时间
*/
private long landingTime;
/**
* startingTime用户从起始页进入设计器完全可用的时间
*/
private long startingTime;
/**
* info设计器环境的详细信息记录环境信息机器信息远程or本地插件信息
*/
private MachineInfo info;
/**
* mode模式0-有设计器起动页1-无设计器起始页
*/
private int mode;
public DesignerStartupModel() {
}
public DesignerStartupModel(long landingTime, long startingTime, MachineInfo info, int mode) {
this.landingTime = landingTime;
this.startingTime = startingTime;
this.info = info;
this.mode = mode;
}
public long getLandingTime() {
return landingTime;
}
public void setLandingTime(long landingTime) {
this.landingTime = landingTime;
}
public long getStartingTime() {
return startingTime;
}
public void setStartingTime(long startingTime) {
this.startingTime = startingTime;
}
public MachineInfo getInfo() {
return info;
}
public void setInfo(MachineInfo info) {
this.info = info;
}
public int getMode() {
return mode;
}
public void setMode(int mode) {
this.mode = mode;
}
private void fillInfo() {
MachineInfo info = new MachineInfo();
AbstractOperatingSystem operatingSystem = OperatingSystem.getOperatingSystem();
info.setSystem(operatingSystem.getDisplayString());
try {
final int byteToMb = 1024 * 1024;
com.sun.management.OperatingSystemMXBean operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
long free = operatingSystemMXBean.getFreePhysicalMemorySize() / byteToMb;
long total = operatingSystemMXBean.getTotalPhysicalMemorySize() / byteToMb;
long used = total - free;
JSONObject jo = new JSONObject();
jo.put("free", free);
jo.put("used", used);
jo.put("total", total);
info.setMachine(jo.toString());
} catch (Exception ignored) {
}
boolean local = WorkContext.getCurrent().isLocal();
info.setWork(local ? 1 : 0);
List<PluginContext> contexts = PluginManager.getContexts();
List<String> contextNames = contexts.stream()
.map(PluginContext::getName)
.collect(Collectors.toList());
JSONArray contextNameJa = new JSONArray(contextNames);
info.setPlugins(contextNameJa.toString());
this.setInfo(info);
}
private void fillMode() {
this.setMode(DesignerStartupConfig.getInstance().isEnabled() ? 0 : 1);
}
public void fill() {
fillInfo();
fillMode();
}
private static class MachineInfo {
/**
* 系统信息
*/
private String system;
/**
* 机器信息
*/
private String machine;
/**
* work0-远程1-本地
*/
private int work;
/**
* 插件列表
*/
private String plugins;
public MachineInfo() {
}
public MachineInfo(String system, String machine, int work, String plugins) {
this.system = system;
this.machine = machine;
this.work = work;
this.plugins = plugins;
}
public String getSystem() {
return system;
}
public void setSystem(String system) {
this.system = system;
}
public String getMachine() {
return machine;
}
public void setMachine(String machine) {
this.machine = machine;
}
public int getWork() {
return work;
}
public void setWork(int work) {
this.work = work;
}
public String getPlugins() {
return plugins;
}
public void setPlugins(String plugins) {
this.plugins = plugins;
}
}
}

71
designer-base/src/main/java/com/fr/startup/metric/DesignerStartupPageStatistic.java

@ -0,0 +1,71 @@
package com.fr.startup.metric;
/**
* 设计器启动页使用数据
*
* created by Harrison on 2022/08/12
**/
public class DesignerStartupPageStatistic {
/**
* operate0-双击工作目录进入 点击蓝色箭头进入1-切换其他工作目录2-点击展开全部3-点击工作目录中的模版直接打开 直接点击蓝色箭头进入
*/
private int operate;
/**
* workplace工作目录名称当operate为 0或1时记录
*/
private String workspace;
/**
* workplaceNumber工作目录的个数当operate为 0或1或2或3时记录
*/
private String workspaceNum;
/**
* template模板名称当operate为 3时记录
*/
private String template;
public DesignerStartupPageStatistic(int operate, String workspace, String workspaceNum, String template) {
this.operate = operate;
this.workspace = workspace;
this.workspaceNum = workspaceNum;
this.template = template;
}
public DesignerStartupPageStatistic() {
}
public int getOperate() {
return operate;
}
public void setOperate(int operate) {
this.operate = operate;
}
public String getWorkspace() {
return workspace;
}
public void setWorkspace(String workspace) {
this.workspace = workspace;
}
public String getWorkspaceNum() {
return workspaceNum;
}
public void setWorkspaceNum(String workspaceNum) {
this.workspaceNum = workspaceNum;
}
public String getTemplate() {
return template;
}
public void setTemplate(String template) {
this.template = template;
}
}

2
designer-realize/src/main/java/com/fr/design/sort/header/HeaderAreaPane.java

@ -168,7 +168,9 @@ public class HeaderAreaPane extends JPanel {
public void populateBean(ColumnRow columnRow, boolean showHeaderArea, boolean enabled) {
cellSelectionManager.build(cellElement, columnRow);
if(showHeaderArea){
columnRow = cellSelectionManager.buildCurrentCell(cellElement, columnRow);
}
columnRowPane.populateBean(columnRow, enabled, cellSelectionManager);
setSortColumnRowPaneShow(showHeaderArea);
uiComboBox.setSelectedIndex(showHeaderArea ? 1 : 0);

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

@ -11,6 +11,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.SwitchForSwingChecker;
import com.fr.design.constants.UIConstants;
import com.fr.design.deeplink.DeepLinkManager;
import com.fr.design.file.HistoryTemplateListCache;
@ -74,9 +75,8 @@ import com.fr.start.server.ServerTray;
import com.fr.third.org.apache.commons.lang3.time.StopWatch;
import com.fr.van.chart.map.server.ChartMapEditorAction;
import com.fr.workspace.WorkContext;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JComponent;
import javax.swing.border.MatteBorder;
import java.awt.Component;
import java.awt.Dimension;
@ -156,6 +156,8 @@ public class MainDesigner extends BaseDesigner {
}
FineLoggerFactory.getLogger().info("Designer started.Time used {} ms", watch.getTime());
watch.stop();
SwitchForSwingChecker.initThreadMonitoring();
}
/**

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

@ -9,6 +9,8 @@ import com.fr.start.common.DesignerStartupContext;
import com.fr.start.module.StartupArgs;
import com.fr.start.util.DesignerStartupPageUtil;
import com.fr.start.warmup.DesignerPreWarmTask;
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;
@ -58,7 +60,7 @@ public class DesignerStartupPageActivator extends Activator {
warmTask.start();
// 即时暂停
DesignerStartupContext.getRecorder().suspend();
suspendRecorder(context);
UIUtil.invokeLaterIfNeeded(() -> {
@ -89,9 +91,20 @@ public class DesignerStartupPageActivator extends Activator {
StartupPageWindow window = new StartupPageWindow(model);
window.setVisible(true);
context.setOnWaiting(true);
});
}
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) {
// 将选中的环境设置为当前环境
@ -118,12 +131,21 @@ public class DesignerStartupPageActivator extends Activator {
UIUtil.invokeLaterIfNeeded(() -> {
// 换到 awt 线程中关闭,不然异步会出现问题。
DesignerStartupContext.getInstance().setOnStartup(false);
recordStartupEnd(stopWatch);
});
}
FineLoggerFactory.getLogger().debug("designer-startup-page started cost {} ms", DesignerStartupContext.getRecorder().getTime(TimeUnit.MILLISECONDS));
}
private void recordStartupEnd(StopWatch stopWatch) {
DesignerMetrics designerMetrics = DesignerStartupContext.getInstance().getDesignerMetrics();
DesignerStartupModel model = designerMetrics.getModel();
model.setStartingTime(stopWatch.getTime(TimeUnit.MILLISECONDS));
model.fill();
}
@Override
public void stop() {

Loading…
Cancel
Save