Skip to content

Commit

Permalink
Merge branch 'feature/IJMP-2024' into 'release/v2.1.0'
Browse files Browse the repository at this point in the history
IJMP-2024 USS files and folders: Properties change feature

See merge request ijmp/for-mainframe!614
  • Loading branch information
Uladzislau Kalesnikau committed Nov 12, 2024
2 parents 6a3e55a + 074104c commit 3696042
Show file tree
Hide file tree
Showing 6 changed files with 344 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ data class RemoteUssAttributes(
override val requesters: MutableList<UssRequester>,
override val length: Long = 0L,
val uid: Long? = null,
val owner: String? = null,
var owner: String? = null,
val gid: Long? = null,
val groupId: String? = null,
var groupId: String? = null,
val modificationTime: String? = null,
val symlinkTarget: String? = null,
var charset: Charset = DEFAULT_BINARY_CHARSET
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2020-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 eu.ibagroup.formainframe.dataops.operations

import com.intellij.openapi.progress.ProgressIndicator
import eu.ibagroup.formainframe.api.api
import eu.ibagroup.formainframe.config.connect.ConnectionConfig
import eu.ibagroup.formainframe.config.connect.authToken
import eu.ibagroup.formainframe.dataops.DataOpsManager
import eu.ibagroup.formainframe.dataops.exceptions.CallException
import eu.ibagroup.formainframe.utils.cancelByIndicator
import eu.ibagroup.formainframe.utils.log
import org.zowe.kotlinsdk.ChangeOwner
import org.zowe.kotlinsdk.DataAPI
import org.zowe.kotlinsdk.FilePath

/**
* Class which represents factory for uss change owner operation runner. Defined in plugin.xml
*/
class UssChangeOwnerFactory : OperationRunnerFactory {
override fun buildComponent(dataOpsManager: DataOpsManager): OperationRunner<UssChangeOwnerOperation, Unit> {
return UssChangeOwner()
}
}

/**
* Data class which represents input parameters for uss change owner operation
* @param parameters instance of [ChangeOwner] object
* @param path path of uss file
*/
data class UssChangeOwnerParams(
val parameters: ChangeOwner,
val path: String,
)

/**
* Data class which represents uss change owner operation object
*/
data class UssChangeOwnerOperation(
override val request: UssChangeOwnerParams,
override val connectionConfig: ConnectionConfig,
) : RemoteUnitOperation<UssChangeOwnerParams>

/**
* Class which represents uss change owner operation runner
*/
class UssChangeOwner : OperationRunner<UssChangeOwnerOperation, Unit> {

override val operationClass = UssChangeOwnerOperation::class.java
override val resultClass = Unit::class.java
override val log = log<UssChangeOwner>()

/**
* Runs an uss change owner operation
* @param operation uss change owner operation to be run
* @param progressIndicator progress indicator object
* @throws CallException if request is not successful
* @return Void
*/
override fun run(
operation: UssChangeOwnerOperation, progressIndicator: ProgressIndicator
) {
progressIndicator.checkCanceled()
val response = api<DataAPI>(operation.connectionConfig).changeFileOwner(
authorizationToken = operation.connectionConfig.authToken,
filePath = FilePath(operation.request.path),
body = operation.request.parameters
).cancelByIndicator(progressIndicator).execute()
if (!response.isSuccessful) {
throw CallException(
response, "Cannot change file owner on ${operation.request.path}"
)
}
}

override fun canRun(operation: UssChangeOwnerOperation): Boolean {
return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ import eu.ibagroup.formainframe.dataops.attributes.RemoteMemberAttributes
import eu.ibagroup.formainframe.dataops.attributes.RemoteUssAttributes
import eu.ibagroup.formainframe.dataops.operations.UssChangeModeOperation
import eu.ibagroup.formainframe.dataops.operations.UssChangeModeParams
import eu.ibagroup.formainframe.dataops.operations.UssChangeOwnerOperation
import eu.ibagroup.formainframe.dataops.operations.UssChangeOwnerParams
import eu.ibagroup.formainframe.explorer.ExplorerUnit
import eu.ibagroup.formainframe.explorer.ui.*
import eu.ibagroup.formainframe.telemetry.NotificationsService
import eu.ibagroup.formainframe.utils.changeFileEncodingAction
import eu.ibagroup.formainframe.utils.clone
import eu.ibagroup.formainframe.utils.isBeingEditingNow
import org.zowe.kotlinsdk.ChangeMode
import org.zowe.kotlinsdk.ChangeOwner

/**
* Action for displaying properties of files on UI in dialog by clicking item in explorer context menu.
Expand Down Expand Up @@ -83,32 +86,64 @@ class GetFilePropertiesAction : AnAction() {
// }
val oldCharset = attributes.charset
val initFileMode = attributes.fileMode?.clone()
val initOwner = attributes.owner?.clone()
val initGroupID = attributes.groupId?.clone()
val dialog = UssFilePropertiesDialog(project, UssFileState(attributes, virtualFile.isBeingEditingNow()))
if (dialog.showAndGet()) {
if (
attributes.fileMode?.owner != initFileMode?.owner
|| attributes.fileMode?.group != initFileMode?.group
|| attributes.fileMode?.all != initFileMode?.all
) {
runBackgroundableTask(
title = "Changing file mode on ${attributes.path}",
project = project,
cancellable = true
) {
if (attributes.fileMode != null) {
runCatching {
dataOpsManager.performOperation(
operation = UssChangeModeOperation(
request = UssChangeModeParams(ChangeMode(mode = attributes.fileMode), attributes.path),
connectionConfig = connectionConfig
),
progressIndicator = it
)
}.onFailure { t ->
initFileMode?.owner?.let { attributes.fileMode.owner = it }
initFileMode?.group?.let { attributes.fileMode.group = it }
initFileMode?.all?.let { attributes.fileMode.all = it }
NotificationsService.errorNotification(t, e.project)
val isFileModeChanged = attributes.fileMode?.owner != initFileMode?.owner
|| attributes.fileMode?.group != initFileMode?.group
|| attributes.fileMode?.all != initFileMode?.all
val isOwnerChanged = attributes.owner != initOwner || attributes.groupId != initGroupID
if (isFileModeChanged || isOwnerChanged) {
if (isOwnerChanged) {
runBackgroundableTask(
title = "Changing file owner on ${attributes.path}",
project = project,
cancellable = true
) {
if (attributes.owner != null || attributes.groupId != null) {
runCatching {
dataOpsManager.performOperation(
operation = UssChangeOwnerOperation(
request = UssChangeOwnerParams(
ChangeOwner(
owner = attributes.owner ?: "",
group = attributes.groupId ?: ""
), attributes.path
),
connectionConfig = connectionConfig
),
progressIndicator = it
)
}.onFailure { t ->
initOwner?.let { attributes.owner = it }
initGroupID?.let { attributes.groupId = it }
NotificationsService.errorNotification(t, e.project)
}
}
}
}
if (isFileModeChanged) {
runBackgroundableTask(
title = "Changing file mode on ${attributes.path}",
project = project,
cancellable = true
) {
if (attributes.fileMode != null) {
runCatching {
dataOpsManager.performOperation(
operation = UssChangeModeOperation(
request = UssChangeModeParams(ChangeMode(mode = attributes.fileMode), attributes.path),
connectionConfig = connectionConfig
),
progressIndicator = it
)
}.onFailure { t ->
initFileMode?.owner?.let { attributes.fileMode.owner = it }
initFileMode?.group?.let { attributes.fileMode.group = it }
initFileMode?.all?.let { attributes.fileMode.all = it }
NotificationsService.errorNotification(t, e.project)
}
}
node.parent?.cleanCacheIfPossible(cleanBatchedQuery = false)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogPanel
import com.intellij.openapi.ui.ComboBox
import com.intellij.openapi.ui.DialogWrapper
import com.intellij.openapi.ui.ValidationInfo
import com.intellij.ui.components.JBTabbedPane
import com.intellij.ui.dsl.builder.bindItem
import com.intellij.ui.dsl.builder.panel
Expand All @@ -27,8 +28,7 @@ import eu.ibagroup.formainframe.dataops.attributes.RemoteUssAttributes
import javax.swing.JComponent
import com.intellij.ui.dsl.builder.*
import eu.ibagroup.formainframe.dataops.content.synchronizer.DEFAULT_BINARY_CHARSET
import eu.ibagroup.formainframe.utils.getParamTextValueOrUnknown
import eu.ibagroup.formainframe.utils.getSupportedEncodings
import eu.ibagroup.formainframe.utils.*
import org.zowe.kotlinsdk.*
import java.nio.charset.Charset

Expand All @@ -38,37 +38,8 @@ class UssFilePropertiesDialog(project: Project?, override var state: UssFileStat

private val sameWidthGroup = "USS_FILE_PROPERTIES_DIALOG_LABELS_WIDTH_GROUP"

private lateinit var generalTab: DialogPanel

private lateinit var permissionTab: DialogPanel

private lateinit var comboBox: Cell<ComboBox<Charset>>

var fileTypeName: String = "File"

private val fileModeValues = listOf(
FileModeValue.NONE,
FileModeValue.EXECUTE,
FileModeValue.WRITE,
FileModeValue.WRITE_EXECUTE,
FileModeValue.READ,
FileModeValue.READ_EXECUTE,
FileModeValue.READ_WRITE,
FileModeValue.READ_WRITE_EXECUTE
)

init {

if (state.ussAttributes.isDirectory)
fileTypeName = "Directory"
title = "$fileTypeName Properties"
init()
}

override fun createCenterPanel(): JComponent {
val tabbedPanel = JBTabbedPane()

generalTab = panel {
private val generalTab by lazy{
panel {
row {
label("$fileTypeName name: ")
.widthGroup(sameWidthGroup)
Expand Down Expand Up @@ -134,22 +105,30 @@ class UssFilePropertiesDialog(project: Project?, override var state: UssFileStat
}
}
}
}

permissionTab = panel {
private val permissionTab by lazy{
panel {
row {
label("Owner: ")
.widthGroup(sameWidthGroup)
textField()
.text(getParamTextValueOrUnknown(state.ussAttributes.owner))
.applyToComponent { isEditable = false }
.bindText(
{ state.ussAttributes.owner ?: UNKNOWN_PARAM_VALUE },
{ state.ussAttributes.owner = it }
)
.validationOnApply { validateForBlank(it) ?: validateFieldWithLengthRestriction(it, 8, "Owner") }
.align(AlignX.FILL)
}
row {
label("Group: ")
.widthGroup(sameWidthGroup)
textField()
.text(getParamTextValueOrUnknown(state.ussAttributes.groupId))
.applyToComponent { isEditable = false }
.bindText(
{ state.ussAttributes.groupId ?: UNKNOWN_PARAM_VALUE },
{ state.ussAttributes.groupId = it }
)
.validationOnApply { validateForBlank(it) ?: validateFieldWithLengthRestriction(it, 8, "Group") }
.align(AlignX.FILL)
}
row {
Expand Down Expand Up @@ -191,7 +170,35 @@ class UssFilePropertiesDialog(project: Project?, override var state: UssFileStat
.align(AlignX.FILL)
}
}
}

private lateinit var comboBox: Cell<ComboBox<Charset>>

var fileTypeName: String = "File"

private val fileModeValues = listOf(
FileModeValue.NONE,
FileModeValue.EXECUTE,
FileModeValue.WRITE,
FileModeValue.WRITE_EXECUTE,
FileModeValue.READ,
FileModeValue.READ_EXECUTE,
FileModeValue.READ_WRITE,
FileModeValue.READ_WRITE_EXECUTE
)

init {
if (state.ussAttributes.isDirectory)
fileTypeName = "Directory"
title = "$fileTypeName Properties"
permissionTab.registerValidators(myDisposable) { map ->
isOKActionEnabled = map.isEmpty()
}
init()
}

override fun createCenterPanel(): JComponent {
val tabbedPanel = JBTabbedPane()
tabbedPanel.add("General", generalTab)
tabbedPanel.add("Permissions", permissionTab)

Expand All @@ -204,6 +211,13 @@ class UssFilePropertiesDialog(project: Project?, override var state: UssFileStat
super.doOKAction()
}

/**
* Overloaded method to validate components in the permissionTab panel
*/
override fun doValidate(): ValidationInfo? {
return permissionTab.validateAll().firstOrNull() ?: super.doValidate()
}

}

class UssFileState(var ussAttributes: RemoteUssAttributes, val fileIsBeingEditingNow: Boolean)
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ Example of how to see the output:<br/>

<operationRunner implementation="eu.ibagroup.formainframe.dataops.operations.UssChangeModeFactory"/>

<operationRunner implementation="eu.ibagroup.formainframe.dataops.operations.UssChangeOwnerFactory"/>

<operationRunner
implementation="eu.ibagroup.formainframe.dataops.operations.mover.MemberToPdsMoverFactory"/>

Expand Down
Loading

0 comments on commit 3696042

Please sign in to comment.