Skip to content

Commit

Permalink
GHI-153: Intermediate implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
dnlsv committed Oct 9, 2024
1 parent a1a6822 commit 56b0157
Show file tree
Hide file tree
Showing 15 changed files with 756 additions and 53 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ val junitVersion = "5.11.1"
val mockkVersion = "1.13.12"
val ibmMqVersion = "9.4.0.0"
val jGraphTVersion = "1.5.2"
val zoweKotlinSdkVersion = "0.5.0"
val zoweKotlinSdkVersion = "0.5.0-rc.13"
val javaKeytarVersion = "1.0.0"

plugins {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2024 IBA Group.
*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBA Group
* Zowe Community
*/

package org.zowe.explorer.apiml.config

import org.zowe.explorer.apiml.config.ui.ApiMLConnectionDialogState
import org.zowe.explorer.config.connect.ConnectionConfig
import org.zowe.explorer.config.connect.CredentialService
import org.zowe.explorer.dataops.exceptions.CredentialsNotFoundForConnectionException
import org.zowe.kotlinsdk.annotations.ZVersion

class ApiMLConnectionConfig : ConnectionConfig {

// var basePath: String = ""

var gatewayPath: String = ""

constructor()

constructor(
uuid: String,
name: String,
url: String,
isAllowSelfSigned: Boolean,
zVersion: ZVersion,
zoweConfigPath: String? = null,
owner: String = "",
// basePath: String = "",
gatewayPath: String = "",
) : super(uuid, name, url, isAllowSelfSigned, zVersion, zoweConfigPath, owner) {
// this.basePath = basePath
this.gatewayPath = gatewayPath
}

fun toDialogState(): ApiMLConnectionDialogState {
var username = ""
var password = ""
var owner = ""
try {
username = CredentialService.getUsername(this)
password = CredentialService.getPassword(this)
owner = CredentialService.getOwner(this)
} catch (_: CredentialsNotFoundForConnectionException) {
}
val pair = splitUrl(this.url)
val baseUrl = pair.first
val basePath = pair.second
return ApiMLConnectionDialogState(
connectionUuid = this.uuid,
connectionName = this.name,
connectionUrl = baseUrl,
username = username,
password = password,
owner = owner,
isAllowSelfSigned = this.isAllowSelfSigned,
zVersion = this.zVersion,
zoweConfigPath = this.zoweConfigPath,
basePath = basePath,
gatewayPath = this.gatewayPath
)
}

private fun splitUrl(url: String): Pair<String, String> {
val regex = Regex("((http|https)://[^:/]+:\\d+)(/.*)")
val matchResult = regex.find(url)

return matchResult?.let {
val baseUrl = it.groups[1]?.value ?: ""
val basePath = it.groups[3]?.value ?: ""
Pair(baseUrl, basePath)
} ?: Pair("", "")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2024 IBA Group.
*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBA Group
* Zowe Community
*/

package org.zowe.explorer.apiml.config

import com.intellij.openapi.options.BoundSearchableConfigurable
import org.zowe.explorer.apiml.config.ui.ApiMLConnectionConfigurable
import org.zowe.explorer.config.ConfigDeclaration
import org.zowe.explorer.config.ConfigDeclarationFactory
import org.zowe.explorer.utils.crudable.Crudable

class ApiMLConnectionInfoConfigDeclarationFactory: ConfigDeclarationFactory {
override fun buildConfigDeclaration(crudable: Crudable): ConfigDeclaration<*> {
return ApiMLConnectionInfoConfigDeclaration(crudable)
}
}

class ApiMLConnectionInfoConfigDeclaration(
crudable: Crudable
) : ConfigDeclaration<ApiMLConnectionConfig>(crudable) {

override val clazz = ApiMLConnectionConfig::class.java

override val useCredentials = true

override val configPriority = 5.0

override fun getDecider(): ConfigDecider<ApiMLConnectionConfig> {
return object: ConfigDecider<ApiMLConnectionConfig>() {
override fun canAdd(row: ApiMLConnectionConfig): Boolean {
return crudable.find(clazz) { it.name == row.name }.count() == 0L
}

override fun canUpdate(currentRow: ApiMLConnectionConfig, updatingRow: ApiMLConnectionConfig): Boolean {
return canAdd(updatingRow) || currentRow.name == updatingRow.name
}
}
}

override fun getConfigurable(): BoundSearchableConfigurable {
return ApiMLConnectionConfigurable()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
* Copyright (c) 2024 IBA Group.
*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBA Group
* Zowe Community
*/

package org.zowe.explorer.apiml.config.ui

import com.intellij.openapi.options.BoundSearchableConfigurable
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogPanel
import com.intellij.ui.dsl.builder.panel
import org.zowe.explorer.api.api
import org.zowe.explorer.apiml.config.ApiMLConnectionConfig
import org.zowe.explorer.apiml.config.ui.table.ApiMLConnectionTableModel
import org.zowe.explorer.common.ui.*
import org.zowe.explorer.config.ConfigSandbox
import org.zowe.explorer.config.SandboxListener
import org.zowe.explorer.config.connect.*
import org.zowe.explorer.dataops.DataOpsManager
import org.zowe.explorer.dataops.operations.InfoOperation
import org.zowe.explorer.dataops.operations.ZOSInfoOperation
import org.zowe.explorer.utils.isThe
import org.zowe.explorer.utils.runTask
import org.zowe.explorer.utils.subscribe
import org.zowe.kotlinsdk.ApiMLGetawayApi
import org.zowe.kotlinsdk.LoginRequest
import org.zowe.kotlinsdk.annotations.ZVersion

class ApiMLConnectionConfigurable : BoundSearchableConfigurable("API ML Connections", "mainframe") {

private lateinit var tableModel: ApiMLConnectionTableModel
private lateinit var table: ValidatingTableView<ApiMLConnectionDialogState>
private lateinit var panel: DialogPanel

override fun createPanel(): DialogPanel {
tableModel = ApiMLConnectionTableModel(ConfigSandbox.getService().crudable)
table = ValidatingTableView(tableModel, disposable!!)
.apply {
rowHeight = DEFAULT_ROW_HEIGHT
// addMouseListener(registerMouseListener())
}

addSandboxListener()

return panel {
group("API ML Connections", false) {
row {
tableWithToolbar(table) {
configureDecorator {
setAddAction {
addSession()
}
setEditAction {
editSession()
}
}
}
}
.resizableRow()
}
.resizableRow()
}.also {
panel = it
}
}

private fun addSandboxListener() {
subscribe(
topic = SandboxListener.TOPIC,
handler = object : SandboxListener {
override fun <E : Any> update(clazz: Class<out E>) {
}

override fun <E : Any> reload(clazz: Class<out E>) {
if (clazz.isThe<ConnectionConfig>()) {
tableModel.reinitialize()
}
}

},
disposable = disposable!!
)
}

override fun apply() {
val wasModified = isModified
ConfigSandbox.getService().apply(Credentials::class.java)
ConfigSandbox.getService().apply(ApiMLConnectionConfig::class.java)
if (wasModified) {
panel.updateUI()
}
}

override fun reset() {
val wasModified = isModified
ConfigSandbox.getService().rollback(Credentials::class.java)
ConfigSandbox.getService().rollback(ApiMLConnectionConfig::class.java)
if (wasModified) {
panel.updateUI()
}
}

override fun cancel() {
reset()
}

override fun isModified(): Boolean {
return ConfigSandbox.getService().isModified(Credentials::class.java)
|| ConfigSandbox.getService().isModified(ApiMLConnectionConfig::class.java)
}

private fun addSession() {
val state = ApiMLConnectionDialogState().initEmptyUuids(ConfigSandbox.getService().crudable)
showAndTestConnection(state, null)?.let { tableModel.addRow(it) }
}

private fun editSession() {
table.selectedObject?.clone()?.let { state ->
state.mode = DialogMode.UPDATE
val dialog = ApiMLConnectionDialog(ConfigSandbox.getService().crudable, state)
if (dialog.showAndGet()) {
val idx = table.selectedRow
tableModel[idx] = state
}
}
}

private fun showAndTestConnection(initialState: ApiMLConnectionDialogState, project: Project? = null): ApiMLConnectionDialogState? {
val dialog = ApiMLConnectionDialog(ConfigSandbox.getService().crudable, initialState)
return showUntilDone(
initialState = initialState,
factory = { dialog },
test = { state ->
val apiMLGatewayApiUrl = "${state.connectionUrl}$DEFAULT_GATEWAY_PATH/"
val response = api<ApiMLGetawayApi>(url = apiMLGatewayApiUrl, true)
.login(body = LoginRequest(state.username, state.password))
.execute()
val cookies = response.headers().values("Set-Cookie")
val tokenVariableName = "apimlAuthenticationToken"
val apimlAuthenticationToken = cookies
.first { it.contains(tokenVariableName) }
.substringAfter("$tokenVariableName=")
.substringBefore(";")
state.initEmptyUuids(ConfigSandbox.getService().crudable)
val connectionConfig = state.connectionConfig
CredentialService.getService().setCredentials(
connectionConfigUuid = state.connectionUuid,
username = state.username,
password = state.password,
token = apimlAuthenticationToken
)
val throwable = runTask(title = "Testing Connection to ${connectionConfig.url}", project = project) {
return@runTask try {
runCatching {
DataOpsManager.getService().performOperation(InfoOperation(connectionConfig), it)
}.onSuccess {
val systemInfo = DataOpsManager.getService().performOperation(ZOSInfoOperation(connectionConfig))
state.zVersion = when (systemInfo.zosVersion) {
"04.25.00" -> ZVersion.ZOS_2_2
"04.26.00" -> ZVersion.ZOS_2_3
"04.27.00" -> ZVersion.ZOS_2_4
"04.28.00" -> ZVersion.ZOS_2_5
else -> ZVersion.ZOS_2_1
}
connectionConfig.zVersion = state.zVersion
}.onFailure {
throw it
}
null
} catch (t: Throwable) {
t
}
}
if (throwable == null) {
runTask(title = "Retrieving user information", project = project) {
// Could be empty if TSO request fails
state.owner = whoAmI(connectionConfig) ?: ""
}
}
true
}
)
}

}
Loading

0 comments on commit 56b0157

Please sign in to comment.