Skip to content

Commit 11bc2f2

Browse files
committed
Merge branch 'private-release/v2.0.1' into public-release/v2.0.1
Signed-off-by: Uladzislau <[email protected]>
2 parents 81ec310 + 31d14a7 commit 11bc2f2

27 files changed

+627
-146
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
.intellijPlatform
44
/build
55
/ide_for_launch
6+
/out
7+
/allure-results
68

79
verifier-all.jar
810

CHANGELOG.md

+19
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@ All notable changes to the Zowe IntelliJ Plugin will be documented in this file.
44

55
## [2.0.0] (2024-10-02)
66

7+
### Bugfixes
8+
9+
* Bugfix: Fixed IndexOutOfBoundException in JES Explorer ([a80bf073](https://github.com/zowe/zowe-explorer-intellij/commit/a80bf073))
10+
* Bugfix: Fixed NullPointerException during a sort action ([42c9ee5a](https://github.com/zowe/zowe-explorer-intellij/commit/42c9ee5a))
11+
* Bugfix: Fixed issue with purge that won't trigger a refresh ([b93118b7](https://github.com/zowe/zowe-explorer-intellij/commit/b93118b7))
12+
* Bugfix: Fixed issue with refreshing USS folders when a working set or a mask is refreshed ([19a08a9b](https://github.com/zowe/zowe-explorer-intellij/commit/19a08a9b))
13+
* Bugfix: Fixed working with trusted certificates ([41b52b83](https://github.com/zowe/zowe-explorer-intellij/commit/41b52b83))
14+
* Bugfix: Fixed issue with refresh that won't work when a connection is changed on a working set ([90825a6d](https://github.com/zowe/zowe-explorer-intellij/commit/90825a6d))
15+
* Bugfix: Fixed issue with cross-system folder copy with name conflicts ([c5345051](https://github.com/zowe/zowe-explorer-intellij/commit/c5345051))
16+
* Bugfix: Clarified 401 error ([f36ec547](https://github.com/zowe/zowe-explorer-intellij/commit/f36ec547))
17+
* Bugfix: Fixed issue with USS copy that would lead to incorrect encoding error ([b4cb705a](https://github.com/zowe/zowe-explorer-intellij/commit/b4cb705a))
18+
* Bugfix: Fixed issue with jobs DDs display in console ([8a75f21a](https://github.com/zowe/zowe-explorer-intellij/commit/8a75f21a))
19+
* Bugfix: Fixed issue with copying another user's folder in USS ([66676550](https://github.com/zowe/zowe-explorer-intellij/commit/66676550))
20+
* Bugfix: Some encodings are made unsupported ([080c25ab](https://github.com/zowe/zowe-explorer-intellij/commit/080c25ab))
21+
* Bugfix: Fixed issue during a file upload to a PDS ([954bf01f](https://github.com/zowe/zowe-explorer-intellij/commit/954bf01f))
22+
* Bugfix: Fixed issue with URL field when typing incorrect information, the last slash at the end of https:// is deleted ([91ab962d](https://github.com/zowe/zowe-explorer-intellij/commit/91ab962d))
23+
24+
## [2.0.0] (2024-10-03)
25+
726
### Features
827

928
* Feature: GitHub issue #119: Space units are clarified with a hint ([451f3528](https://github.com/zowe/zowe-explorer-intellij/commit/451f3528))

build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ val plugins = listOf(
5252
jvmTargetVersion = JavaVersion.VERSION_21,
5353
since = "243.12818",
5454
getUntil = { provider { null } },
55-
sdkVersion = "243-EAP-SNAPSHOT",
55+
sdkVersion = "2024.3",
5656
sourceFolder = "IC-243"
5757
)
5858
)

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#
1414
org.gradle.jvmargs=-Xss1M
1515
# SemVer format -> https://semver.org
16-
pluginVersion=2.0.0
16+
pluginVersion=2.0.1
1717
pluginGroup=eu.ibagroup
1818
pluginRepositoryUrl=https://github.com/for-mainframe/For-Mainframe
1919
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html

src/main/kotlin/eu/ibagroup/formainframe/api/ZosmfApiImpl.kt

+78-77
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,19 @@
1414

1515
package eu.ibagroup.formainframe.api
1616

17-
import com.google.gson.GsonBuilder
17+
import com.intellij.util.net.ssl.CertificateManager
1818
import eu.ibagroup.formainframe.config.connect.ConnectionConfig
19-
import org.zowe.kotlinsdk.buildApi
20-
import org.zowe.kotlinsdk.buildApiWithBytesConverter
2119
import okhttp3.ConnectionPool
2220
import okhttp3.ConnectionSpec
2321
import okhttp3.Dispatcher
2422
import okhttp3.OkHttpClient
25-
import retrofit2.converter.gson.GsonConverterFactory
26-
import retrofit2.converter.scalars.ScalarsConverterFactory
23+
import org.zowe.kotlinsdk.buildApi
24+
import org.zowe.kotlinsdk.buildApiWithBytesConverter
2725
import java.security.SecureRandom
2826
import java.security.cert.CertificateException
2927
import java.security.cert.X509Certificate
3028
import java.util.concurrent.TimeUnit
31-
import javax.net.ssl.SSLContext
32-
import javax.net.ssl.TrustManager
33-
import javax.net.ssl.X509TrustManager
29+
import javax.net.ssl.*
3430

3531
/**
3632
* Class that implements z/OSMF API for sending requests.
@@ -101,44 +97,8 @@ class ZosmfApiImpl : ZosmfApi {
10197
}
10298
}
10399

104-
private val gsonFactory = GsonConverterFactory.create(GsonBuilder().create())
105-
private val scalarsConverterFactory = ScalarsConverterFactory.create()
106-
107-
/**
108-
* Connection pool is initialized and the connection parameters are set.
109-
*/
110-
private fun OkHttpClient.Builder.addThreadPool(): OkHttpClient.Builder {
111-
readTimeout(5, TimeUnit.MINUTES)
112-
connectTimeout(5, TimeUnit.MINUTES)
113-
connectionPool(ConnectionPool(100, 5, TimeUnit.MINUTES))
114-
dispatcher(Dispatcher().apply {
115-
maxRequests = 100
116-
maxRequestsPerHost = 100
117-
})
118-
return this
119-
}
120-
121-
val unsafeOkHttpClient by lazy { buildUnsafeClient() }
122-
val safeOkHttpClient: OkHttpClient by lazy {
123-
OkHttpClient.Builder()
124-
.setupClient()
125-
.build()
126-
}
127-
128-
/**
129-
* Setups http client. Adds the necessary headers. Configures connection specs.
130-
*/
131-
private fun OkHttpClient.Builder.setupClient(): OkHttpClient.Builder {
132-
return addThreadPool()
133-
.addInterceptor {
134-
it.request().newBuilder().addHeader("X-CSRF-ZOSMF-HEADER", "").build().let { request ->
135-
it.proceed(request)
136-
}
137-
}.connectionSpecs(mutableListOf(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT))
138-
}
139-
140100
/**
141-
* Returns [OkHttpClient] depending on whether self-signed certificates are allowed or not.
101+
* Returns [OkHttpClient] depending on whether self-signed certificates are allowed or not
142102
* @param isAllowSelfSigned whether to allow self-signed certificates.
143103
* @return safe or unsafe [OkHttpClient] object.
144104
*/
@@ -150,43 +110,84 @@ private fun getOkHttpClient(isAllowSelfSigned: Boolean): OkHttpClient {
150110
}
151111
}
152112

113+
private val unsafeOkHttpClient by lazy { buildUnsafeClient() }
114+
private val safeOkHttpClient by lazy { buildSafeClient() }
115+
153116
/**
154-
* Method for building an unsafe http client that allows the use of self-signed certificates.
155-
* @throws RuntimeException if timeout is exceeded.
156-
* @return unsafe [OkHttpClient] object.
117+
* Build an unsafe HTTP client that will allow the use of self-signed certificates
118+
* @return unsafe [OkHttpClient] object
157119
*/
158120
private fun buildUnsafeClient(): OkHttpClient {
159-
return try {
160-
val trustAllCerts: Array<TrustManager> = arrayOf(
161-
object : X509TrustManager {
162-
@Throws(CertificateException::class)
163-
override fun checkClientTrusted(
164-
chain: Array<X509Certificate?>?,
165-
authType: String?
166-
) {
167-
}
121+
val trustAllCerts: Array<TrustManager> = arrayOf(
122+
object : X509TrustManager {
123+
@Throws(CertificateException::class)
124+
override fun checkClientTrusted(
125+
chain: Array<X509Certificate?>?,
126+
authType: String?
127+
) {
128+
}
168129

169-
@Throws(CertificateException::class)
170-
override fun checkServerTrusted(
171-
chain: Array<X509Certificate?>?,
172-
authType: String?
173-
) {
174-
}
130+
@Throws(CertificateException::class)
131+
override fun checkServerTrusted(
132+
chain: Array<X509Certificate?>?,
133+
authType: String?
134+
) {
135+
}
175136

176-
override fun getAcceptedIssuers(): Array<X509Certificate> {
177-
return arrayOf()
178-
}
137+
override fun getAcceptedIssuers(): Array<X509Certificate> {
138+
return arrayOf()
179139
}
140+
}
141+
)
142+
val sslContext = SSLContext.getInstance("TLSv1.2")
143+
sslContext.init(null, trustAllCerts, SecureRandom())
144+
val sslSocketFactory = sslContext.socketFactory
145+
return OkHttpClient.Builder()
146+
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
147+
.hostnameVerifier { _, _ -> true }
148+
.setupClient()
149+
.build()
150+
}
151+
152+
/**
153+
* Build a safe HTTP client that will reuse all allowed secured trusted certificates across the client's system
154+
* (as well as those uploaded into IntelliJ's server certificates store)
155+
* @return safe [OkHttpClient] object
156+
*/
157+
private fun buildSafeClient(): OkHttpClient {
158+
val trustManager = CertificateManager.getInstance().trustManager
159+
val sslContext = CertificateManager.getInstance().sslContext
160+
return OkHttpClient.Builder()
161+
.sslSocketFactory(sslContext.socketFactory, trustManager)
162+
.setupClient()
163+
.build()
164+
}
165+
166+
/** Set up an HTTP client. Adds the necessary headers. Configures connection specs */
167+
private fun OkHttpClient.Builder.setupClient(): OkHttpClient.Builder {
168+
return addThreadPool()
169+
.addInterceptor {
170+
it.request()
171+
.newBuilder()
172+
.addHeader("X-CSRF-ZOSMF-HEADER", "")
173+
.build()
174+
.let { request ->
175+
it.proceed(request)
176+
}
177+
}
178+
.connectionSpecs(
179+
mutableListOf(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT)
180180
)
181-
val sslContext = SSLContext.getInstance("TLSv1.2")
182-
sslContext.init(null, trustAllCerts, SecureRandom())
183-
val sslSocketFactory = sslContext.socketFactory
184-
val builder = OkHttpClient.Builder()
185-
builder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
186-
builder.hostnameVerifier { _, _ -> true }
187-
builder.setupClient()
188-
builder.build()
189-
} catch (e: Exception) {
190-
throw RuntimeException(e)
191-
}
181+
}
182+
183+
/** Connection pool is initialized and the connection parameters are set */
184+
private fun OkHttpClient.Builder.addThreadPool(): OkHttpClient.Builder {
185+
readTimeout(5, TimeUnit.MINUTES)
186+
connectTimeout(5, TimeUnit.MINUTES)
187+
connectionPool(ConnectionPool(100, 5, TimeUnit.MINUTES))
188+
dispatcher(Dispatcher().apply {
189+
maxRequests = 100
190+
maxRequestsPerHost = 100
191+
})
192+
return this
192193
}

src/main/kotlin/eu/ibagroup/formainframe/config/connect/ui/zosmf/ConnectionDialog.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ class ConnectionDialog(
173173
"04.26.00" -> ZVersion.ZOS_2_3
174174
"04.27.00" -> ZVersion.ZOS_2_4
175175
"04.28.00" -> ZVersion.ZOS_2_5
176+
"04.29.00" -> ZVersion.ZOS_3_1
176177
else -> ZVersion.ZOS_2_1
177178
}
178179
newTestedConnConfig.zVersion = state.zVersion
@@ -286,7 +287,7 @@ class ConnectionDialog(
286287
textField()
287288
.bindText(state::connectionUrl)
288289
.validationOnApply {
289-
it.text = it.text.trim().removeTrailingSlashes()
290+
it.text = it.text.trim()
290291
validateForBlank(it) ?: validateZosmfUrl(it)
291292
}
292293
.also { urlTextField = it.component }

src/main/kotlin/eu/ibagroup/formainframe/dataops/attributes/RemoteUssAttributes.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ data class RemoteUssAttributes(
8080
val gid: Long? = null,
8181
val groupId: String? = null,
8282
val modificationTime: String? = null,
83-
val symlinkTarget: String? = null
83+
val symlinkTarget: String? = null,
84+
var charset: Charset = DEFAULT_BINARY_CHARSET
8485
) : MFRemoteFileAttributes<ConnectionConfig, UssRequester>, Copyable {
8586

8687
/**
@@ -102,7 +103,8 @@ data class RemoteUssAttributes(
102103
gid = ussFile.gid,
103104
groupId = ussFile.groupId,
104105
modificationTime = ussFile.modificationTime,
105-
symlinkTarget = ussFile.target
106+
symlinkTarget = ussFile.target,
107+
charset = DEFAULT_BINARY_CHARSET
106108
)
107109

108110
/**
@@ -176,8 +178,6 @@ data class RemoteUssAttributes(
176178
|| mode == FileModeValue.READ_WRITE_EXECUTE.mode
177179
}
178180

179-
var charset: Charset = DEFAULT_BINARY_CHARSET
180-
181181
override var contentMode: XIBMDataType = XIBMDataType(XIBMDataType.Type.BINARY)
182182

183183
override val isCopyPossible: Boolean

src/main/kotlin/eu/ibagroup/formainframe/dataops/attributes/RemoteUssAttributesService.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ class RemoteUssAttributesService(
8888
gid = newAttributes.gid,
8989
groupId = newAttributes.groupId,
9090
modificationTime = newAttributes.modificationTime,
91-
symlinkTarget = newAttributes.symlinkTarget
91+
symlinkTarget = newAttributes.symlinkTarget,
92+
charset = oldAttributes.charset
9293
)
9394
}
9495

src/main/kotlin/eu/ibagroup/formainframe/dataops/fetch/RemoteFileFetchProviderBase.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
package eu.ibagroup.formainframe.dataops.fetch
1616

1717
import com.intellij.ide.util.treeView.AbstractTreeNode
18-
import com.intellij.openapi.components.service
1918
import com.intellij.openapi.progress.ProcessCanceledException
2019
import com.intellij.openapi.progress.ProgressIndicator
2120
import com.intellij.openapi.vfs.VirtualFile
@@ -24,6 +23,7 @@ import eu.ibagroup.formainframe.config.connect.ConnectionConfigBase
2423
import eu.ibagroup.formainframe.dataops.DataOpsManager
2524
import eu.ibagroup.formainframe.dataops.Query
2625
import eu.ibagroup.formainframe.dataops.RemoteQuery
26+
import eu.ibagroup.formainframe.dataops.UnitRemoteQueryImpl
2727
import eu.ibagroup.formainframe.dataops.exceptions.CallException
2828
import eu.ibagroup.formainframe.dataops.services.ErrorSeparatorService
2929
import eu.ibagroup.formainframe.utils.castOrNull
@@ -223,7 +223,8 @@ abstract class RemoteFileFetchProviderBase<Connection : ConnectionConfigBase, Re
223223
}
224224
}
225225

226-
refreshCacheOfCollidingQuery(query, files)
226+
//TODO: the only known evidence to use refresh of colliding query is related to BatchedQuery
227+
query.castOrNull(UnitRemoteQueryImpl::class.java) ?: refreshCacheOfCollidingQuery(query, files)
227228

228229
cache[query] = files
229230
cacheState[query] = CacheState.FETCHED

src/main/kotlin/eu/ibagroup/formainframe/dataops/log/AbstractMFLoggerBase.kt

+7
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ abstract class AbstractMFLoggerBase<PInfo: MFProcessInfo, LFetcher: LogFetcher<P
126126
this.onFinishHandler = finishHandler
127127
}
128128

129+
/**
130+
* Fetch log files
131+
*/
132+
override fun fetchLog() {
133+
logFetcher.fetchLog(mfProcessInfo)
134+
}
135+
129136
/**
130137
* Sets onNextLog handler.
131138
*/

src/main/kotlin/eu/ibagroup/formainframe/dataops/log/MFLogger.kt

+5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ interface MFLogger<LFetcher: LogFetcher<out MFProcessInfo>> {
4141
*/
4242
fun onLogFinished(finishHandler: () -> Unit)
4343

44+
/**
45+
* Fetch log files
46+
*/
47+
fun fetchLog()
48+
4449
/**
4550
* Sets handler for event after requesting next portion of mainframe log.
4651
* @param nextLogHandler handler that will be invoked after next request to fetching log from mainframe.

src/main/kotlin/eu/ibagroup/formainframe/dataops/operations/InfoOperationRunner.kt

+5-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ class InfoOperationRunner : OperationRunner<InfoOperation, SystemsResponse> {
6161
.cancelByIndicator(progressIndicator)
6262
.execute()
6363
if (!response.isSuccessful) {
64-
val headMessage = responseMessageMap[response.message()] ?: response.message()
64+
log.info("Test connection response: $response")
65+
val zosmfMessage = response.message().trim()
66+
val headMessage = if (zosmfMessage.isNotEmpty())
67+
responseMessageMap[zosmfMessage] ?: zosmfMessage
68+
else responseMessageMap["Unauthorized"] ?: zosmfMessage
6569
throw CallException(response, headMessage)
6670
}
6771
return response.body() ?: throw CallException(response, "Cannot parse z/OSMF info request body")

0 commit comments

Comments
 (0)