@@ -3,6 +3,7 @@ package com.coder.gateway.views.steps
3
3
import com.coder.gateway.CoderGatewayBundle
4
4
import com.coder.gateway.icons.CoderIcons
5
5
import com.coder.gateway.models.CoderWorkspacesWizardModel
6
+ import com.coder.gateway.models.WorkspaceAgentModel
6
7
import com.coder.gateway.sdk.Arch
7
8
import com.coder.gateway.sdk.CoderRestClientService
8
9
import com.coder.gateway.sdk.OS
@@ -38,10 +39,13 @@ import com.jetbrains.gateway.ssh.HighLevelHostAccessor
38
39
import com.jetbrains.gateway.ssh.IdeStatus
39
40
import com.jetbrains.gateway.ssh.IdeWithStatus
40
41
import com.jetbrains.gateway.ssh.IntelliJPlatformProduct
42
+ import kotlinx.coroutines.CancellationException
41
43
import kotlinx.coroutines.CoroutineScope
42
44
import kotlinx.coroutines.Dispatchers
45
+ import kotlinx.coroutines.Job
43
46
import kotlinx.coroutines.async
44
47
import kotlinx.coroutines.cancel
48
+ import kotlinx.coroutines.cancelAndJoin
45
49
import kotlinx.coroutines.launch
46
50
import kotlinx.coroutines.withContext
47
51
import java.awt.Component
@@ -67,6 +71,8 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit
67
71
private lateinit var tfProject: JBTextField
68
72
private lateinit var terminalLink: LazyBrowserLink
69
73
74
+ private lateinit var ideResolvingJob: Job
75
+
70
76
override val component = panel {
71
77
indent {
72
78
row {
@@ -118,61 +124,73 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit
118
124
titleLabel.text = CoderGatewayBundle .message(" gateway.connector.view.coder.remoteproject.choose.text" , selectedWorkspace.name)
119
125
terminalLink.url = " ${coderClient.coderURL} /@${coderClient.me.username} /${selectedWorkspace.name} /terminal"
120
126
121
- cs.launch {
122
- logger.info(" Retrieving available IDE's for ${selectedWorkspace.name} workspace..." )
123
- val hostAccessor = HighLevelHostAccessor .create(
124
- RemoteCredentialsHolder ().apply {
125
- setHost(" coder.${selectedWorkspace.name} " )
126
- userName = " coder"
127
- authType = AuthType .OPEN_SSH
128
- },
129
- true
130
- )
131
- val workspaceOS = if (selectedWorkspace.agentOS != null && selectedWorkspace.agentArch != null ) toDeployedOS(selectedWorkspace.agentOS, selectedWorkspace.agentArch) else withContext(Dispatchers .IO ) {
132
- try {
133
- hostAccessor.guessOs()
134
- } catch (e: Exception ) {
135
- logger.error(" Could not resolve any IDE for workspace ${selectedWorkspace.name} . Reason: $e " )
136
- null
137
- }
138
- }
139
- if (workspaceOS == null ) {
140
- disableNextAction()
141
- cbIDE.renderer = object : ColoredListCellRenderer <IdeWithStatus >() {
142
- override fun customizeCellRenderer (list : JList <out IdeWithStatus >, value : IdeWithStatus ? , index : Int , isSelected : Boolean , cellHasFocus : Boolean ) {
143
- background = UIUtil .getListBackground(isSelected, cellHasFocus)
144
- icon = UIUtil .getBalloonErrorIcon()
145
- append(CoderGatewayBundle .message(" gateway.connector.view.coder.remoteproject.ide.error.text" , selectedWorkspace.name))
127
+ ideResolvingJob = cs.launch {
128
+ try {
129
+ retrieveIDES(selectedWorkspace)
130
+ } catch (e: Exception ) {
131
+ when (e) {
132
+ is InterruptedException -> Unit
133
+ is CancellationException -> Unit
134
+ else -> {
135
+ logger.error(" Could not resolve any IDE for workspace ${selectedWorkspace.name} . Reason: $e " )
136
+ withContext(Dispatchers .Main ) {
137
+ disableNextAction()
138
+ cbIDE.renderer = object : ColoredListCellRenderer <IdeWithStatus >() {
139
+ override fun customizeCellRenderer (list : JList <out IdeWithStatus >, value : IdeWithStatus ? , index : Int , isSelected : Boolean , cellHasFocus : Boolean ) {
140
+ background = UIUtil .getListBackground(isSelected, cellHasFocus)
141
+ icon = UIUtil .getBalloonErrorIcon()
142
+ append(CoderGatewayBundle .message(" gateway.connector.view.coder.remoteproject.ide.error.text" , selectedWorkspace.name))
143
+ }
144
+ }
145
+ }
146
146
}
147
147
}
148
- } else {
149
- logger.info(" Resolved OS and Arch for ${selectedWorkspace.name} is: $workspaceOS " )
150
- val installedIdesJob = async(Dispatchers .IO ) {
151
- hostAccessor.getInstalledIDEs().map { ide -> IdeWithStatus (ide.product, ide.buildNumber, IdeStatus .ALREADY_INSTALLED , null , ide.pathToIde, ide.presentableVersion, ide.remoteDevType) }
152
- }
153
- val idesWithStatusJob = async(Dispatchers .IO ) {
154
- IntelliJPlatformProduct .values()
155
- .filter { it.showInGateway }
156
- .flatMap { CachingProductsJsonWrapper .getInstance().getAvailableIdes(it, workspaceOS) }
157
- .map { ide -> IdeWithStatus (ide.product, ide.buildNumber, IdeStatus .DOWNLOAD , ide.download, null , ide.presentableVersion, ide.remoteDevType) }
158
- }
148
+ }
149
+ }
150
+ }
159
151
160
- val installedIdes = installedIdesJob.await()
161
- val idesWithStatus = idesWithStatusJob.await()
162
- if (installedIdes.isEmpty()) {
163
- logger.info(" No IDE is installed in workspace ${selectedWorkspace.name} " )
164
- } else {
165
- ideComboBoxModel.addAll(installedIdes)
166
- cbIDE.selectedIndex = 0
167
- }
152
+ private suspend fun retrieveIDES (selectedWorkspace : WorkspaceAgentModel ) {
153
+ logger.info(" Retrieving available IDE's for ${selectedWorkspace.name} workspace..." )
154
+ val hostAccessor = HighLevelHostAccessor .create(
155
+ RemoteCredentialsHolder ().apply {
156
+ setHost(" coder.${selectedWorkspace.name} " )
157
+ userName = " coder"
158
+ authType = AuthType .OPEN_SSH
159
+ },
160
+ true
161
+ )
162
+ val workspaceOS = if (selectedWorkspace.agentOS != null && selectedWorkspace.agentArch != null ) toDeployedOS(selectedWorkspace.agentOS, selectedWorkspace.agentArch) else withContext(Dispatchers .IO ) {
163
+ hostAccessor.guessOs()
164
+ }
168
165
169
- if (idesWithStatus.isEmpty()) {
170
- logger.warn(" Could not resolve any IDE for workspace ${selectedWorkspace.name} , probably $workspaceOS is not supported by Gateway" )
171
- } else {
166
+ logger.info(" Resolved OS and Arch for ${selectedWorkspace.name} is: $workspaceOS " )
167
+ val installedIdesJob = cs.async(Dispatchers .IO ) {
168
+ hostAccessor.getInstalledIDEs().map { ide -> IdeWithStatus (ide.product, ide.buildNumber, IdeStatus .ALREADY_INSTALLED , null , ide.pathToIde, ide.presentableVersion, ide.remoteDevType) }
169
+ }
170
+ val idesWithStatusJob = cs.async(Dispatchers .IO ) {
171
+ IntelliJPlatformProduct .values()
172
+ .filter { it.showInGateway }
173
+ .flatMap { CachingProductsJsonWrapper .getInstance().getAvailableIdes(it, workspaceOS) }
174
+ .map { ide -> IdeWithStatus (ide.product, ide.buildNumber, IdeStatus .DOWNLOAD , ide.download, null , ide.presentableVersion, ide.remoteDevType) }
175
+ }
172
176
173
- ideComboBoxModel.addAll(idesWithStatus)
174
- cbIDE.selectedIndex = 0
175
- }
177
+ val installedIdes = installedIdesJob.await()
178
+ val idesWithStatus = idesWithStatusJob.await()
179
+ if (installedIdes.isEmpty()) {
180
+ logger.info(" No IDE is installed in workspace ${selectedWorkspace.name} " )
181
+ } else {
182
+ withContext(Dispatchers .Main ) {
183
+ ideComboBoxModel.addAll(installedIdes)
184
+ cbIDE.selectedIndex = 0
185
+ }
186
+ }
187
+
188
+ if (idesWithStatus.isEmpty()) {
189
+ logger.warn(" Could not resolve any IDE for workspace ${selectedWorkspace.name} , probably $workspaceOS is not supported by Gateway" )
190
+ } else {
191
+ withContext(Dispatchers .Main ) {
192
+ ideComboBoxModel.addAll(idesWithStatus)
193
+ cbIDE.selectedIndex = 0
176
194
}
177
195
}
178
196
}
@@ -213,6 +231,13 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit
213
231
return true
214
232
}
215
233
234
+ override fun onPrevious () {
235
+ super .onPrevious()
236
+ cs.launch {
237
+ ideResolvingJob.cancelAndJoin()
238
+ }
239
+ }
240
+
216
241
override fun dispose () {
217
242
cs.cancel()
218
243
}
0 commit comments