Browse Source
* commit '18a7bf34c1a4d63ecaddf340488472f279ac047f': 无jira任务,修复打包报错 无jira任务,修复打包报错 REPORT-114392 FR-FBP版本本地设计适配 去除模板主题中的frm选项 REPORT-114392 FR-FBP版本本地设计适配 修复数据连接预览 REPORT-114392 FR-FBP版本本地设计适配 修复国际化 REPORT-114392 FR-FBP版本本地设计适配 修复数据连接 REPORT-114392 FR-FBP版本本地设计适配 修复数据连接保存 REPORT-114392 FR-FBP版本本地设计适配 关闭环境监测 REPORT-127453 frm问题处理 REPORT-114391 【微服务适配】远程&本地设计器能够正常启动 修复序列化问题 REPORT-114391 【微服务适配】远程&本地设计器能够正常启动 代码规范 REPORT-114391 【微服务适配】远程&本地设计器能够正常启动 修复图表配置+优化环境切换 REPORT-114391 【微服务适配】远程&本地设计器能够正常启动 优化断开提醒 REPORT-114391 【微服务适配】远程&本地设计器能够正常启动 优化启动与切换fbp-1.0
22 changed files with 441 additions and 66 deletions
@ -0,0 +1,159 @@ |
|||||||
|
package com.fr.design; |
||||||
|
|
||||||
|
import com.fr.design.dialog.FineJOptionPane; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.design.ui.util.UIUtil; |
||||||
|
import com.fr.event.Event; |
||||||
|
import com.fr.event.EventDispatcher; |
||||||
|
import com.fr.event.Listener; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.StableUtils; |
||||||
|
import com.fr.third.org.apache.http.client.config.RequestConfig; |
||||||
|
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse; |
||||||
|
import com.fr.third.org.apache.http.client.methods.HttpGet; |
||||||
|
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient; |
||||||
|
import com.fr.third.org.apache.http.impl.client.HttpClients; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.Workspace; |
||||||
|
import com.fr.workspace.WorkspaceEvent; |
||||||
|
import com.fr.workspace.base.WorkspaceConstants; |
||||||
|
import com.fr.workspace.connect.WorkspaceConnectionInfo; |
||||||
|
import com.fr.workspace.engine.channel.WorkspaceChannelFactory; |
||||||
|
import com.fr.workspace.engine.exception.WorkspaceConnectionException; |
||||||
|
|
||||||
|
import javax.swing.JOptionPane; |
||||||
|
import javax.swing.UIManager; |
||||||
|
|
||||||
|
/** |
||||||
|
* RPC连接处理中心 |
||||||
|
* |
||||||
|
* @author Roger |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2023/12/13 |
||||||
|
*/ |
||||||
|
public class RPCConnectHandlerCenter { |
||||||
|
|
||||||
|
private static volatile boolean alerting = false; |
||||||
|
private static final int TIMEOUT = 5000; |
||||||
|
|
||||||
|
private static Listener<Workspace> listener = new Listener<Workspace>() { |
||||||
|
@Override |
||||||
|
public void on(Event event, Workspace workspace) { |
||||||
|
//暂时先不做重连处理,3次RPC连接失败后提示切换工作目录
|
||||||
|
showRPCDisconnectDialog(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* 开启事件监听 |
||||||
|
*/ |
||||||
|
public static void startListener() { |
||||||
|
if (!WorkContext.getCurrent().isLocal()) { |
||||||
|
EventDispatcher.listen(WorkspaceEvent.LostConnect, listener); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 弹窗提示连接断开 |
||||||
|
*/ |
||||||
|
public static void showRPCDisconnectDialog() { |
||||||
|
UIUtil.invokeLaterIfNeeded(RPCConnectHandlerCenter::showDialog); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* RPC连接测试 |
||||||
|
* |
||||||
|
* @param info 连接信息 |
||||||
|
* @return 是否连接成功 |
||||||
|
*/ |
||||||
|
public static boolean checkRPCConnect(WorkspaceConnectionInfo info) { |
||||||
|
try { |
||||||
|
return WorkspaceChannelFactory.testConnection(info); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e, e.getMessage()); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* http连接检测,从DesignerSocketIO中移过来的,先保留着 |
||||||
|
* |
||||||
|
* @param info 连接信息 |
||||||
|
* @return 是否连接成功 |
||||||
|
*/ |
||||||
|
public static boolean checkHttpConnect(WorkspaceConnectionInfo info) { |
||||||
|
CloseableHttpClient httpclient = HttpClients.createDefault(); |
||||||
|
HttpGet httpGet = new HttpGet(StableUtils.pathJoin(info.getUrl(), WorkspaceConstants.CONTROLLER_PREFIX, WorkspaceConstants.VT)); |
||||||
|
RequestConfig requestConfig = RequestConfig |
||||||
|
.custom() |
||||||
|
.setConnectTimeout(TIMEOUT) |
||||||
|
.setConnectionRequestTimeout(TIMEOUT) |
||||||
|
.build(); |
||||||
|
httpGet.setConfig(requestConfig); |
||||||
|
try { |
||||||
|
CloseableHttpResponse response = httpclient.execute(httpGet); |
||||||
|
if (isErrorStatus(response.getStatusLine().getStatusCode())) { |
||||||
|
//这边nginx做负载,服务器被kill掉,返回的是502,不会抛错,导致checkRPCConnect通过
|
||||||
|
//针对500-600的错误码加个判断,其他类型的状态码暂不考虑,如果有遇到再处理,不然怕影响范围大
|
||||||
|
throw new WorkspaceConnectionException("Response " + response.getStatusLine().toString()); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e, e.getMessage()); |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 提示连接已经断开,如果已经在提示中了就直接返回 |
||||||
|
*/ |
||||||
|
private static void showDialog() { |
||||||
|
if (alerting) { |
||||||
|
return; |
||||||
|
} |
||||||
|
synchronized (RPCConnectHandlerCenter.class) { |
||||||
|
if (alerting) { |
||||||
|
return; |
||||||
|
} |
||||||
|
alerting = true; |
||||||
|
try { |
||||||
|
FineJOptionPane.showMessageDialog( |
||||||
|
DesignerContext.getDesignerFrame(), |
||||||
|
Toolkit.i18nText("Fine-Design_Basic_Remote_Disconnected"), |
||||||
|
UIManager.getString("OptionPane.messageDialogTitle"), |
||||||
|
JOptionPane.ERROR_MESSAGE, |
||||||
|
UIManager.getIcon("OptionPane.errorIcon")); |
||||||
|
EnvChangeEntrance.getInstance().chooseEnv(); |
||||||
|
} finally { |
||||||
|
alerting = false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 错误状态码 |
||||||
|
* 5xx(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。代码 说明 |
||||||
|
* 500 (服务器内部错误) 服务器遇到错误,无法完成请求。 |
||||||
|
* 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。 |
||||||
|
* 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。 |
||||||
|
* 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。 |
||||||
|
* 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 |
||||||
|
* 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。 |
||||||
|
* |
||||||
|
* @param status 错误状态码 |
||||||
|
* @return 是否是错误状态码 |
||||||
|
*/ |
||||||
|
private static boolean isErrorStatus(int status) { |
||||||
|
return status >= 500 && status <= 600; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 停止事件监听 |
||||||
|
*/ |
||||||
|
public static void stopListener() { |
||||||
|
if (!WorkContext.getCurrent().isLocal()) { |
||||||
|
EventDispatcher.stopListen(listener); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,129 @@ |
|||||||
|
package com.fr.design.data.datapane.preview; |
||||||
|
|
||||||
|
import com.fr.data.auth.AuthenticationType; |
||||||
|
import com.fr.data.auth.kerberos.KerberosAuthentication; |
||||||
|
import com.fr.data.auth.kerberos.KerberosUtils; |
||||||
|
import com.fr.data.impl.Connection; |
||||||
|
import com.fr.data.impl.JDBCDatabaseConnection; |
||||||
|
import com.fr.data.impl.NameDatabaseConnection; |
||||||
|
import com.fr.data.pool.DBCPConnectionPoolAttr; |
||||||
|
import com.fr.data.security.ssh.BaseSsh; |
||||||
|
import com.fr.data.security.ssh.SshType; |
||||||
|
import com.fr.data.security.ssh.impl.KeyVerifySsh; |
||||||
|
import com.fr.data.security.ssl.BaseSsl; |
||||||
|
import com.fr.data.security.ssl.SslType; |
||||||
|
import com.fr.data.security.ssl.impl.NormalSsl; |
||||||
|
import com.fr.decision.privilege.TransmissionTool; |
||||||
|
import com.fr.decision.webservice.bean.datasource.ConnectionInfoBean; |
||||||
|
import com.fr.decision.webservice.bean.datasource.JDBCConnectionBean; |
||||||
|
import com.fr.decision.webservice.utils.DecisionServiceConstants; |
||||||
|
import com.fr.decision.webservice.v10.datasource.connection.processor.impl.ConnectionProcessorFactory; |
||||||
|
import com.fr.decision.webservice.v10.datasource.connection.processor.impl.JDBCConnectionProcessor; |
||||||
|
import com.fr.security.encryption.transmission.TransmissionEncryptors; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.third.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据连接传输工具类 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2024/7/25 |
||||||
|
*/ |
||||||
|
public class ConnectionInfoBeanHelper { |
||||||
|
private static ObjectMapper objectMapper = new ObjectMapper(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建数据连接Bean,可自定义是否携带密码 |
||||||
|
*/ |
||||||
|
public static ConnectionInfoBean createConnectionInfoBean(String name, Connection connection, boolean withPassword) throws Exception { |
||||||
|
if (connection instanceof NameDatabaseConnection) { |
||||||
|
name = ((NameDatabaseConnection) connection).getName(); |
||||||
|
connection = ((NameDatabaseConnection) connection).createDatabase(); |
||||||
|
} |
||||||
|
if (JDBCConnectionProcessor.KEY.acceptConnections().contains(connection.getClass())) { |
||||||
|
ConnectionInfoBean bean = new ConnectionInfoBean(); |
||||||
|
bean.setConnectionData(objectMapper.writeValueAsString(convertToJDBCConnectionBean(connection, withPassword))); |
||||||
|
bean.setConnectionType(JDBCConnectionProcessor.CONNECTION_TYPE); |
||||||
|
bean.setConnectionType(JDBCConnectionProcessor.KEY.getConnectionType(connection)); |
||||||
|
bean.setConnectionName(name); |
||||||
|
bean.setCreator(connection.getCreator()); |
||||||
|
return bean; |
||||||
|
} else { |
||||||
|
return ConnectionProcessorFactory.createConnectionInfoBean(name, connection); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建数据连接Bean,默认携带密码 |
||||||
|
*/ |
||||||
|
public static ConnectionInfoBean createConnectionInfoBean(String name, Connection connection) throws Exception { |
||||||
|
return createConnectionInfoBean(name, connection, true); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建数据连接bean |
||||||
|
*/ |
||||||
|
public static ConnectionInfoBean createConnectionInfoBean(Connection connection) throws Exception { |
||||||
|
return createConnectionInfoBean(connection.getConnectionName(), connection, true); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* jdbc的特殊处理 |
||||||
|
*/ |
||||||
|
private static JDBCConnectionBean convertToJDBCConnectionBean(Connection connection, boolean withPassword) { |
||||||
|
JDBCDatabaseConnection jdbcConnection = (JDBCDatabaseConnection) connection; |
||||||
|
JDBCConnectionBean jdbcConnectionBean = new JDBCConnectionBean(); |
||||||
|
DBCPConnectionPoolAttr poolAttr = new DBCPConnectionPoolAttr(); |
||||||
|
try { |
||||||
|
poolAttr = (DBCPConnectionPoolAttr) jdbcConnection.getDbcpAttr().clone(); |
||||||
|
} catch (CloneNotSupportedException ignore) { |
||||||
|
} |
||||||
|
poolAttr.setValidationQuery(TransmissionTool.encrypt(poolAttr.getValidationQuery())); |
||||||
|
KerberosAuthentication kerberosAuthentication = null; |
||||||
|
if (jdbcConnection.getAuthentication().type() == AuthenticationType.KERBEROS) { |
||||||
|
//获取数据连接信息的时候,做一下兼容处理(兼容旧的kerberos形式)
|
||||||
|
KerberosUtils.compatibilityProcess(((KerberosAuthentication) jdbcConnection.getAuthentication())); |
||||||
|
kerberosAuthentication = ((KerberosAuthentication) jdbcConnection.getAuthentication()); |
||||||
|
} |
||||||
|
//因为设计器创建连接时database属性为空,所以这里直接取数据库保存的fetchSize值,默认值为-1
|
||||||
|
return jdbcConnectionBean |
||||||
|
.newCharsetName(jdbcConnection.getNewCharsetName()) |
||||||
|
.originalCharsetName(jdbcConnection.getOriginalCharsetName()) |
||||||
|
.database(jdbcConnection.getDatabase()) |
||||||
|
.user(jdbcConnection.getUser()) |
||||||
|
.driver(jdbcConnection.getDriver()) |
||||||
|
// 关键中的关键,由设计器发出的请求如果要携带密码,不能传明文,必须必须必须传加密后的密码
|
||||||
|
.password(withPassword ? TransmissionEncryptors.getInstance().encrypt(jdbcConnection.getPassword()) : DecisionServiceConstants.DEFAULT_PASSWORD) |
||||||
|
.schema(jdbcConnection.getSchema()) |
||||||
|
.url(jdbcConnection.getURL()) |
||||||
|
.creator(jdbcConnection.getCreator()) |
||||||
|
.source(jdbcConnection.getDriverSource()) |
||||||
|
.connectionPoolAttr(poolAttr.create()) |
||||||
|
.authType(kerberosAuthentication != null ? "kerberos" : StringUtils.EMPTY) |
||||||
|
.principal(kerberosAuthentication != null ? kerberosAuthentication.getPrincipal() : StringUtils.EMPTY) |
||||||
|
.keyPath(kerberosAuthentication != null ? kerberosAuthentication.getKeyPath() : StringUtils.EMPTY) |
||||||
|
.krb5Path(kerberosAuthentication != null ? KerberosUtils.getKrb5Path(kerberosAuthentication.getKeyPath(), kerberosAuthentication.getPrincipal()) : StringUtils.EMPTY) |
||||||
|
.useJaas(jdbcConnection.getAuthentication().type() == AuthenticationType.KERBEROS && ((KerberosAuthentication) jdbcConnection.getAuthentication()).getUseJaas()) |
||||||
|
.fetchSize(jdbcConnection.getFetchSize()).identity(connection.getIdentity()) |
||||||
|
.sshType(jdbcConnection.getSsh().getSshType().toString()) |
||||||
|
.sshIp(((BaseSsh) jdbcConnection.getSsh()).getIp()) |
||||||
|
.usingSsh(jdbcConnection.getSsh().isUsingSsh()) |
||||||
|
.sshUser(((BaseSsh) jdbcConnection.getSsh()).getUser()) |
||||||
|
.sshPort(((BaseSsh) jdbcConnection.getSsh()).getPort()) |
||||||
|
.redirectPort(jdbcConnection.getSsh().getRedirectPort()) |
||||||
|
.redirectIp((jdbcConnection.getSsh()).getRedirectIp()) |
||||||
|
.sshTimeOut(((BaseSsh) jdbcConnection.getSsh()).getTimeOut()) |
||||||
|
.sshSecret(withPassword ? ((BaseSsh) jdbcConnection.getSsh()).getSecret() : DecisionServiceConstants.DEFAULT_PASSWORD) |
||||||
|
.sshPrivateKeyPath(jdbcConnection.getSsh().getSshType() == SshType.KEY ? ((KeyVerifySsh) jdbcConnection.getSsh()).getPrivateKeyPath() : StringUtils.EMPTY) |
||||||
|
.usingSsl((jdbcConnection.getSsl()).isUsingSsl()) |
||||||
|
.sslType(jdbcConnection.getSsl().getSslType().toString()) |
||||||
|
.sslClientCertificate(((BaseSsl) jdbcConnection.getSsl()).getClientCertificate()) |
||||||
|
.sslClientPrivateKey(((BaseSsl) jdbcConnection.getSsl()).getClientPrivateKey()) |
||||||
|
.caCertificate(((BaseSsl) jdbcConnection.getSsl()).getCaCertificate()) |
||||||
|
.properties(jdbcConnection.getProperties()) |
||||||
|
.verifyCa(jdbcConnection.getSsl().getSslType() == SslType.NORMAL && ((NormalSsl) jdbcConnection.getSsl()).isVerifyCa()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue