Skip to content

Commit

Permalink
IJMP-1923 Fixed IDE error in case of invalid zowe.config
Browse files Browse the repository at this point in the history
Signed-off-by: Katsiaryna Tsytsenia <[email protected]>
  • Loading branch information
Katsiaryna Tsytsenia authored and Katsiaryna Tsytsenia committed Nov 8, 2024
1 parent d466545 commit d742a64
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

package org.zowe.explorer.config.connect.ui.zosmf

import com.google.gson.JsonSyntaxException
import com.intellij.ide.DataManager
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.options.BoundSearchableConfigurable
Expand All @@ -34,6 +37,7 @@ import org.zowe.explorer.config.connect.Credentials
import org.zowe.explorer.config.ws.FilesWorkingSetConfig
import org.zowe.explorer.config.ws.JesWorkingSetConfig
import org.zowe.explorer.config.ws.WorkingSetConfig
import org.zowe.explorer.telemetry.NotificationsService
import org.zowe.explorer.utils.crudable.getAll
import org.zowe.explorer.utils.isThe
import org.zowe.explorer.utils.runWriteActionInEdtAndWait
Expand Down Expand Up @@ -109,7 +113,16 @@ class ZOSMFConnectionConfigurable : BoundSearchableConfigurable("z/OSMF Connecti
return
}

val zoweConfig = parseConfigJson(configFile.inputStream)
val zoweConfig = try {
parseConfigJson(configFile.inputStream)
} catch (e: JsonSyntaxException) {
NotificationsService.errorNotification(
e,
project = DataManager.getInstance().getDataContext(panel).getData(PlatformDataKeys.PROJECT),
custTitle = "Error with Zowe config file"
)
return
}
zoweConfig.extractSecureProperties(configFile.path.split("/").toTypedArray())
kotlin.runCatching {
zoweConfig.updateFromState(state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package org.zowe.explorer.zowe.actions

import com.google.gson.JsonSyntaxException
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
Expand Down Expand Up @@ -84,12 +85,17 @@ class UpdateZoweConfigAction : DumbAwareAction() {
zoweConfigService.localZoweConfig
else
zoweConfigService.globalZoweConfig
if (type == ZoweConfigType.LOCAL) {
zoweConfigService.localZoweConfig = parseConfigJson(editor.document.text)
zoweConfigService.localZoweConfig?.extractSecureProperties(vFile.path.split("/").toTypedArray())
} else {
zoweConfigService.globalZoweConfig = parseConfigJson(editor.document.text)
zoweConfigService.globalZoweConfig?.extractSecureProperties(vFile.path.split("/").toTypedArray())
try {
if (type == ZoweConfigType.LOCAL) {
zoweConfigService.localZoweConfig = parseConfigJson(editor.document.text)
zoweConfigService.localZoweConfig?.extractSecureProperties(vFile.path.split("/").toTypedArray())
} else {
zoweConfigService.globalZoweConfig = parseConfigJson(editor.document.text)
zoweConfigService.globalZoweConfig?.extractSecureProperties(vFile.path.split("/").toTypedArray())
}
} catch (ex: JsonSyntaxException) {
e.presentation.isEnabledAndVisible = false
return
}
val zoweState = zoweConfigService.getZoweConfigState(false, type = type)
e.presentation.isEnabledAndVisible =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@

package org.zowe.explorer.zowe.service

import com.intellij.notification.Notification
import com.intellij.notification.NotificationGroupManager
import com.intellij.notification.NotificationType
import com.intellij.notification.Notifications
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.application.runWriteAction
Expand All @@ -38,6 +36,7 @@ import org.zowe.explorer.dataops.DataOpsManager
import org.zowe.explorer.dataops.operations.InfoOperation
import org.zowe.explorer.dataops.operations.ZOSInfoOperation
import org.zowe.explorer.explorer.EXPLORER_NOTIFICATION_GROUP_ID
import org.zowe.explorer.telemetry.NotificationsService
import org.zowe.explorer.utils.crudable.find
import org.zowe.explorer.utils.crudable.getAll
import org.zowe.explorer.utils.runTask
Expand All @@ -64,9 +63,6 @@ import java.util.regex.Pattern
import java.util.stream.Collectors
import kotlin.collections.set


const val ZOWE_CONFIG_NOTIFICATION_GROUP_ID = "org.zowe.explorerzowe.service.ZoweConfigNotificationGroupId"

const val ZOWE_PROJECT_PREFIX = "zowe-"

/**
Expand Down Expand Up @@ -123,22 +119,6 @@ class ZoweConfigServiceImpl(override val myProject: Project) : ZoweConfigService

override var globalZoweConfig: ZoweConfig? = null

/**
* Displays an error notification if an error was received.
* @param t thrown error.
* @param title error text.
*/
private fun notifyError(t: Throwable, title: String? = null) {
Notifications.Bus.notify(
Notification(
ZOWE_CONFIG_NOTIFICATION_GROUP_ID,
title ?: "Error with Zowe config file",
t.message ?: t.toString(),
NotificationType.ERROR
)
)
}

/**
* Checks project contains zowe.config.json. If zowe config presented
* it will parse it and save to object model inside zoweConfig field.
Expand All @@ -162,7 +142,8 @@ class ZoweConfigServiceImpl(override val myProject: Project) : ZoweConfigService
}
}
} catch (e: Exception) {
throw Exception("Cannot parse $type Zowe config file")
NotificationsService.errorNotification(e, project = myProject, custTitle="Error with Zowe config file")
return null
}
}

Expand Down Expand Up @@ -306,7 +287,7 @@ class ZoweConfigServiceImpl(override val myProject: Project) : ZoweConfigService
}

} catch (e: Exception) {
notifyError(e)
NotificationsService.errorNotification(e, project = myProject, custTitle="Error with Zowe config file")
}
}

Expand Down Expand Up @@ -384,7 +365,7 @@ class ZoweConfigServiceImpl(override val myProject: Project) : ZoweConfigService
}

} catch (e: Exception) {
notifyError(e)
NotificationsService.errorNotification(e, project = myProject, custTitle="Error with Zowe config file")
}
}

Expand Down Expand Up @@ -490,11 +471,7 @@ class ZoweConfigServiceImpl(override val myProject: Project) : ZoweConfigService
*/
override fun getZoweConfigState(scanProject: Boolean, type: ZoweConfigType): ZoweConfigState {
if (scanProject) {
try {
scanForZoweConfig(type)
} catch (e: Exception) {
notifyError(e)
}
}
val zoweConfig = if (type == ZoweConfigType.LOCAL)
localZoweConfig ?: return ZoweConfigState.NOT_EXISTS
Expand Down
17 changes: 17 additions & 0 deletions src/test/kotlin/org/zowe/explorer/config/ZoweConfigTestSpec.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ import org.zowe.explorer.dataops.operations.InfoOperation
import org.zowe.explorer.dataops.operations.ZOSInfoOperation
import org.zowe.explorer.explorer.Explorer
import org.zowe.explorer.explorer.WorkingSet
import org.zowe.explorer.telemetry.NotificationsService
import org.zowe.explorer.testutils.WithApplicationShouldSpec
import org.zowe.explorer.testutils.testServiceImpl.TestDataOpsManagerImpl
import org.zowe.explorer.testutils.testServiceImpl.TestNotificationsServiceImpl
import org.zowe.explorer.utils.crudable.*
import org.zowe.explorer.utils.runIfTrue
import org.zowe.explorer.utils.validateForBlank
Expand Down Expand Up @@ -128,6 +130,21 @@ class ZoweConfigTestSpec : WithApplicationShouldSpec({
Optional.of(ConnectionConfig())
}

val notificationsService = NotificationsService.getService() as TestNotificationsServiceImpl
notificationsService.testInstance = object : TestNotificationsServiceImpl() {
override fun notifyError(
t: Throwable,
project: Project?,
custTitle: String?,
custDetailsShort: String?,
custDetailsLong: String?
) {
if (custTitle == "Error with Zowe config file") {
notified = true
}
}
}

afterEach {
isFilesWriteTriggered = false
isRunWriteActionCalled = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

package org.zowe.explorer.config.connect.ui.zosmf

import com.intellij.ide.DataManager
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogWrapper
import com.intellij.openapi.ui.Messages
Expand All @@ -29,7 +32,9 @@ import org.zowe.explorer.common.ui.ValidatingTableView
import org.zowe.explorer.config.ConfigStateV2
import org.zowe.explorer.config.connect.ConnectionConfig
import org.zowe.explorer.config.makeCrudableWithoutListeners
import org.zowe.explorer.telemetry.NotificationsService
import org.zowe.explorer.testutils.WithApplicationShouldSpec
import org.zowe.explorer.testutils.testServiceImpl.TestNotificationsServiceImpl
import org.zowe.kotlinsdk.annotations.ZVersion
import org.zowe.kotlinsdk.zowe.config.DefaultKeytarWrapper
import org.zowe.kotlinsdk.zowe.config.KeytarWrapper
Expand All @@ -49,6 +54,7 @@ class ZOSMFConnectionConfigurableTest : WithApplicationShouldSpec({
var isShowOkCancelDialogCalled = false
var isFindFileByNioPathCalled = false
var isInputStreamCalled = false
var notified = false

afterSpec {
clearAllMocks()
Expand All @@ -59,10 +65,26 @@ class ZOSMFConnectionConfigurableTest : WithApplicationShouldSpec({
isShowOkCancelDialogCalled = false
isFindFileByNioPathCalled = false
isInputStreamCalled = false
notified = false
}

context("ZOSMFConnectionConfigurable:") {

val notificationsService = NotificationsService.getService() as TestNotificationsServiceImpl
notificationsService.testInstance = object : TestNotificationsServiceImpl() {
override fun notifyError(
t: Throwable,
project: Project?,
custTitle: String?,
custDetailsShort: String?,
custDetailsLong: String?
) {
if (custTitle == "Error with Zowe config file") {
notified = true
}
}
}

val state = ConnectionDialogState(
connectionUuid = "0000",
connectionUrl = "https://111.111.111.111:111",
Expand Down Expand Up @@ -156,6 +178,42 @@ class ZOSMFConnectionConfigurableTest : WithApplicationShouldSpec({
isFindFileByNioPathCalled = true
vfMock
}
every { vfMock.inputStream } answers {
isInputStreamCalled = true
val fileCont = "{\n" +
" \"\$schema\": \"./zowe.schema.json\",\n" +
" \"profiles\": {\n" +
" \"zosmf\": {\n" +
"}"
fileCont.toByteArray().inputStream()
}
every { vfMock.path } returns "/zowe/file/path/zowe.config.json"
every { vfMock.charset } returns Charsets.UTF_8
every { vfMock.setBinaryContent(any()) } just Runs

mockkObject(ZoweConfig)
val confMap = mutableMapOf<String, MutableMap<String, String>>()
val configCredentialsMap = mutableMapOf<String, String>()
configCredentialsMap["profiles.base.properties.user"] = "testUser"
configCredentialsMap["profiles.base.properties.password"] = "testPass"
confMap.clear()
confMap["/zowe/file/path/zowe.config.json"] = configCredentialsMap
every { ZoweConfig.Companion["readZoweCredentialsFromStorage"](any<KeytarWrapper>()) } returns confMap

should("updateZoweConfigIfNeeded throw JsonSyntaxException") {
zOSMFConnectionConfigurableMock::class.declaredMemberFunctions.find { it.name == "updateZoweConfigIfNeeded" }
?.let {
it.isAccessible = true
try {
it.call(zOSMFConnectionConfigurableMock, state)
} catch (t: Throwable) {
println("ghjkk")
t.cause.toString().shouldContain("Zowe config file not found")
}
}
notified shouldBe true
}

every { vfMock.inputStream } answers {
isInputStreamCalled = true
val fileCont = "{\n" +
Expand Down Expand Up @@ -205,18 +263,6 @@ class ZOSMFConnectionConfigurableTest : WithApplicationShouldSpec({
"}"
fileCont.toByteArray().inputStream()
}
every { vfMock.path } returns "/zowe/file/path/zowe.config.json"
every { vfMock.charset } returns Charsets.UTF_8
every { vfMock.setBinaryContent(any()) } just Runs

mockkObject(ZoweConfig)
val confMap = mutableMapOf<String, MutableMap<String, String>>()
val configCredentialsMap = mutableMapOf<String, String>()
configCredentialsMap["profiles.base.properties.user"] = "testUser"
configCredentialsMap["profiles.base.properties.password"] = "testPass"
confMap.clear()
confMap["/zowe/file/path/zowe.config.json"] = configCredentialsMap
every { ZoweConfig.Companion["readZoweCredentialsFromStorage"](any<KeytarWrapper>()) } returns confMap

should("updateZoweConfigIfNeeded success") {
zOSMFConnectionConfigurableMock::class.declaredMemberFunctions.find { it.name == "updateZoweConfigIfNeeded" }
Expand Down

0 comments on commit d742a64

Please sign in to comment.