@@ -12,6 +12,7 @@ import com.intellij.ide.BrowserUtil
12
12
import com.intellij.openapi.components.service
13
13
import com.intellij.openapi.diagnostic.thisLogger
14
14
import com.intellij.openapi.progress.ProgressManager
15
+ import com.intellij.openapi.ui.Messages
15
16
import com.intellij.remote.RemoteCredentialsHolder
16
17
import com.intellij.ssh.AskAboutHostKey
17
18
import com.intellij.ssh.OpenSshLikeHostKeyVerifier
@@ -31,6 +32,7 @@ import com.jetbrains.gateway.ssh.ClientOverSshTunnelConnector
31
32
import com.jetbrains.gateway.ssh.SshHostTunnelConnector
32
33
import com.jetbrains.gateway.thinClientLink.ThinClientHandle
33
34
import com.jetbrains.rd.util.URI
35
+ import com.jetbrains.rd.util.concurrentMapOf
34
36
import com.jetbrains.rd.util.lifetime.Lifetime
35
37
import io.gitpod.gitpodprotocol.api.entities.WorkspaceInstance
36
38
import io.gitpod.jetbrains.icons.GitpodIcons
@@ -49,7 +51,7 @@ import kotlin.coroutines.coroutineContext
49
51
50
52
@Suppress(" UnstableApiUsage" , " OPT_IN_USAGE" )
51
53
class GitpodConnectionProvider : GatewayConnectionProvider {
52
-
54
+ private val activeConnections = concurrentMapOf< String , Boolean >()
53
55
private val gitpod = service<GitpodConnectionService >()
54
56
55
57
private val httpClient = HttpClient .newBuilder()
@@ -59,6 +61,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
59
61
private val jacksonMapper = jacksonObjectMapper()
60
62
.configure(DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false )
61
63
64
+
62
65
override suspend fun connect (
63
66
parameters : Map <String , String >,
64
67
requestor : ConnectionRequestor
@@ -74,6 +77,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
74
77
parameters[" workspaceId" ]!! ,
75
78
parameters[" backendPort" ]
76
79
)
80
+
77
81
val client = gitpod.obtainClient(connectParams.gitpodHost)
78
82
val connectionLifetime = Lifetime .Eternal .createNested()
79
83
val updates = client.listenToWorkspace(connectionLifetime, connectParams.workspaceId)
@@ -144,6 +148,22 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
144
148
connectionPanel.repaint()
145
149
}
146
150
151
+ val connectionKeyId = " ${connectParams.gitpodHost} -${connectParams.workspaceId} -${connectParams.backendPort} "
152
+
153
+ if (activeConnections.containsKey(connectionKeyId)) {
154
+ val message = " You are trying to connect to a workspace that has a session already open"
155
+ val title = " Oops"
156
+ val okButton = Messages .getOkButton()
157
+ val options = arrayOf(okButton)
158
+ val defaultIndex = 0
159
+ val icon = Messages .getWarningIcon()
160
+ Messages .showDialog(message, title, options, defaultIndex, icon)
161
+
162
+ val errMessage = " A connection to the same workspace already exists: $connectionKeyId "
163
+ thisLogger().warn(errMessage)
164
+ throw IllegalArgumentException (errMessage)
165
+ }
166
+
147
167
GlobalScope .launch {
148
168
var thinClient: ThinClientHandle ? = null
149
169
var thinClientJob: Job ? = null
@@ -230,6 +250,12 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
230
250
setErrorMessage(" failed to fetch JetBrains Gateway Join Link." )
231
251
return @launch
232
252
}
253
+
254
+ // TODO: is this the right place?
255
+ activeConnections[connectionKeyId] = true
256
+
257
+ thisLogger().warn(" Storing connection for $connectionKeyId " )
258
+
233
259
val connector = ClientOverSshTunnelConnector (
234
260
connectionLifetime,
235
261
SshHostTunnelConnector (credentials),
@@ -239,6 +265,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
239
265
clientHandle.clientClosed.advise(connectionLifetime) {
240
266
application.invokeLater {
241
267
connectionLifetime.terminate()
268
+ // todo: remove this connection from activeConnections
242
269
}
243
270
}
244
271
clientHandle.onClientPresenceChanged.advise(connectionLifetime) {
0 commit comments