@ -7,20 +7,33 @@ import com.fr.design.EnvChangeEntrance;
import com.fr.design.dialog.FineJOptionPane ;
import com.fr.design.env.DesignerWorkspaceInfo ;
import com.fr.design.env.DesignerWorkspaceInfoContext ;
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.mainframe.loghandler.DesignerLogger ;
import com.fr.design.mainframe.share.ui.base.MouseClickListener ;
import com.fr.design.mainframe.toast.DesignerToastMsgUtil ;
import com.fr.design.mainframe.toast.ToastMsgDialog ;
import com.fr.design.ui.util.UIUtil ;
import com.fr.design.utils.BrowseUtils ;
import com.fr.event.EventDispatcher ;
import com.fr.general.CloudCenter ;
import com.fr.general.ComparatorUtils ;
import com.fr.log.FineLoggerFactory ;
import com.fr.report.RemoteDesignConstants ;
import com.fr.serialization.SerializerHelper ;
import com.fr.stable.ArrayUtils ;
import com.fr.stable.StableUtils ;
import com.fr.stable.StringUtils ;
import com.fr.third.apache.log4j.spi.LoggingEvent ;
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.conn.ssl.NoopHostnameVerifier ;
import com.fr.third.org.apache.http.conn.ssl.TrustSelfSignedStrategy ;
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient ;
import com.fr.third.org.apache.http.impl.client.HttpClients ;
import com.fr.third.org.apache.http.ssl.SSLContexts ;
import com.fr.web.WebSocketConfig ;
import com.fr.web.socketio.WebSocketProtocol ;
@ -29,22 +42,27 @@ import com.fr.workspace.Workspace;
import com.fr.workspace.base.WorkspaceConstants ;
import com.fr.workspace.connect.WorkspaceConnection ;
import com.fr.workspace.connect.WorkspaceConnectionInfo ;
import com.fr.workspace.server.socket.SocketInfoOperator ;
import io.socket.client.IO ;
import io.socket.client.Socket ;
import io.socket.emitter.Emitter ;
import javax.net.ssl.SSLContext ;
import javax.swing.BorderFactory ;
import javax.swing.JOptionPane ;
import javax.swing.JPanel ;
import javax.swing.UIManager ;
import java.awt.BorderLayout ;
import java.awt.Color ;
import java.awt.Cursor ;
import java.awt.event.MouseEvent ;
import java.io.File ;
import java.io.FileInputStream ;
import java.security.KeyStore ;
import java.util.Arrays ;
import javax.net.ssl.SSLContext ;
import javax.swing.* ;
import java.io.IOException ;
import java.net.URI ;
import java.net.URL ;
import java.security.KeyStore ;
import java.util.Arrays ;
import java.util.Timer ;
import java.util.TimerTask ;
public class DesignerSocketIO {
@ -54,18 +72,21 @@ public class DesignerSocketIO {
Disconnecting
}
private static final String WEBSOCKET_HELP_DOC = CloudCenter . getInstance ( ) . acquireUrlByKind ( "websocketConnect" , "https://help.fanruan.com/finereport/doc-view-2512.html" ) ;
private static final String HTTPS = "https" ;
private static final String HTTP = "http" ;
private static Socket socket = null ;
private static Status status = Status . Disconnected ;
private static Timer disConnectHintTimer = null ;
private static long disConnectHintTimerDelay = 3000 ;
private static final int TIMEOUT = 5000 ;
//维护一个当前工作环境的uri列表
private static String [ ] uri ;
//维护一个关于uri列表的计数器
private static int count ;
// 当前webSocket选择的协议
private static String currentProtocol ;
private static ToastMsgDialog dialog = null ;
public static void close ( ) {
@ -115,7 +136,6 @@ public class DesignerSocketIO {
private static IO . Options createOptions ( ) {
IO . Options options = new IO . Options ( ) ;
options . path = WebSocketConfig . getInstance ( ) . getSocketContext ( ) ;
try {
if ( ComparatorUtils . equals ( currentProtocol , HTTPS ) ) {
options . sslContext = getSSLContext ( ) ;
@ -186,6 +206,7 @@ public class DesignerSocketIO {
private static final Emitter . Listener failRetry = new Emitter . Listener ( ) {
@Override
public void call ( Object . . . args ) {
showSocketDisconnectToast ( ) ;
printLog ( args , PrintEventLogImpl . WARN , "failed args: {}" ) ;
status = Status . Disconnecting ;
socket . close ( ) ;
@ -224,41 +245,38 @@ public class DesignerSocketIO {
@Override
public void call ( Object . . . objects ) {
FineLoggerFactory . getLogger ( ) . info ( "start disConnectHintTimer" ) ;
disConnectHintTimer = new Timer ( ) ;
disConnectHintTimer . schedule ( new TimerTask ( ) {
@Override
public void run ( ) {
try {
/ *
* todo 远程心跳断开不一定 socket 断开 和远程紧密相关的业务都绑定在心跳上 , 切换成心跳断开之后进行提醒 ,
* socket 只用推日志和通知配置变更
* /
printLog ( objects , PrintEventLogImpl . ERROR , "disConnected args: {}" ) ;
if ( status ! = Status . Disconnecting ) {
showConnectionLostDialog ( ) ;
}
status = Status . Disconnected ;
} finally {
disConnectHintTimer . cancel ( ) ;
disConnectHintTimer = null ;
}
}
} , disConnectHintTimerDelay ) ;
/ *
* todo 远程心跳断开不一定 socket 断开 和远程紧密相关的业务都绑定在心跳上 , 切换成心跳断开之后进行提醒 ,
* socket 只用推日志和通知配置变更
* /
printLog ( objects , PrintEventLogImpl . ERROR , "disConnected args: {}" ) ;
if ( status ! = Status . Disconnecting ) {
dealWithSocketDisconnect ( ) ;
}
status = Status . Disconnected ;
}
} ;
private static void showConnectionLostDialog ( ) {
private static void dealWithSocketDisconnect ( ) {
if ( checkRPCConnect ( ) ) {
showSocketDisconnectToast ( ) ;
} else {
showRPCDisconnectDialog ( ) ;
}
}
private static void showSocketDisconnectToast ( ) {
try {
UIUtil . invokeLaterIfNeeded ( new Runnable ( ) {
@Override
public void run ( ) {
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 ( ) ;
if ( dialog = = null ) {
dialog = DesignerToastMsgUtil . createPromptDialog ( createDialogContent ( ) ) ;
}
if ( ! dialog . isShow ( ) ) {
dialog . setVisible ( true ) ;
}
}
} ) ;
} catch ( Exception e ) {
@ -266,6 +284,57 @@ public class DesignerSocketIO {
}
}
private static JPanel createDialogContent ( ) {
JPanel jPanel = FRGUIPaneFactory . createBorderLayout_S_Pane ( ) ;
jPanel . add ( new UILabel ( Toolkit . i18nText ( "Fine-Design_WebSocket_Lost_Tip" ) ) , BorderLayout . WEST ) ;
UILabel hyperLinkLabel = new UILabel ( Toolkit . i18nText ( "Fine-Design_WebSocket_Lost_Tip_HyperLink_Text" ) ) ;
hyperLinkLabel . addMouseListener ( new MouseClickListener ( ) {
@Override
public void mouseClicked ( MouseEvent e ) {
BrowseUtils . browser ( WEBSOCKET_HELP_DOC ) ;
}
} ) ;
hyperLinkLabel . setBorder ( BorderFactory . createEmptyBorder ( 0 , 3 , 0 , 0 ) ) ;
hyperLinkLabel . setForeground ( Color . BLUE ) ;
hyperLinkLabel . setCursor ( Cursor . getPredefinedCursor ( Cursor . HAND_CURSOR ) ) ;
jPanel . add ( hyperLinkLabel , BorderLayout . CENTER ) ;
return jPanel ;
}
private static void showRPCDisconnectDialog ( ) {
UIUtil . invokeLaterIfNeeded ( new Runnable ( ) {
@Override
public void run ( ) {
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 ( ) ;
}
} ) ;
}
private static boolean checkRPCConnect ( ) {
CloseableHttpClient httpclient = HttpClients . createDefault ( ) ;
WorkspaceConnectionInfo info = getConnectionInfo ( ) ;
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 ) ;
} catch ( Exception e ) {
FineLoggerFactory . getLogger ( ) . error ( e , e . getMessage ( ) ) ;
return false ;
}
return true ;
}
//配置变更监听器
private static final Emitter . Listener modifyConfig = new Emitter . Listener ( ) {
@Override