Browse Source

Pull request #11745: REPORT-91503 保存模板频繁报错锁定信息不一致,在这个弹窗另存为一定会失败。

Merge in DESIGN/design from ~YVAN/design:release/11.0 to release/11.0

* commit 'fe85bf97116dc844a808cbfcb1f439222f56131d':
  REPORT-91503 保存模板频繁报错锁定信息不一致,在这个弹窗另存为一定会失败。 处理创建模板备份文件时的锁定问题,以及锁定可能失败的问题
  REPORT-91503 保存模板频繁报错锁定信息不一致,在这个弹窗另存为一定会失败。 代码格式化、注释等
  REPORT-91503 保存模板频繁报错锁定信息不一致,在这个弹窗另存为一定会失败。 【问题原因】REPORT-70481迭代引起,原因是在模板锁定信息不一致的时候,原本的逻辑是将当前模板保存为备份文件 + 关闭当前模板,但是保存的动作是通过SwingWorker做的,关闭当前模板的动作未被包含在SwingWorker中,因此会导致先关闭当前模板释放资源,再读取当前模板写入新文件(此时有资源已被释放,会在写入时引起NPE) 【改动思路】将关闭当前模板的动作放到保存的SwingWorker的done方法中,即先保存成功,再关闭模板;另外优化了一下保存的代码,使其更符合开发规范 【review建议】
newui
Yvan-欧阳帆 2 years ago
parent
commit
01cb38d597
  1. 85
      designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java
  2. 8
      designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java

85
designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java

@ -16,6 +16,7 @@ import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils; import com.fr.stable.ArrayUtils;
import com.fr.stable.CoreConstants; import com.fr.stable.CoreConstants;
import com.fr.stable.ProductConstants; import com.fr.stable.ProductConstants;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContext;
import com.fr.workspace.server.lock.TplOperator; import com.fr.workspace.server.lock.TplOperator;
@ -33,14 +34,30 @@ public class TemplateUtils {
/** /**
* 创建新的模板文件并打开模板 * 创建新的模板文件并打开模板
* @param prefix 模板文件名称前缀 *
* @param file 模板文件 * @param prefix 模板文件名称前缀
* @param file 模板文件
* @param createByEditingTemplate 是否根据 当前编辑模板 来创建新模板 * @param createByEditingTemplate 是否根据 当前编辑模板 来创建新模板
* 为true时以CurrentEditingTemplate为准创建新模板 * 为true时以CurrentEditingTemplate为准创建新模板
* 为false时以传入的File文件为准创建新模板此文件可以不是编辑状态 * 为false时以传入的File文件为准创建新模板此文件可以不是编辑状态
* @param openNewTemplate 是否需要在创建后打开模板 * @param openNewTemplate 是否需要在创建后打开模板
*/ */
public static void createAndOpenTemplate(String prefix, FILE file, boolean createByEditingTemplate, boolean openNewTemplate) { public static void createAndOpenTemplate(String prefix, FILE file, boolean createByEditingTemplate, boolean openNewTemplate) {
createAndOpenTemplate(prefix, file, createByEditingTemplate, openNewTemplate, () -> {});
}
/**
* 创建新的模板文件并打开模板并在创建备份模板成功后执行doAfterCreate
*
* @param prefix 模板文件名称前缀
* @param file 模板文件
* @param createByEditingTemplate 是否根据 当前编辑模板 来创建新模板
* 为true时以CurrentEditingTemplate为准创建新模板
* 为false时以传入的File文件为准创建新模板此文件可以不是编辑状态
* @param openNewTemplate 是否需要在创建后打开模板
* @param doAfterCreateTemplate 创建备份模板成功后调用
*/
public static void createAndOpenTemplate(String prefix, FILE file, boolean createByEditingTemplate, boolean openNewTemplate, Runnable doAfterCreateTemplate) {
String fileName = file.getName(); String fileName = file.getName();
String oldPath = file.getPath(); String oldPath = file.getPath();
int indexOfLastDot = fileName.lastIndexOf(CoreConstants.DOT); int indexOfLastDot = fileName.lastIndexOf(CoreConstants.DOT);
@ -48,7 +65,7 @@ public class TemplateUtils {
return; return;
} }
String suffix = fileName.substring(indexOfLastDot + 1); String suffix = fileName.substring(indexOfLastDot + 1);
FILEChooserPane fileChooserPane = FILEChooserPane.getInstance(true, true); FILEChooserPane fileChooserPane = FILEChooserPane.getInstance(true, true);
fileChooserPane.setFileNameTextField(prefix + fileName, suffix); fileChooserPane.setFileNameTextField(prefix + fileName, suffix);
FileExtension fileExtension = FileExtension.parse(suffix); FileExtension fileExtension = FileExtension.parse(suffix);
fileChooserPane.addChooseFILEFilter(new ChooseFileFilter(fileExtension, ProductConstants.APP_NAME + Toolkit.i18nText("Fine-Design_Report_Template_File"))); fileChooserPane.addChooseFILEFilter(new ChooseFileFilter(fileExtension, ProductConstants.APP_NAME + Toolkit.i18nText("Fine-Design_Report_Template_File")));
@ -62,31 +79,26 @@ public class TemplateUtils {
if (isOk(result)) { if (isOk(result)) {
file = fileChooserPane.getSelectedFILE(); file = fileChooserPane.getSelectedFILE();
_createAndOpenTemplate(file, oldPath, createByEditingTemplate, openNewTemplate); createAndOpenTemplate0(file, oldPath, createByEditingTemplate, openNewTemplate, doAfterCreateTemplate);
} }
} }
private static void _createAndOpenTemplate(FILE file, String oldPath, boolean createByEditingTemplate, boolean openNewTemplate){ private static void createAndOpenTemplate0(FILE file, String oldPath, boolean createByEditingTemplate, boolean openNewTemplate, Runnable doAfterCreateTemplate) {
new SwingWorker<Void, Void>() { new SwingWorker<Boolean, Void>() {
@Override @Override
protected Void doInBackground() throws Exception { protected Boolean doInBackground() throws Exception {
byte[] content = new byte[0]; // 读取模板数据
if (createByEditingTemplate) { byte[] content = getTemplateData(createByEditingTemplate, oldPath);
// 从当前编辑模板中生成备份文件
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
content = template.exportData();
} else {
content = WorkContext.getWorkResource().readFully(oldPath);
}
if (ArrayUtils.isEmpty(content)) {
throw new Exception(oldPath + " content is empty" );
}
OutputStream out = null; OutputStream out = null;
try { try {
// 加锁 // 加锁
WorkContext.getCurrent().get(TplOperator.class).saveAs(file.getPath()); boolean saveAsLock = WorkContext.getCurrent().get(TplOperator.class).saveAs(file.getPath());
if (!saveAsLock) {
// 加锁失败时,直接返回
return false;
}
out = file.asOutputStream(); out = file.asOutputStream();
out.write(content); out.write(content);
} finally { } finally {
@ -98,15 +110,18 @@ public class TemplateUtils {
// 解锁 // 解锁
WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(file.getPath()); WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(file.getPath());
} }
} }
return null; return true;
} }
@Override @Override
protected void done() { protected void done() {
try { try {
get(); if (!get()) {
throw new Exception("[RemoteDesign] back up template file failed");
}
// 创建备份成功后,关闭原模板
doAfterCreateTemplate.run();
if (openNewTemplate) { if (openNewTemplate) {
DesignerContext.getDesignerFrame().openTemplate(file); DesignerContext.getDesignerFrame().openTemplate(file);
} }
@ -118,7 +133,31 @@ public class TemplateUtils {
} }
} }
}.execute(); }.execute();
}
/**
* 读取模板文件数据
*
* @param readCurrentEditingTemplate 是否读取当前编辑模板
* @param path 模板路径
* @return 模板文件数据
*/
private static byte[] getTemplateData(boolean readCurrentEditingTemplate, String path) throws Exception {
byte[] content = new byte[0];
if (readCurrentEditingTemplate) {
// 从当前编辑模板中读取模板文件数据
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (JTemplate.isValid(template)) {
content = template.exportData();
}
} else {
// 从给定的模板路径中读取模板文件数据
content = WorkContext.getWorkResource().readFully(path);
}
if (ArrayUtils.isEmpty(content)) {
throw new Exception(StringUtils.messageFormat("{} content is empty", path));
}
return content;
} }
private static boolean isCancel(int result) { private static boolean isCancel(int result) {

8
designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java

@ -133,14 +133,14 @@ public class SaveFailureHandler implements ThrowableHandler {
new Object[] {Toolkit.i18nText("Fine_Design_Template_SaveAs_Backup"), Toolkit.i18nText("Fine-Design_Basic_Button_Cancel")}, null); new Object[] {Toolkit.i18nText("Fine_Design_Template_SaveAs_Backup"), Toolkit.i18nText("Fine-Design_Basic_Button_Cancel")}, null);
if (option == JOptionPane.YES_OPTION) { if (option == JOptionPane.YES_OPTION) {
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (template != null) { if (JTemplate.isValid(template)) {
TemplateUtils.createAndOpenTemplate( TemplateUtils.createAndOpenTemplate(
Toolkit.i18nText("Fine_Design_Template_Backup"), Toolkit.i18nText("Fine_Design_Template_Backup"),
new FileNodeFILE(new FileNode(template.getPath(), false)), new FileNodeFILE(new FileNode(template.getPath(), false)),
true, true,
true); true,
// 创建并打开备份模板后,关闭原模板 // 创建并打开备份模板后,关闭原模板,无需释放原模板锁(锁定信息不一致 = 此用户模板锁信息已被清除)
HistoryTemplateListCache.getInstance().closeSelectedReport(template); () -> HistoryTemplateListCache.getInstance().closeSelectedReport(template));
} }
} }
} }

Loading…
Cancel
Save