Browse Source

REPORT-114391 【微服务适配】远程&本地设计器能够正常启动 设计器启动适配fbp1.0分支与设计器基础远程设计框架适配

mss/2.0
Destiny.Lin 6 months ago
parent
commit
62d9909ce6
  1. 27
      designer-base/src/main/java/com/fr/design/DesignModelAdapter.java
  2. 3
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java
  3. 3
      designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java
  4. 10
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/TableDataPreviewDesensitizeManager.java
  5. 14
      designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java
  6. 9
      designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/TableDataFactory.java
  7. 10
      designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java
  8. 22
      designer-base/src/main/java/com/fr/design/editlock/EditLockUtils.java
  9. 2
      designer-base/src/main/java/com/fr/design/env/DesignerWorkspaceGenerator.java
  10. 59
      designer-base/src/main/java/com/fr/design/env/HttpWorkspaceConnector.java
  11. 14
      designer-base/src/main/java/com/fr/design/env/RemoteWorkspace.java
  12. 9
      designer-base/src/main/java/com/fr/design/file/NodeAuthProcessor.java
  13. 3
      designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java
  14. 6
      designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateDirTree.java
  15. 13
      designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java
  16. 22
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  17. 33
      designer-base/src/main/java/com/fr/design/versioncheck/VersionCheckUtils.java
  18. 3
      designer-base/src/main/java/com/fr/file/FILEChooserPane.java
  19. 25
      designer-base/src/main/java/com/fr/file/FileNodeFILE.java
  20. 5
      designer-chart/src/main/java/com/fr/van/chart/map/designer/type/WMSLayerPane.java
  21. 29
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoPane.java
  22. 2
      designer-realize/src/main/java/com/fanruan/boot/init/DesignSerializationComponent.java
  23. 35
      designer-realize/src/main/java/com/fanruan/boot/init/DesignWorkContextComponent.java
  24. 6
      designer-realize/src/main/java/com/fanruan/boot/init/DesignerInitComponent.java
  25. 2
      designer-realize/src/main/java/com/fanruan/boot/init/DesignerStartupComponent.java
  26. 2
      designer-realize/src/main/java/com/fanruan/boot/init/PreLoadComponent.java
  27. 2
      designer-realize/src/main/java/com/fanruan/boot/init/XMLableComponent.java
  28. 28
      designer-realize/src/main/java/com/fanruan/boot/pre/DesignConfigComponent.java
  29. 24
      designer-realize/src/main/java/com/fanruan/boot/pre/DesignPluginSupplementComponent.java
  30. 151
      designer-realize/src/main/java/com/fanruan/boot/pre/DesignPreStartComponent.java
  31. 14
      designer-realize/src/main/java/com/fanruan/boot/pre/DesignTenantComponent.java
  32. 5
      designer-realize/src/main/java/com/fanruan/boot/show/DesignConfConfigComponent.java
  33. 5
      designer-realize/src/main/java/com/fanruan/boot/show/DesignCoreSupplementalComponent.java
  34. 2
      designer-realize/src/main/java/com/fanruan/boot/show/DesignEnvComponent.java
  35. 5
      designer-realize/src/main/java/com/fanruan/boot/show/DesignFunctionComponent.java
  36. 5
      designer-realize/src/main/java/com/fanruan/boot/show/DesignLoggerComponent.java
  37. 5
      designer-realize/src/main/java/com/fanruan/boot/show/DesignPluginComponent.java
  38. 2
      designer-realize/src/main/java/com/fanruan/boot/show/DesignUpdateComponent.java
  39. 2
      designer-realize/src/main/java/com/fanruan/boot/show/DesignWorkspaceComponent.java
  40. 2
      designer-realize/src/main/java/com/fanruan/boot/show/DesignWorkspaceRegisterComponent.java
  41. 2
      designer-realize/src/main/java/com/fanruan/boot/show/DesignerComponent.java
  42. 5
      designer-realize/src/main/java/com/fanruan/boot/show/DesignerDaoComponent.java
  43. 2
      designer-realize/src/main/java/com/fanruan/boot/show/DesignerShowComponent.java
  44. 3
      designer-realize/src/main/java/com/fr/design/mainframe/InformationCollector.java
  45. 4
      designer-realize/src/main/java/com/fr/design/report/ReportEnginePane.java
  46. 37
      designer-realize/src/main/java/com/fr/start/CarinaDesigner.java
  47. 2
      designer-realize/src/main/java/com/fr/start/DesignLauncher.java
  48. 3
      designer-realize/src/main/java/com/fr/start/SplashContext.java
  49. 4
      designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.java
  50. 116
      designer-realize/src/main/java/com/fr/start/module/optimized/TenantDBAdapter4Designer.java

27
designer-base/src/main/java/com/fr/design/DesignModelAdapter.java

@ -16,9 +16,11 @@ import com.fr.form.ui.MultiFileEditor;
import com.fr.form.ui.Widget;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.script.Calculator;
import com.fr.stable.Filter;
import com.fr.stable.ParameterProvider;
import com.fr.stable.StringUtils;
import com.fr.stable.collections.CollectionUtils;
import com.fr.stable.js.WidgetName;
import com.fr.util.ParameterApplyHelper;
@ -285,7 +287,7 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
tableDatas.add(tableData);
names.add(name);
}
ParameterProvider[][] totalParameterProviders = DataOperator.getInstance().getTotalTableDataParameters(tableDatas);
ParameterProvider[][] totalParameterProviders = getTotalTableDataParameters(tableDatas);
tableDataParametersMap.clear();
for (int i = 0; i < totalParameterProviders.length; i++) {
ParameterProvider[] parameterProviders = totalParameterProviders[i];
@ -301,6 +303,29 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
}
}
private ParameterProvider[][] getTotalTableDataParameters(List<TableData> tableDatas) {
if (CollectionUtils.isEmpty(tableDatas)) {
return new ParameterProvider[0][];
}
List<ParameterProvider[]> parameterProviders = new ArrayList<>();
for (TableData tableData : tableDatas) {
ParameterProvider[] tableDataParameters = this.getTableDataParameters(tableData);
parameterProviders.add(tableDataParameters);
}
return parameterProviders.toArray(new ParameterProvider[parameterProviders.size()][]);
}
private ParameterProvider[] getTableDataParameters(TableData tableData) {
ParameterProvider[] res = null;
if (tableData != null) {
res = tableData.getParameters(Calculator.createCalculator());
}
return res == null ? new ParameterProvider[0] : res;
}
protected void updateTableDataParameters(String oldName,
String tdName,
TableData tableData,

3
designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java

@ -136,7 +136,8 @@ public class AlphaFineConfigManager implements XMLable {
public static boolean isALPHALicAvailable() {
return VT4FR.AlphaFine.isSupport();
// todo lic相关的被拆分了,需要再适配一下lic的api
return true;
}
@Override

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

@ -336,7 +336,8 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
private List<String> getHasAuthConnections() {
List<String> authConnections = new ArrayList<>();
Set<String> allConnections = ConnectionConfigProviderFactory.getConfigProvider().getConnections().keySet();
Collection<String> noAuthConnections = WorkContext.getCurrent().get(DBConnectAuth.class).getNoAuthConnections();
// todo 待实现
Collection<String> noAuthConnections = new ArrayList<>();
if (noAuthConnections == null) {
return authConnections;
}

10
designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/TableDataPreviewDesensitizeManager.java

@ -8,18 +8,12 @@ import com.fr.data.desensitize.base.DesensitizationTableData;
import com.fr.data.desensitize.base.TableDataDesensitizationItem;
import com.fr.data.desensitize.manage.DesensitizationManager;
import com.fr.data.desensitize.util.DesentizationUtils;
import com.fr.decision.webservice.bean.user.DepartmentPostBean;
import com.fr.decision.webservice.bean.user.RoleBean;
import com.fr.decision.webservice.utils.DecisionServiceConstants;
import com.fr.decision.webservice.v10.user.CustomRoleService;
import com.fr.decision.webservice.v10.user.PositionService;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.preview.PreviewTableModel;
import com.fr.design.data.datapane.preview.desensitization.model.DesensitizedPreviewTableModel;
import com.fr.esd.query.StrategicTableData;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import java.util.Arrays;
import java.util.Collection;

14
designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java

@ -1,5 +1,6 @@
package com.fr.design.data.datapane.preview.sql;
import com.fanruan.carina.Carina;
import com.fr.base.Parameter;
import com.fr.base.ParameterHelper;
import com.fr.base.ParameterMapNameSpace;
@ -19,6 +20,7 @@ import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.CloudCenter;
import com.fr.general.GeneralContext;
import com.fr.log.FineLoggerFactory;
import com.fr.platform.scaffold.provider.config.PreventSqlInjConfigProvider;
import com.fr.plugin.injectable.PluginModule;
import com.fr.script.Calculator;
import com.fr.stable.ArrayUtils;
@ -189,7 +191,9 @@ public class PreviewPerformedSqlPane extends JDialog implements ActionListener {
Parameter[] paras = processParameters(tableData, calculator);
// 所有被转义参数的集合
refreshEscapeSqlHelper();
Set<String> specialCharParam = EscapeSqlHelper.getInstance().getSpecialCharParam(paras);
// todo 待实现[check]EscapeSqlHelper.getInstance().getSpecialCharParam(paras);
Set<String> specialCharParam = new HashSet<>();
// 将参数转义等
Set<TableDataProvider> tableDataProviders = getTableDataProviders();
for (TableDataProvider provider : tableDataProviders) {
@ -223,15 +227,13 @@ public class PreviewPerformedSqlPane extends JDialog implements ActionListener {
// 埋点方法
private static void showSpecialCharSqlPane(String sql, List<int[]> specialCharParamIndex, boolean highlight) {
PreviewPerformedSqlPane pane = new PreviewPerformedSqlPane(DesignerContext.getDesignerFrame(), sql, specialCharParamIndex, ConfigService.getInstance().getPSIConfig().getSelectedSpecialChar(), highlight);
PreviewPerformedSqlPane pane = new PreviewPerformedSqlPane(DesignerContext.getDesignerFrame(), sql, specialCharParamIndex, Carina.config(PreventSqlInjConfigProvider.class).getSpecialChars(), highlight);
pane.setVisible(true);
}
private static void refreshEscapeSqlHelper() {
EscapeSqlHelper.getInstance().setUseForbidWord(ConfigService.getInstance().getPSIConfig().isUseForbidWord());
EscapeSqlHelper.getInstance().setSelectedForbidWord(ConfigService.getInstance().getPSIConfig().getSelectedForbidWord());
EscapeSqlHelper.getInstance().setUseEscapeSpecialChar(ConfigService.getInstance().getPSIConfig().isUseEscapeSpecialChar());
EscapeSqlHelper.getInstance().setSelectedSpecialChar(ConfigService.getInstance().getPSIConfig().getSelectedSpecialChar());
EscapeSqlHelper.getInstance().setUseForbidWord(Carina.config(PreventSqlInjConfigProvider.class).isUseForbidWord());
EscapeSqlHelper.getInstance().setUseEscapeSpecialChar(Carina.config(PreventSqlInjConfigProvider.class).isUseEscapeSpecialChar());
}
private static boolean isShowSpecialCharSqlPane(List<int[]> specialCharParamIndex) {

9
designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/TableDataFactory.java

@ -8,7 +8,7 @@ import com.fr.data.impl.DBTableData;
import com.fr.data.impl.DecoratedTableData;
import com.fr.data.impl.EmbeddedTableData;
import com.fr.data.impl.FileTableData;
import com.fr.data.impl.MultiFieldTableData;
//import com.fr.data.impl.MultiFieldTableData;
import com.fr.data.impl.MultiTDTableData;
import com.fr.data.impl.RecursionTableData;
import com.fr.data.impl.storeproc.StoreProcedure;
@ -28,6 +28,7 @@ import com.fr.stable.ArrayUtils;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.authority.user.UserAuthority;
import com.fr.workspace.server.repository.tabledata.TableDataRepository;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
@ -63,7 +64,8 @@ public abstract class TableDataFactory {
defaultMap.put(MultiTDTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/standard/multi_normal.svg", MultiTDTableData.class, MultiTDTableDataPane.class));
defaultMap.put(FileTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/standard/file_normal.svg", FileTableData.class, FileTableDataPane.class));
defaultMap.put(RecursionTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/standard/tree_normal.svg", RecursionTableData.class, TreeTableDataPane.class));
defaultMap.put(MultiFieldTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/standard/database_normal.svg", MultiFieldTableData.class, null));
// todo 待实现
//defaultMap.put(MultiFieldTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/standard/database_normal.svg", MultiFieldTableData.class, null));
map.putAll(defaultMap);
}
@ -177,8 +179,7 @@ public abstract class TableDataFactory {
public static String[] getSortOfChineseNameOfServerData() {
clearAll();
try {
UserAuthority userAuthority = WorkContext.getCurrent().get(UserAuthority.class);
Iterator<String> nameIt = userAuthority.getAuthServerDataSetNames().iterator();
Iterator<String> nameIt = TableDataRepository.getInstance().getAllNames(StringUtils.EMPTY).iterator();
while (nameIt.hasNext()) {
String name = nameIt.next();
addName(name, TableDataConfigProviderFactory.getInstance().getTableData(name));

10
designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java

@ -6,6 +6,8 @@ import com.fr.log.FineLoggerFactory;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.lock.editlock.EditLockOperator;
import com.fr.report.LockItem;
import com.fr.workspace.server.repository.connection.ConnectionRepository;
import com.fr.workspace.server.repository.tabledata.TableDataRepository;
import java.util.ArrayList;
import java.util.List;
@ -38,8 +40,12 @@ public abstract class EditLockChangeChecker {
// 判断是否为远程设计环境
if (!WorkContext.getCurrent().isLocal()) {
try {
EditLockOperator operator = WorkContext.getCurrent().get(EditLockOperator.class);
boolean locked = operator.isLocked(lockItem);
boolean locked = false;
if (lockItem == LockItem.CONNECTION) {
locked = ConnectionRepository.getInstance().isLock(lockItem.getDescription());
} else {
locked = TableDataRepository.getInstance().isLock(lockItem.getDescription());
}
if (isLocked() != locked) {
setLocked(locked);
fireChange();

22
designer-base/src/main/java/com/fr/design/editlock/EditLockUtils.java

@ -9,6 +9,8 @@ import com.fr.general.IOUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.lock.editlock.EditLockOperator;
import com.fr.report.LockItem;
import com.fr.workspace.server.repository.connection.ConnectionRepository;
import com.fr.workspace.server.repository.tabledata.TableDataRepository;
import org.jetbrains.annotations.Nullable;
import javax.swing.Icon;
@ -72,16 +74,26 @@ public class EditLockUtils {
}
public static boolean lock(LockItem lockItem) {
return WorkContext.getCurrent().get(EditLockOperator.class).lock(lockItem);
if (lockItem == LockItem.CONNECTION) {
return ConnectionRepository.getInstance().lock(lockItem.getDescription());
} else {
return TableDataRepository.getInstance().lock(lockItem.getDescription());
}
}
public static boolean unlock(LockItem lockItem) {
return WorkContext.getCurrent().get(EditLockOperator.class).unlock(lockItem);
if (lockItem == LockItem.CONNECTION) {
return ConnectionRepository.getInstance().unlock(lockItem.getDescription());
} else {
return TableDataRepository.getInstance().unlock(lockItem.getDescription());
}
}
public static boolean isLocked(LockItem lockItem) {
EditLockOperator operator = WorkContext.getCurrent().get(EditLockOperator.class);
// 启动过程中UILockButton初始化的时候会调用这个方法,但是此时workObjectPool中还没有对象,会报npe
return operator != null && operator.isLocked(lockItem);
if (lockItem == LockItem.CONNECTION) {
return ConnectionRepository.getInstance().isLock(lockItem.getDescription());
} else {
return TableDataRepository.getInstance().isLock(lockItem.getDescription());
}
}
}

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

@ -2,14 +2,12 @@ package com.fr.design.env;
import com.fr.common.report.ReportState;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.EnvChangeEntrance;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.messagecollect.StartErrorMessageCollector;
import com.fr.design.mainframe.messagecollect.entity.DesignerErrorMessage;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.process.ProcessEventPipe;
import com.fr.process.engine.core.CarryMessageEvent;
import com.fr.process.engine.core.FineProcessContext;
import com.fr.stable.StringUtils;

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

@ -0,0 +1,59 @@
package com.fr.design.env;
import com.fanruan.workplace.http.HttpConstants;
import com.fr.stable.StringUtils;
import com.fr.workspace.server.repository.connect.FineWorkspaceHttpClient;
import com.fr.decision.webservice.bean.authentication.LoginRequestInfoBean;
import com.fr.decision.webservice.bean.authentication.LoginResponseInfoBean;
import com.fr.workspace.connect.WorkspaceClient;
import com.fr.workspace.connect.WorkspaceConnection;
import com.fr.workspace.connect.WorkspaceConnectionInfo;
import com.fr.workspace.connect.WorkspaceConnector;
import com.fr.workspace.server.repository.connect.RemoteNetworkRepository;
import java.net.InetAddress;
import java.util.UUID;
/**
* 远程环境连接器
*
* @author Destiny.Lin
* @since 11.0
* Created on 2024/5/24
*/
public class HttpWorkspaceConnector implements WorkspaceConnector {
private static final HttpWorkspaceConnector INSTANCE = new HttpWorkspaceConnector();
public static HttpWorkspaceConnector getInstance() {
return INSTANCE;
}
@Override
public boolean testConnection(WorkspaceConnectionInfo connectionInfo) throws Exception {
LoginResponseInfoBean bean = RemoteNetworkRepository.getInstance().login(createLoginBean(connectionInfo));
return StringUtils.isNotEmpty(bean.getAccessToken());
}
@Override
public WorkspaceClient connect(WorkspaceConnectionInfo connectionInfo) throws Exception {
FineWorkspaceHttpClient client = FineWorkspaceHttpClient.create("Http-Client", connectionInfo);
LoginResponseInfoBean bean = RemoteNetworkRepository.getInstance().login(createLoginBean(connectionInfo));
WorkspaceConnection connection = new WorkspaceConnection(
UUID.randomUUID().toString(),
connectionInfo.getUserName(),
HttpConstants.AUTHORIZATION_PREFIX + bean.getAccessToken(),
InetAddress.getLocalHost().getHostAddress());
client.updateConnection(connection);
client.startHeartBeat();
return client;
}
private LoginRequestInfoBean createLoginBean(WorkspaceConnectionInfo connectionInfo) {
LoginRequestInfoBean bean = new LoginRequestInfoBean();
bean.setUsername(connectionInfo.getUserName());
bean.setPassword(connectionInfo.getPassword());
bean.setEncrypted(false);
return bean;
}
}

14
designer-base/src/main/java/com/fr/design/env/RemoteWorkspace.java vendored

@ -13,6 +13,8 @@ import com.fr.workspace.connect.WorkspaceConnection;
import com.fr.workspace.connect.WorkspaceConnectionInfo;
import com.fr.workspace.server.authority.decision.DecisionOperator;
import com.fr.workspace.pool.WorkObjectPool;
import com.fr.workspace.server.repository.authority.RemoteAuthorityRepository;
import javax.swing.SwingWorker;
/**
@ -63,15 +65,7 @@ public class RemoteWorkspace implements Workspace {
@Override
public boolean isWarDeploy() {
if (warDeploy == null) {
warDeploy = WorkContext.getCurrent().get(CommonOperator.class, new ExceptionHandler<Boolean>() {
@Override
public Boolean callHandler(RPCInvokerExceptionInfo rpcInvokerExceptionInfo) {
return false;
}
}).isWarDeploy();
}
return warDeploy;
return false;
}
@Override
@ -86,7 +80,7 @@ public class RemoteWorkspace implements Workspace {
if (isRoot == null) {
synchronized (this) {
if (isRoot == null) {
isRoot = WorkContext.getCurrent().get(DecisionOperator.class).isRoot(getConnection().getUserName());
isRoot = RemoteAuthorityRepository.getInstance().isRoot(getConnection().getUserName());
}
}
}

9
designer-base/src/main/java/com/fr/design/file/NodeAuthProcessor.java

@ -12,6 +12,7 @@ import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.authority.AuthorityOperator;
import com.fr.workspace.server.authority.decision.DecisionOperator;
import com.fr.workspace.server.repository.authority.RemoteAuthorityRepository;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
@ -43,13 +44,7 @@ public class NodeAuthProcessor {
try {
String userName = WorkContext.getCurrent().getConnection().getUserName();
DesignAuthority[] authorities = null;
try {
String userId = WorkContext.getCurrent().get(DecisionOperator.class).getUserIdByName(userName);
authorities = WorkContext.getCurrent().get(AuthorityOperator.class).getAuthorities(userId);
} catch(UndeclaredThrowableException e) {
// 兼容旧版本的服务器
authorities = WorkContext.getCurrent().get(AuthorityOperator.class).getAuthorities();
}
authorities = RemoteAuthorityRepository.getInstance().getAuthorities(WorkContext.getCurrent().getConnection().getUserName());
// 远程设计获取设计成员的权限列表
DesignAuthority authority = null;

3
designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java

@ -61,6 +61,7 @@ import java.util.Observer;
import java.util.Set;
import java.util.stream.Collectors;
import com.fr.workspace.server.repository.template.TemplateRepository;
import org.jetbrains.annotations.Nullable;
@ -212,7 +213,7 @@ public class TemplateTreePane extends JPanel implements FileOperations {
* 刷新
*/
public void refreshDockingView() {
reportletsTree.setFileNodeFilter(new IOFileNodeFilter(FRContext.getFileNodes().getSupportedTypes()));
reportletsTree.setFileNodeFilter(new IOFileNodeFilter(TemplateRepository.getInstance().getSupportedTypes()));
reportletsTree.refreshEnv();
}

6
designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateDirTree.java

@ -4,6 +4,8 @@ import com.fr.base.FRContext;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.mainframe.manager.search.TemplateDirTreeSearchManager;
import com.fr.file.filetree.FileNode;
import com.fr.workspace.server.entity.template.TemplateListBean;
import com.fr.workspace.server.repository.template.TemplateRepository;
import java.util.Arrays;
import java.util.Map;
@ -26,7 +28,9 @@ public class TemplateDirTree extends TemplateFileTree {
* @return
*/
public FileNode[] listFile(String path) {
return Arrays.stream(FRContext.getFileNodes().list(path)).filter(FileNode::isDirectory).toArray(FileNode[]::new);
TemplateListBean bean = new TemplateListBean();
bean.setTargetPath(path);
return Arrays.stream(TemplateRepository.getInstance().list(bean)).filter(FileNode::isDirectory).toArray(FileNode[]::new);
}

13
designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java

@ -13,6 +13,8 @@ import com.fr.stable.ArrayUtils;
import com.fr.stable.StableUtils;
import com.fr.stable.collections.CollectionUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.server.entity.template.TemplateListBean;
import com.fr.workspace.server.repository.template.TemplateRepository;
import javax.swing.text.Position;
import javax.swing.tree.DefaultTreeModel;
@ -142,10 +144,13 @@ public class TemplateFileTree extends EnvFileTree {
public FileNode[] listFile(String path) {
// 支持插件扩展, 先从env的filter拿, 再从插件拿
Set<FileExtension> supportTypes = createFileExtensionFilter();
return FRContext.getFileNodes().list(
path,
supportTypes.toArray(new FileExtension[supportTypes.size()]), false, true
);
TemplateListBean bean = new TemplateListBean();
bean.setFilter( supportTypes.toArray(new FileExtension[supportTypes.size()]));
bean.setCheckLock(true);
bean.setRecurse(false);
bean.setTargetPath(path);
return TemplateRepository.getInstance().list(bean);
}
private Set<FileExtension> createFileExtensionFilter() {

22
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -14,7 +14,6 @@ import com.fr.base.theme.TemplateThemeCompatible;
import com.fr.base.theme.TemplateThemeConfig;
import com.fr.base.theme.ThemedTemplate;
import com.fr.base.vcs.DesignerMode;
import com.fr.decision.config.FSConfig;
import com.fr.design.DesignModelAdapter;
import com.fr.design.DesignState;
import com.fr.design.DesignerEnvManager;
@ -99,6 +98,7 @@ import com.fr.stable.StringUtils;
import com.fr.stable.core.UUID;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.lock.TplOperator;
import com.fr.workspace.server.repository.template.TemplateRepository;
import javax.swing.BorderFactory;
import javax.swing.Icon;
@ -1044,15 +1044,9 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
}
protected void checkBeforeSave() throws Exception {
// 保存前校验下未解锁
if (WorkContext.getCurrent().get(LockInfoOperator.class).isTplUnLocked(getEditingFILE().getPath())) {
throw new UnLockedException();
}
// 过滤掉本地文件
boolean localFile = getEditingFILE() instanceof FileFILE;
boolean inconsistent = !localFile && getEditingFILE().exists()
&& !WorkContext.getCurrent().get(LockInfoOperator.class).isConsistentLock(getEditingFILE().getPath());
if (inconsistent) {
if (!localFile && getEditingFILE().exists()) {
throw new InconsistentLockException();
}
}
@ -1728,6 +1722,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
if (editingFILE == null || editingFILE instanceof MemFILE) {
return false;
}
// 锁的check在服务器做
checkBeforeSave();
export();
this.editingFILE = editingFILE;
@ -1738,9 +1733,10 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
}
private boolean checkJTemplateAuthority() {
if (!FSConfig.getInstance().getAuthorizeAttr().isDataConnectionAuthority()) {
return true;
}
// todo:微服务待调整
//if (!FSConfig.getInstance().getAuthorizeAttr().isDataConnectionAuthority()) {
// return true;
//}
JTemplateAuthorityChecker jTemplateAuthorityChecker = new JTemplateAuthorityChecker(this);
if (jTemplateAuthorityChecker.isAuthority()) {
return true;
@ -1806,12 +1802,12 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
// 目标本地文件
!editingFILE.isEnvFile() ||
// 目标远程文件
WorkContext.getCurrent().get(TplOperator.class).saveAs(editingFILE.getPath());
TemplateRepository.getInstance().saveAs(editingFILE.getPath());
if (lockedTarget) {
boolean saved = saveNewRealFile(editingFILE, oldName);
// 目标文件保存成功并且源文件不一致的情况下,把源文件锁释放掉
if (saved && !ComparatorUtils.equals(editingFILE.getPath(), sourceFile.getPath())) {
WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(sourceFile.getPath());
TemplateRepository.getInstance().close(sourceFile.getPath());
}
return saved;
} else {

33
designer-base/src/main/java/com/fr/design/versioncheck/VersionCheckUtils.java

@ -198,22 +198,23 @@ public class VersionCheckUtils {
public static String getRemoteBranch(DesignerWorkspaceInfo selectedEnv) {
String remoteBranch;
remoteBranch = WorkContext.getCurrent().get(VersionInfoOperator.class, new ExceptionHandler<String>() {
@Override
public String callHandler(RPCInvokerExceptionInfo exceptionInfo) {
WorkspaceConnectionInfo connectionInfo = selectedEnv.getConnection();
String remoteBranch = StringUtils.EMPTY;
try {
remoteBranch = new FunctionalHttpRequest(connectionInfo).getServerBranch();
} catch (WorkspaceConnectionException e) {
remoteBranch = Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Branch_Is_Old") + formatBranch(GeneralUtils.readFullBuildNO());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return remoteBranch;
}
}).getFullBuildNO();
return remoteBranch;
// todo 微服务的branch还不确定,后面适配
//remoteBranch = WorkContext.getCurrent().get(VersionInfoOperator.class, new ExceptionHandler<String>() {
// @Override
// public String callHandler(RPCInvokerExceptionInfo exceptionInfo) {
// WorkspaceConnectionInfo connectionInfo = selectedEnv.getConnection();
// String remoteBranch = StringUtils.EMPTY;
// try {
// remoteBranch = new FunctionalHttpRequest(connectionInfo).getServerBranch();
// } catch (WorkspaceConnectionException e) {
// remoteBranch = Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Branch_Is_Old") + formatBranch(GeneralUtils.readFullBuildNO());
// } catch (Exception e) {
// FineLoggerFactory.getLogger().error(e.getMessage(), e);
// }
// return remoteBranch;
// }
//}).getFullBuildNO();
return StringUtils.EMPTY;
}
/**

3
designer-base/src/main/java/com/fr/file/FILEChooserPane.java

@ -1,5 +1,6 @@
package com.fr.file;
import com.fr.workspace.server.repository.system.WorkspaceSystemInfo;
import com.fr.base.BaseUtils;
import com.fr.base.FRContext;
import com.fr.base.extension.FileExtension;
@ -1497,7 +1498,7 @@ public class FILEChooserPane extends BasicPane {
if (!path.endsWith("/") && !path.endsWith("\\") && !StringUtils.isBlank(path)) {
path = path + "/";
}
String webAppName = GeneralContext.getCurrentAppNameOfEnv();
String webAppName = WorkspaceSystemInfo.getINSTANCE().getAppName();
if (StringUtils.isBlank(path) && isWebAppNamePath) {
this.buttonList.add(createBlankButton(new SetDirectoryAction(webAppName + '/')));
}

25
designer-base/src/main/java/com/fr/file/FileNodeFILE.java

@ -1,6 +1,5 @@
package com.fr.file;
import com.fr.base.BaseUtils;
import com.fr.base.FRContext;
import com.fr.base.svg.IconUtils;
import com.fr.design.file.TemplateResourceManager;
@ -23,7 +22,10 @@ import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import com.fr.workspace.WorkspaceEvent;
import com.fr.workspace.resource.WorkResourceTempRenameStream;
import com.fr.workspace.server.entity.WorkResourceTempRenameStream;
import com.fr.workspace.server.entity.template.TemplateListBean;
import com.fr.workspace.server.repository.system.WorkspaceSystemInfo;
import com.fr.workspace.server.repository.template.TemplateRepository;
import javax.swing.*;
import java.io.InputStream;
@ -33,15 +35,15 @@ import java.util.Arrays;
public class FileNodeFILE implements FILE {
public static String webRootPath = FRContext.getCommonOperator().getWebRootPath();
private static String[] supportTypes = FRContext.getFileNodes().getSupportedTypes();
public static String webRootPath = WorkspaceSystemInfo.getINSTANCE().getWebRootPath();
private static String[] supportTypes = TemplateRepository.getInstance().getSupportedTypes();
static {
EventDispatcher.listen(WorkspaceEvent.AfterSwitch, new Listener<Workspace>() {
@Override
public void on(Event event, Workspace workspace) {
webRootPath = FRContext.getCommonOperator().getWebRootPath();
supportTypes = FRContext.getFileNodes().getSupportedTypes();
webRootPath = WorkspaceSystemInfo.getINSTANCE().getWebRootPath();
supportTypes = TemplateRepository.getInstance().getSupportedTypes();
}
});
}
@ -256,11 +258,10 @@ public class FileNodeFILE implements FILE {
private FileNode[] listFile(String rootFilePath) {
try {
if (ComparatorUtils.equals(envPath, webRootPath)) {
return FRContext.getFileNodes().listWebRootFile(rootFilePath);
} else {
return FRContext.getFileNodes().list(rootFilePath);
}
TemplateListBean bean = new TemplateListBean();
bean.setTargetPath(rootFilePath);
bean.setListWebroot(ComparatorUtils.equals(envPath, webRootPath));
return TemplateRepository.getInstance().list(bean);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
@ -324,7 +325,7 @@ public class FileNodeFILE implements FILE {
}
try {
return TemplateResourceManager.getResource().exist(node.getEnvPath());
return TemplateRepository.getInstance().exists(node.getEnvPath());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return false;

5
designer-chart/src/main/java/com/fr/van/chart/map/designer/type/WMSLayerPane.java

@ -1,6 +1,6 @@
package com.fr.van.chart.map.designer.type;
import com.fr.decision.webservice.v10.map.MapEditService;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.event.UIObserver;
import com.fr.design.event.UIObserverListener;
@ -88,7 +88,8 @@ public class WMSLayerPane extends JPanel implements UIObserver {
@Override
protected Void doInBackground() {
List<String> wmsNames = MapEditService.getInstance().getWMSNames(wmsUrl.getText());
// todo 待实现[check]MapEditService.getInstance().getWMSNames(wmsUrl.getText());
List<String> wmsNames = new ArrayList<>();
list.clear();
for (String layer : wmsNames) {
list.add(new WMSLayer(layer, false));

29
designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoPane.java

@ -9,21 +9,24 @@ import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.FormWidgetDetailPane;
import com.fr.design.mainframe.reuse.SnapChatKeys;
import com.fr.design.mainframe.share.sort.WidgetSortType;
import com.fr.design.mainframe.share.ui.base.DownloadProgressPane;
import com.fr.design.mainframe.share.ui.base.MouseClickListener;
import com.fr.design.mainframe.share.ui.block.LocalWidgetBlock;
import com.fr.design.mainframe.share.ui.block.LocalWidgetUpdater;
import com.fr.design.mainframe.share.ui.widgetfilter.LocalWidgetFilter;
import com.fr.design.mainframe.share.util.InstallComponentHelper;
import com.fr.design.mainframe.share.util.ShareComponentUtils;
import com.fr.design.mainframe.theme.edit.ui.LabelUtils;
import com.fr.design.notification.SnapChat;
import com.fr.design.notification.SnapChatFactory;
import com.fr.form.share.Group;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.group.DefaultShareGroupManager;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.workspace.server.repository.widget.ShareRepository;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
@ -76,7 +79,9 @@ public class LocalWidgetRepoPane extends BasicPane {
private LocalWidgetRepoPane() {
initializePane(this);
//新用户预装组件
InstallComponentHelper.installPreComponent();
if (needPreInstallComponent()) {
ShareRepository.getInstance().installPreComponent();
}
doRefresh();
}
@ -88,6 +93,20 @@ public class LocalWidgetRepoPane extends BasicPane {
return keyWord4Searching;
}
private static boolean needPreInstallComponent() {
try {
//老用户或者组件库里已有组件,不预装组件
SnapChat snapChat = SnapChatFactory.createSnapChat(false, SnapChatKeys.COMPONENT);
return !snapChat.hasRead() ;
} catch (Throwable e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
private void initializePane(Container container) {
container.setLayout(new BorderLayout());
@ -353,11 +372,7 @@ public class LocalWidgetRepoPane extends BasicPane {
@Override
protected Boolean doInBackground() throws Exception {
if (isRefreshing.compareAndSet(false, true)) {
boolean isRefresh = DefaultShareGroupManager.getInstance().refresh();
if (isRefresh) {
ShareComponentUtils.checkReadMe();
}
return isRefresh;
return ShareRepository.getInstance().refresh();
}
return false;
}

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

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.init;
import com.fanruan.carina.annotions.ActivatorRefer;

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

@ -1,23 +1,24 @@
package com.fanruan.boot;
package com.fanruan.boot.init;
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.Stop;
import com.fanruan.carina.annotions.Supplemental;
import com.fanruan.workplace.http.RepositoryManager;
import com.fanruan.workplace.http.WorkspaceHeartBeatShell;
import com.fanruan.workplace.standard.ServerInfo;
import com.fanruan.workplace.standard.ServerInfoOperator;
import com.fr.decision.service.context.ServiceContext;
import com.fr.log.FineLoggerFactory;
import com.fr.design.env.HttpWorkspaceConnector;
import com.fr.security.encryption.storage.StorageEncryptors;
import com.fr.security.encryption.storage.StorageTransfer;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.base.WorkspaceAPI;
import com.fr.workspace.base.WorkspaceKey;
import com.fr.workspace.engine.FineWorkspaceFactory;
import com.fr.workspace.engine.base.FineObjectPool;
import com.fr.workspace.engine.client.FineWorkspaceConnector;
import com.fr.workspace.engine.client.heartbeart.FineWorkspaceHeartbeat;
import com.fr.workspace.engine.client.heartbeart.WorkspaceHeartbeat;
import com.fr.workspace.engine.resource.FineWorkResource;
@ -25,6 +26,14 @@ import com.fr.workspace.engine.resource.FineWorkResourceAdaptor;
import com.fr.workspace.pool.WorkRPCRegister;
import com.fr.workspace.pool.WorkRPCType;
import com.fr.workspace.resource.WorkResource;
import com.fr.workspace.server.repository.authority.RemoteAuthorityRepository;
import com.fr.workspace.server.repository.connect.RemoteNetworkRepository;
import com.fr.workspace.server.repository.connection.ConnectionRepository;
import com.fr.workspace.server.repository.system.SystemInfoRepository;
import com.fr.workspace.server.repository.tabledata.TableDataRepository;
import com.fr.workspace.server.repository.template.TemplateRepository;
import com.fr.workspace.server.repository.vcs.VcsRepository;
import com.fr.workspace.server.repository.widget.ShareRepository;
/**
* 设计器工作环境调用类初始化模块主要负责将各个模块注册的方法注入进来
@ -34,7 +43,7 @@ import com.fr.workspace.resource.WorkResource;
* Created on 2024/5/28
*/
@FineComponent(name = "design_workcontext")
@DependsOn(dependencies = {"design_start_up", "i18n", "class", "design_serialization"})
@DependsOn(dependencies = {"design_pre_load", "i18n", "class", "design_serialization"})
public class DesignWorkContextComponent {
private static final String VERSION_NUM = "01";
@ -45,7 +54,7 @@ public class DesignWorkContextComponent {
*/
@Supplemental
public void prepare() {
// 纯启动部分的代码不涉及Repository的更改,下一批提交会改掉
Carina.getApplicationContext().singleton(WorkspaceHeartBeatShell.class).set(new FineWorkspaceHeartbeat());
ServiceContext.group(WorkspaceKey.class).addAll(
WorkRPCRegister.wrap(ServerInfoOperator.class, new ServerInfo()),
WorkRPCRegister.wrap(WorkRPCType.Local, WorkResource.class, FineWorkResource.getInstance()),
@ -59,13 +68,22 @@ public class DesignWorkContextComponent {
*/
@Start
public void start() {
RepositoryManager.getInstance().pureRegisterRepo4Start(ConnectionRepository.getInstance());
RepositoryManager.getInstance().pureRegisterRepo4Start(RemoteAuthorityRepository.getInstance());
RepositoryManager.getInstance().pureRegisterRepo4Start(RemoteNetworkRepository.getInstance());
RepositoryManager.getInstance().pureRegisterRepo4Start(SystemInfoRepository.getInstance());
RepositoryManager.getInstance().pureRegisterRepo4Start(TableDataRepository.getInstance());
RepositoryManager.getInstance().pureRegisterRepo4Start(TemplateRepository.getInstance());
RepositoryManager.getInstance().pureRegisterRepo4Start(VcsRepository.getInstance());
RepositoryManager.getInstance().pureRegisterRepo4Start(ShareRepository.getInstance());
for (WorkRPCRegister<?> workRPCRegister : ServiceContext.group(WorkspaceKey.class).getAll()) {
validate(workRPCRegister.getClazz());
FineObjectPool.getInstance().add(workRPCRegister.getClazz(), workRPCRegister.getType(), workRPCRegister.getObject());
}
WorkContext.setConnector(FineWorkspaceConnector.getInstance());
WorkContext.setConnector(HttpWorkspaceConnector.getInstance());
WorkContext.setFactory(FineWorkspaceFactory.getInstance());
WorkContext.setWorkResource(new FineWorkResourceAdaptor());
@ -92,8 +110,5 @@ public class DesignWorkContextComponent {
if (clazz == null) {
return;
}
if (clazz.getAnnotation(WorkspaceAPI.class) == null) {
FineLoggerFactory.getLogger().warn("workspace service {} not annotated with @Workspace.", clazz);
}
}
}

6
designer-realize/src/main/java/com/fanruan/boot/DesignerInitComponent.java → designer-realize/src/main/java/com/fanruan/boot/init/DesignerInitComponent.java

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.init;
import com.fanruan.carina.annotions.ActivatorRefer;
import com.fanruan.carina.annotions.DependsOn;
@ -9,14 +9,14 @@ import com.fr.start.module.optimized.DesignerStartupPageActivator;
/**
* 设计器界面初始化模块
* <p>负责设计器基础界面初始化+设计器启动页初始化</p>
* <p>设计器启动两个阶段中的第一阶段到该模块加载完表示设计器基础的前置初始化界面国际化等杂七杂八的东西全部结束了后面要正式开始数据与功能模块的初始化</p>
* <p>设计器启动三个阶段中的第二阶段到该模块加载完表示设计器基础的前置初始化界面国际化等杂七杂八的东西全部结束了后面要正式开始数据与功能模块的初始化</p>
*
* @author Destiny.Lin
* @since 11.0
* Created on 2024/5/27
*/
@FineComponent(name = "design_init")
@DependsOn(dependencies = {"design_start_up", "design_tenant", "design_workcontext", "design_xml", "design_serialization"})
@DependsOn(dependencies = {"design_start_up", "design_workcontext", "design_xml", "design_serialization"})
@ActivatorRefer(refer = {
DesignerInitActivator.class,
DesignerStartupPageActivator.class,

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

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.init;
import com.fanruan.carina.Carina;
import com.fanruan.carina.annotions.FineComponent;

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

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.init;
import com.fanruan.carina.Carina;
import com.fanruan.carina.annotions.DependsOn;

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

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.init;
import com.fanruan.carina.annotions.ActivatorRefer;

28
designer-realize/src/main/java/com/fanruan/boot/pre/DesignConfigComponent.java

@ -0,0 +1,28 @@
package com.fanruan.boot.pre;
import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.Start;
import com.fanruan.config.ConfigProviderFactory;
import com.fanruan.config.impl.PublicConfigProviderImpl;
import com.fanruan.config.impl.ShareConfigProviderImpl;
import com.fanruan.config.realm.ConfigRealm;
import com.fanruan.config.realm.ConfigRepositoryFactory;
import com.fanruan.config.realm.mem.MemConfigRepositoryBuilder;
/**
* 类解释注释
*
* @author Destiny.Lin
* @since 11.0
* Created on 2024/5/29
*/
@FineComponent(name = "design_universal_config")
public class DesignConfigComponent {
@Start
public void start() {
ConfigProviderFactory.getInstance().registerProvider(ConfigRealm.SHARE, new ShareConfigProviderImpl());
ConfigProviderFactory.getInstance().registerProvider(ConfigRealm.PUBLIC, new PublicConfigProviderImpl());
ConfigRepositoryFactory.getInstance().registerConfigRepositoryBuilder(new MemConfigRepositoryBuilder());
}
}

24
designer-realize/src/main/java/com/fanruan/boot/pre/DesignPluginSupplementComponent.java

@ -0,0 +1,24 @@
package com.fanruan.boot.pre;
import com.fanruan.boot.PluginComponent;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.Start;
import com.fanruan.carina.annotions.Supplemental;
/**
* 类解释注释
*
* @author Destiny.Lin
* @since 11.0
* Created on 2024/5/31
*/
@FineComponent(name = "design_plugin_supplement")
@DependsOn(dependencies = {"design_tenant", "design_universal_config"})
public class DesignPluginSupplementComponent extends PluginComponent {
@Start
public void start() {
super.prepare();
}
}

151
designer-realize/src/main/java/com/fanruan/boot/pre/DesignPreStartComponent.java

@ -0,0 +1,151 @@
package com.fanruan.boot.pre;
import com.fanruan.boot.key.StartupArgsShell;
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.carina.context.CarinaApplicationContext;
import com.fanruan.carina.lifecycle.bootstrap.BootstrapFactory;
import com.fanruan.carina.standard.PartitionManager;
import com.fanruan.carina.standard.PartitionManagerImpl;
import com.fr.base.StateHubContext;
import com.fr.base.function.UITerminator;
import com.fr.design.DesignerEnvManager;
import com.fr.design.deeplink.DeepLinkManager;
import com.fr.design.fun.OemProcessor;
import com.fr.design.mainframe.messagecollect.StartErrorMessageCollector;
import com.fr.design.mainframe.messagecollect.entity.DesignerErrorMessage;
import com.fr.design.monitor.DesignerLifecycleMonitorContext;
import com.fr.design.ui.util.UIUtil;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.DesignerPort;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.log.FineLoggerFactory;
import com.fr.module.engine.event.LifecycleErrorEvent;
import com.fr.runtime.FineRuntime;
import com.fr.stable.lifecycle.FineLifecycleFatalError;
import com.fr.start.DesignContext;
import com.fr.start.DesignLauncher;
import com.fr.start.DesignerSubListener;
import com.fr.start.EmptyServletContext;
import com.fr.start.LifecycleFatalErrorHandler;
import com.fr.start.OemHandler;
import com.fr.start.SplashContext;
import com.fr.start.SplashStrategy;
import com.fr.start.common.SplashCommon;
import com.fr.start.preload.PreLoadService;
import java.util.concurrent.CompletableFuture;
/**
* 设计器启动前处理的模块入口
*
* @author Destiny.Lin
* @since 11.0
* Created on 2024/5/31
*/
@FineComponent(name = "design_pre_start")
@DependsOn(dependencies = {"design_universal_config", "design_tenant", "design_plugin_supplement"})
public class DesignPreStartComponent {
@Start
public void start() {
DesignerEnvManager.getEnvManager();
startPreload0();
DesignerLifecycleMonitorContext.getMonitor().beforeStart();
//启动运行时
FineRuntime.start();
//等 FineRuntime 启动后启动
DeepLinkManager.getInstance().start(Carina.getApplicationContext().singleton(StartupArgsShell.class).get().get());
startPreload1();
DesignerSubListener.getInstance().start();
EventDispatcher.listen(LifecycleErrorEvent.SELF, new Listener<FineLifecycleFatalError>() {
@Override
public void on(Event event, FineLifecycleFatalError param) {
LifecycleFatalErrorHandler.getInstance().handle(param);
}
});
try {
BootstrapFactory.get().start("design_init");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* {@link FineRuntime#start()} 运行后
*/
protected static void startPreload1() {
CompletableFuture<Void> initLookAndFeel = CompletableFuture.runAsync(DesignUtils::initLookAndFeel);
PreLoadService.getInstance().addUIFuture(initLookAndFeel);
showSplash();
}
/**
* {@link FineRuntime#start()} 运行前
*/
protected static void startPreload0() {
PreLoadService.getInstance().addRunnable(() -> {
if (DesignUtils.isPortOccupied()) {
UITerminator action = new UITerminator() {
@Override
protected void doRun() {
StartErrorMessageCollector.getInstance().record(DesignerErrorMessage.PORT_OCCUPIED.getId(),
DesignerErrorMessage.PORT_OCCUPIED.getMessage());
DesignerPort.getInstance().resetPort();
}
};
action.run();
}
});
}
private static void showSplash() {
// 快快显示启动画面
// vito: 这里必须用 wait, 不然会导致莫名其妙的问题
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
SplashContext.getInstance().registerSplash(createSplash());
SplashContext.getInstance().show();
}
});
}
private static SplashStrategy createSplash() {
OemProcessor oemProcessor = OemHandler.findOem();
if (oemProcessor != null) {
SplashStrategy splashStrategy = null;
try {
splashStrategy = oemProcessor.createSplashStrategy();
} catch (Throwable e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
if (splashStrategy != null) {
return splashStrategy;
}
}
return new SplashCommon();
}
}

14
designer-realize/src/main/java/com/fanruan/boot/DesignTenantComponent.java → designer-realize/src/main/java/com/fanruan/boot/pre/DesignTenantComponent.java

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.pre;
import com.fanruan.carina.Carina;
import com.fanruan.carina.annotions.DependsOn;
@ -21,7 +21,7 @@ import java.util.ArrayList;
* Created on 2024/5/24
*/
@FineComponent(name = "design_tenant")
@DependsOn(dependencies = {"design_start_up"})
@DependsOn(dependencies = {})
public class DesignTenantComponent {
/**
@ -31,12 +31,12 @@ public class DesignTenantComponent {
public void start() {
TenantContext.registerStorage(new DefaultTenantStorage());
TenantContext.registerConfigProvider(new TenantConfigProvider() {
@Override
public boolean isMultiTenantOpen() {
return false;
}
@Override
public boolean isMultiTenantOpen() {
return false;
}
});
PlatformScaffoldTenantStarter.start(new ArrayList<>(Carina.getApplicationContext().group(CurrentTenantKey.class).getAll()));
PlatformScaffoldTenantStarter.start(new ArrayList<>(Carina.getApplicationContext().group(CurrentTenantKey.class).getAll()));
}

5
designer-realize/src/main/java/com/fanruan/boot/DesignConfConfigComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignConfConfigComponent.java

@ -1,5 +1,6 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.boot.ConfConfigComponent;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.JPAEntityScan;
@ -16,7 +17,7 @@ import com.fanruan.carina.annotions.Stop;
@FineComponent(name = "design_conf_config")
@JPAEntityScan("com.fr.config.entity")
@DependsOn(dependencies = {"design_dao", "design_core_supplemental"})
public class DesignConfConfigComponent extends ConfConfigComponent{
public class DesignConfConfigComponent extends ConfConfigComponent {
/**

5
designer-realize/src/main/java/com/fanruan/boot/DesignCoreSupplementalComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignCoreSupplementalComponent.java

@ -1,5 +1,6 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.boot.CoreSupplementalComponent;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.Start;
@ -16,7 +17,7 @@ import com.fanruan.carina.annotions.Supplemental;
*/
@FineComponent(name = "design_core_supplemental")
@DependsOn(dependencies = {"env"})
public class DesignCoreSupplementalComponent extends CoreSupplementalComponent{
public class DesignCoreSupplementalComponent extends CoreSupplementalComponent {
/**

2
designer-realize/src/main/java/com/fanruan/boot/DesignEnvComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignEnvComponent.java

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.carina.annotions.ActivatorRefer;
import com.fanruan.carina.annotions.FineComponent;

5
designer-realize/src/main/java/com/fanruan/boot/DesignFunctionComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignFunctionComponent.java

@ -1,9 +1,10 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.carina.annotions.ActivatorRefer;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;
import com.fr.chart.activator.ChartBaseActivator;
import com.fr.data.DatasourceActivator;
import com.fr.form.module.FormBaseActivator;
import com.fr.report.module.ReportBaseActivator;
import com.fr.workspace.server.vcs.VcsFolderManagerActivator;
@ -18,6 +19,6 @@ import com.fr.workspace.server.vcs.VcsFolderManagerActivator;
*/
@FineComponent(name = "design_function")
@DependsOn(dependencies = {"design_core_supplemental", "design_dao", "design_conf_config", "design_update"})
@ActivatorRefer(refer = {ChartBaseActivator.class, ReportBaseActivator.class, VcsFolderManagerActivator.class, FormBaseActivator.class})
@ActivatorRefer(refer = {DatasourceActivator.class, ChartBaseActivator.class, ReportBaseActivator.class, VcsFolderManagerActivator.class, FormBaseActivator.class})
public class DesignFunctionComponent {
}

5
designer-realize/src/main/java/com/fanruan/boot/DesignLoggerComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignLoggerComponent.java

@ -1,6 +1,7 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.boot.LoggerComponent;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.Start;
@ -16,7 +17,7 @@ import com.fanruan.carina.annotions.Stop;
*/
@FineComponent(name = "design_logger")
@DependsOn(dependencies = {"design_core_supplemental", "design_dao", "design_conf_config"})
public class DesignLoggerComponent extends LoggerComponent{
public class DesignLoggerComponent extends LoggerComponent {
/**

5
designer-realize/src/main/java/com/fanruan/boot/DesignPluginComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignPluginComponent.java

@ -1,5 +1,6 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.boot.PluginComponent;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.Start;
@ -15,7 +16,7 @@ import javax.servlet.ServletContext;
*/
@FineComponent(name = "design_plugin")
@DependsOn(dependencies = {"design_core_supplemental", "design_dao", "design_conf_config", "design_logger"})
public class DesignPluginComponent extends PluginComponent{
public class DesignPluginComponent extends PluginComponent {
/**
* start

2
designer-realize/src/main/java/com/fanruan/boot/DesignUpdateComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignUpdateComponent.java

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.carina.annotions.ActivatorRefer;
import com.fanruan.carina.annotions.DependsOn;

2
designer-realize/src/main/java/com/fanruan/boot/DesignWorkspaceComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignWorkspaceComponent.java

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.carina.annotions.ActivatorRefer;
import com.fanruan.carina.annotions.DependsOn;

2
designer-realize/src/main/java/com/fanruan/boot/DesignWorkspaceRegisterComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignWorkspaceRegisterComponent.java

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.carina.annotions.ActivatorRefer;
import com.fanruan.carina.annotions.DependsOn;

2
designer-realize/src/main/java/com/fanruan/boot/DesignerComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignerComponent.java

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.carina.annotions.ActivatorRefer;
import com.fanruan.carina.annotions.DependsOn;

5
designer-realize/src/main/java/com/fanruan/boot/DesignerDaoComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignerDaoComponent.java

@ -1,6 +1,7 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.boot.DAOComponent;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;
import com.fanruan.carina.annotions.Start;
@ -16,7 +17,7 @@ import com.fanruan.carina.annotions.Stop;
*/
@FineComponent(name ="design_dao")
@DependsOn(dependencies = {"design_core_supplemental"})
public class DesignerDaoComponent extends DAOComponent{
public class DesignerDaoComponent extends DAOComponent {
/**

2
designer-realize/src/main/java/com/fanruan/boot/DesignerShowComponent.java → designer-realize/src/main/java/com/fanruan/boot/show/DesignerShowComponent.java

@ -1,4 +1,4 @@
package com.fanruan.boot;
package com.fanruan.boot.show;
import com.fanruan.carina.annotions.DependsOn;
import com.fanruan.carina.annotions.FineComponent;

3
designer-realize/src/main/java/com/fr/design/mainframe/InformationCollector.java

@ -143,7 +143,8 @@ public class InformationCollector implements XMLReadable, XMLWriter {
*/
public void collectStartTime() {
this.current.setStartDate(dateToString());
sendInfo();
// todo 收集信息先关掉,后面再适配
//sendInfo();
}
private void sendInfo() {

4
designer-realize/src/main/java/com/fr/design/report/ReportEnginePane.java

@ -1,5 +1,6 @@
package com.fr.design.report;
import com.fanruan.cloud.FanruanCloud;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.editor.editor.IntegerEditor;
@ -13,7 +14,6 @@ import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.widget.FRWidgetFactory;
import com.fr.general.SiteCenter;
import com.fr.log.FineLoggerFactory;
import com.fr.report.core.ReportUtils;
import com.fr.report.stable.LayerReportAttr;
@ -203,7 +203,7 @@ public class ReportEnginePane extends BasicBeanPane<LayerReportAttr> {
@Override
public void mouseClicked(MouseEvent e) {
try {
Desktop.getDesktop().browse(new URI(SiteCenter.getInstance().acquireUrlByKind("standard.doc", ProductConstants.WEBSITE_URL)));
Desktop.getDesktop().browse(new URI(FanruanCloud.siteCenter().acquireUrlByKind("standard.doc", ProductConstants.WEBSITE_URL)));
} catch (IOException | URISyntaxException ex) {
FineLoggerFactory.getLogger().error("io exception or not find website", ex);
}

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

@ -5,20 +5,13 @@ 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.fr.design.DesignerEnvManager;
import com.fr.base.StateHubContext;
import com.fr.design.carton.SwitchForSwingChecker;
import com.fr.design.deeplink.DeepLinkManager;
import com.fr.design.monitor.DesignerLifecycleMonitorContext;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.log.FineLoggerFactory;
import com.fr.module.engine.event.LifecycleErrorEvent;
import com.fr.runtime.FineRuntime;
import com.fr.stable.lifecycle.FineLifecycleFatalError;
import com.fr.start.common.DesignerStartupContext;
import com.fr.start.module.StartupArgs;
import com.fr.workspace.WorkContext;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
@ -40,36 +33,18 @@ public class CarinaDesigner extends MainDesigner{
* main
*/
public static void main(String[] args) {
DesignerStartupContext.getRecorder().start();
PartitionManager manager = new PartitionManagerImpl();
StateHubContext.setReady(false);
CarinaApplicationContext carinaApplicationContext = new DesignContext(new EmptyServletContext(), manager, new Properties());
Carina.setApplicationContext(carinaApplicationContext);
Carina.setPartitionManager(manager);
DesignLauncher.setContext(carinaApplicationContext);
DesignerEnvManager.getEnvManager();
startPreload0();
DesignerLifecycleMonitorContext.getMonitor().beforeStart();
//启动运行时
FineRuntime.start();
//等 FineRuntime 启动后启动
DeepLinkManager.getInstance().start(args);
startPreload1();
DesignerSubListener.getInstance().start();
EventDispatcher.listen(LifecycleErrorEvent.SELF, new Listener<FineLifecycleFatalError>() {
@Override
public void on(Event event, FineLifecycleFatalError param) {
LifecycleFatalErrorHandler.getInstance().handle(param);
}
});
Carina.getApplicationContext().singleton(StartupArgsShell.class).set(new StartupArgs(args));
DesignLauncher launch = new DesignLauncher("/com/fr/config/starter/designer-startup-carina.xml");
try {
FineLoggerFactory.getLogger().debug("Designer prepared.Time used {} ms", DesignerStartupContext.getRecorder().getTime(TimeUnit.MILLISECONDS));
Carina.getApplicationContext().singleton(StartupArgsShell.class).set(new StartupArgs(args));
launch.launch();
} catch (Exception e) {
throw new RuntimeException(e);

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

@ -65,7 +65,7 @@ public class DesignLauncher extends XmlCarinaLauncher {
protected void startComponentsAndServices() throws CarinaException {
try {
BootstrapFactory.get().supplement();
BootstrapFactory.get().start("design_init");
BootstrapFactory.get().start("design_pre_start");
} catch (Exception e) {
throw new RuntimeException(e);
}

3
designer-realize/src/main/java/com/fr/start/SplashContext.java

@ -152,7 +152,8 @@ public class SplashContext {
*/
private void showThanks() {
if (shouldShowThanks() && !hasShowThanks) {
tryFetchOnline();
// todo 涉及到云中心的都先放着
//tryFetchOnline();
if (StringUtils.isNotEmpty(guest)) {
updateThanksLog(THANKS + guest);
hasShowThanks = true;

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

@ -55,8 +55,8 @@ public class DesignerStartupPageActivator extends Activator {
DesignerStartupContext context = DesignerStartupContext.getInstance();
context.setStartupArgs(startupArgsValue.getValue());
if (context.isShowStartupPage()) {
// 目前先只支持启动页
if (true) {
showDesignerStartupPage(context);
} else {
startNonStartupPage();

116
designer-realize/src/main/java/com/fr/start/module/optimized/TenantDBAdapter4Designer.java

@ -1,58 +1,58 @@
package com.fr.start.module.optimized;
import com.fanruan.carina.Carina;
import com.fanruan.dao.shell.DBContextShell;
import com.fr.config.BaseDBEnv;
import com.fr.config.dao.DaoSelectorFactory;
import com.fr.config.dao.swicter.DaoSwitcher;
import com.fr.design.DesignerEnvManager;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.exit.ConfigToPropMigrator;
import com.fr.stable.db.DBContext;
import com.fr.stable.db.tenant.TenantDBAdapter;
import com.fr.start.event.LazyStartupEvent;
import com.fr.start.server.EmbedServerEvent;
/**
* @author hades
* @version 11.0
* Created by hades on 2022/3/7
*/
public class TenantDBAdapter4Designer extends TenantDBAdapter {
@Override
public void start() {
BaseDBEnv.setDBContext((DBContext) Carina.getApplicationContext().singleton(DBContextShell.class).get());
if (DaoSelectorFactory.getDaoSelector().useCacheDao()) {
listenEvent(LazyStartupEvent.INSTANCE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
TenantDBAdapter4Designer.super.start();
afterStart();
}
});
listenEvent(EmbedServerEvent.BeforeStart, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
if (DaoSelectorFactory.getDaoSelector().useCacheDao()) {
EventDispatcher.fire(LazyStartupEvent.INSTANCE);
}
}
});
} else {
super.start();
}
}
private void afterStart() {
DesignerEnvManager.getEnvManager().setPropertiesUsable(false);
DaoSwitcher.executeSwitch();
ConfigToPropMigrator.getInstance().deletePropertiesCache();
DesignerEnvManager.getEnvManager().saveXMLFile();
}
}
//package com.fr.start.module.optimized;
//
//import com.fanruan.carina.Carina;
//import com.fanruan.dao.shell.DBContextShell;
//import com.fr.config.BaseDBEnv;
//import com.fr.config.dao.DaoSelectorFactory;
//import com.fr.config.dao.swicter.DaoSwitcher;
//import com.fr.design.DesignerEnvManager;
//import com.fr.event.Event;
//import com.fr.event.EventDispatcher;
//import com.fr.event.Listener;
//import com.fr.event.Null;
//import com.fr.exit.ConfigToPropMigrator;
//import com.fr.stable.db.DBContext;
//import com.fr.stable.db.tenant.TenantDBAdapter;
//import com.fr.start.event.LazyStartupEvent;
//import com.fr.start.server.EmbedServerEvent;
//
///**
// * @author hades
// * @version 11.0
// * Created by hades on 2022/3/7
// */
//public class TenantDBAdapter4Designer extends TenantDBAdapter {
//
// @Override
// public void start() {
// BaseDBEnv.setDBContext((DBContext) Carina.getApplicationContext().singleton(DBContextShell.class).get());
// if (DaoSelectorFactory.getDaoSelector().useCacheDao()) {
// listenEvent(LazyStartupEvent.INSTANCE, new Listener<Null>() {
// @Override
// public void on(Event event, Null param) {
// TenantDBAdapter4Designer.super.start();
// afterStart();
// }
// });
//
// listenEvent(EmbedServerEvent.BeforeStart, new Listener<Null>() {
// @Override
// public void on(Event event, Null param) {
// if (DaoSelectorFactory.getDaoSelector().useCacheDao()) {
// EventDispatcher.fire(LazyStartupEvent.INSTANCE);
// }
// }
// });
//
// } else {
// super.start();
// }
// }
//
// private void afterStart() {
// DesignerEnvManager.getEnvManager().setPropertiesUsable(false);
// DaoSwitcher.executeSwitch();
// ConfigToPropMigrator.getInstance().deletePropertiesCache();
// DesignerEnvManager.getEnvManager().saveXMLFile();
// }
//}

Loading…
Cancel
Save