Skip to content

Commit 82eacd8

Browse files
author
David Hasani
committed
put ZIP contents under dependencies/
1 parent 53cb61e commit 82eacd8

File tree

15 files changed

+315
-113
lines changed

15 files changed

+315
-113
lines changed

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerManager.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ class CodeModernizerManager(private val project: Project) : PersistentStateCompo
687687
sourceVendor = customerSelection.sourceVendor,
688688
targetVendor = customerSelection.targetVendor,
689689
sourceServerName = customerSelection.sourceServerName,
690+
sqlMetadataZip = customerSelection.sqlMetadataZip,
690691
),
691692
)
692693
}

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package software.aws.toolkits.jetbrains.services.codemodernizer
55

66
import com.intellij.openapi.Disposable
77
import com.intellij.openapi.application.runInEdt
8-
import com.intellij.openapi.projectRoots.JavaSdkVersion
98
import com.intellij.serviceContainer.AlreadyDisposedException
109
import com.intellij.util.io.HttpRequests
1110
import kotlinx.coroutines.delay
@@ -63,12 +62,7 @@ import java.util.concurrent.CancellationException
6362
import java.util.concurrent.atomic.AtomicBoolean
6463
import javax.net.ssl.SSLHandshakeException
6564

66-
const val ZIP_SOURCES_PATH = "sources"
67-
const val BUILD_LOG_PATH = "build-logs.txt"
68-
const val UPLOAD_ZIP_MANIFEST_VERSION = 1.0F
6965
const val MAX_ZIP_SIZE = 2000000000 // 2GB
70-
const val HIL_1P_UPGRADE_CAPABILITY = "HIL_1pDependency_VersionUpgrade"
71-
const val EXPLAINABILITY_V1 = "EXPLAINABILITY_V1"
7266

7367
// constants for handling SDKClientException
7468
const val CONNECTION_REFUSED_ERROR: String = "Connection refused"
@@ -274,7 +268,7 @@ class CodeModernizerSession(
274268
} finally {
275269
telemetry.uploadProject(payloadSize, startTime, true, telemetryErrorMessage)
276270
if (payload != null) {
277-
// TODO: revert
271+
// TODO: revert this
278272
notifyStickyInfo("zip path", payload.path)
279273
// deleteUploadArtifact(payload)
280274
}

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeTransformTelemetryManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class CodeTransformTelemetryManager(private val project: Project) {
145145
}
146146

147147
fun getProjectHash(customerSelection: CustomerSelection) = Base64.getEncoder().encodeToString(
148-
DigestUtils.sha256(customerSelection.configurationFile.toNioPath().toAbsolutePath().toString())
148+
DigestUtils.sha256(customerSelection.configurationFile?.toNioPath()?.toAbsolutePath().toString())
149149
)
150150

151151
/**

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt

Lines changed: 25 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import com.intellij.openapi.fileChooser.FileChooser
1111
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
1212
import com.intellij.openapi.module.ModuleUtil
1313
import com.intellij.openapi.projectRoots.JavaSdkVersion
14+
import com.intellij.openapi.util.io.FileUtil.createTempDirectory
15+
import com.intellij.openapi.vfs.LocalFileSystem
1416
import com.intellij.openapi.vfs.VirtualFile
1517
import kotlinx.coroutines.CoroutineScope
1618
import kotlinx.coroutines.Dispatchers
@@ -102,10 +104,20 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getModuleOr
102104
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.isCodeTransformAvailable
103105
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.toVirtualFile
104106
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.tryGetJdk
107+
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.unzipFile
108+
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.validateSctMetadata
105109
import software.aws.toolkits.jetbrains.services.cwc.messages.ChatMessageType
106110
import software.aws.toolkits.jetbrains.utils.notifyStickyInfo
107111
import software.aws.toolkits.resources.message
108112
import software.aws.toolkits.telemetry.CodeTransformVCSViewerSrcComponents
113+
import java.io.BufferedReader
114+
import java.io.File
115+
import java.io.FileInputStream
116+
import java.io.InputStreamReader
117+
import java.nio.charset.StandardCharsets
118+
import java.util.zip.ZipFile
119+
import java.util.zip.ZipInputStream
120+
import kotlin.io.path.Path
109121

110122
class CodeTransformChatController(
111123
private val context: AmazonQAppInitContext,
@@ -289,69 +301,11 @@ class CodeTransformChatController(
289301
}
290302
}
291303

292-
private fun validateSctMetadata(selectedFile: VirtualFile): SqlMetadataValidationResult {
293-
val fileContent = selectedFile.contentsToByteArray().toString(Charsets.UTF_8)
294-
val xmlDeserializer = XmlMapper(JacksonXmlModule())
295-
var sctMetadata: Map<*, *>? = null
296-
try {
297-
sctMetadata = xmlDeserializer.readValue(fileContent, Any::class.java) as Map<*, *>
298-
} catch (e: Exception) {
299-
getLogger<CodeTransformChatController>().error { "Error parsing .sct metadata file; invalid XML encountered." }
300-
return SqlMetadataValidationResult(false, "Invalid XML encountered.")
301-
}
302-
303-
try {
304-
val instances = sctMetadata["instances"] as Map<*, *>
305-
val projectModel = instances["ProjectModel"] as Map<*, *>
306-
val entities = projectModel["entities"] as Map<*, *>
307-
308-
val sources = entities["sources"] as Map<*, *>
309-
val sourceDbServer = sources["DbServer"] as Map<*, *>
310-
val sourceVendor = (sourceDbServer["vendor"] as String).trim().uppercase()
311-
if (sourceVendor != "ORACLE") {
312-
return SqlMetadataValidationResult(false, "Sorry, your .sct metadata file appears to be invalid; the source DB must be Oracle.")
313-
}
314-
315-
val sourceServerName = (sourceDbServer["name"] as String).trim()
316-
317-
val targets = entities["targets"] as Map<*, *>
318-
val targetDbServer = targets["DbServer"] as Map<*, *>
319-
val targetVendor = (targetDbServer["vendor"] as String).trim().uppercase()
320-
if (targetVendor != "AURORA_POSTGRESQL" && targetVendor != "RDS_POSTGRESQL") {
321-
return SqlMetadataValidationResult(false, "Sorry, your .sct metadata file appears to be invalid; the target DB must be Aurora PostgreSQL or Amazon RDS for PostgreSQL.")
322-
}
323-
324-
val relations = projectModel["relations"] as Map<*, *>
325-
val serverNodeLocations = relations["server-node-location"] as List<Map<*, *>>
326-
val schemaNames = mutableSetOf<String>()
327-
for (serverNodeLocation in serverNodeLocations) {
328-
val fullNameNodeInfoList = serverNodeLocation["FullNameNodeInfoList"] as Map<*, *>
329-
val nameParts = fullNameNodeInfoList["nameParts"] as Map<*, *>
330-
var fullNameNodeInfo = nameParts["FullNameNodeInfo"] // as List<Map<*, *>>
331-
if (fullNameNodeInfo is Map<*, *>) {
332-
continue
333-
} else {
334-
fullNameNodeInfo = fullNameNodeInfo as List<Map<*, *>>
335-
}
336-
fullNameNodeInfo.forEach{ node ->
337-
if ((node["typeNode"] as String).lowercase() == "schema") {
338-
schemaNames.add((node["nameNode"] as String).uppercase()) // user will choose one later
339-
}
340-
}
341-
}
342-
// .sct metadata file is valid, return SqlMetadataValidationResult with all data we parsed
343-
return SqlMetadataValidationResult(true, "", sourceVendor, targetVendor, sourceServerName, schemaNames)
344-
} catch (e: Exception) {
345-
getLogger<CodeTransformChatController>().error { "Error parsing .sct metadata file: $e" }
346-
return SqlMetadataValidationResult(false, "Sorry, the .sct metadata file you provided appears to be invalid.")
347-
}
348-
}
349-
350304
override suspend fun processCodeTransformSelectSQLModuleSchemaAction(message: IncomingCodeTransformMessage.CodeTransformSelectSQLModuleSchema) {
351-
val moduleName = context.project.getModuleOrProjectNameForFile(message.modulePath.toVirtualFile() as VirtualFile)
305+
val moduleName = context.project.getModuleOrProjectNameForFile(message.modulePath.toVirtualFile())
352306
codeTransformChatHelper.addNewMessage(buildUserSQLConversionSelectionSummaryChatContent(moduleName, message.schema))
353307
codeModernizerManager.codeTransformationSession?.let {
354-
it.sessionContext.configurationFile = message.modulePath.toVirtualFile() as VirtualFile // any file in the selected module works fine; will use to createZip
308+
it.sessionContext.configurationFile = message.modulePath.toVirtualFile()
355309
it.sessionContext.schema = message.schema
356310
}
357311
// start the SQL conversion
@@ -363,12 +317,18 @@ class CodeTransformChatController(
363317
override suspend fun processCodeTransformSelectSQLMetadataAction(message: IncomingCodeTransformMessage.CodeTransformSelectSQLMetadata) {
364318
runInEdt {
365319
val descriptor = FileChooserDescriptorFactory.createSingleFileDescriptor()
366-
.withDescription("Select .sct metadata file")
367-
.withFileFilter { it.extension == "sct" }
320+
.withDescription("Select metadata ZIP file")
321+
.withFileFilter { it.extension == "zip" }
322+
323+
val selectedZipFile = FileChooser.chooseFile(descriptor, null, null) ?: return@runInEdt
324+
val extractedZip = createTempDirectory("codeTransformSQLMetadata", null) // .path.toVirtualFile()
325+
unzipFile(selectedZipFile.toNioPath(), extractedZip.toPath())
326+
327+
notifyStickyInfo("tempDir", extractedZip.path)
368328

369-
val selectedFile = FileChooser.chooseFile(descriptor, null, null) ?: return@runInEdt
329+
val sctFile = extractedZip.listFiles { file -> file.name.endsWith(".sct") }.firstOrNull()
370330

371-
val metadataValidationResult = this.validateSctMetadata(selectedFile)
331+
val metadataValidationResult = validateSctMetadata(sctFile)
372332

373333
if (!metadataValidationResult.valid) {
374334
CoroutineScope(Dispatchers.Main).launch {
@@ -395,7 +355,7 @@ class CodeTransformChatController(
395355
sourceVendor = metadataValidationResult.sourceVendor,
396356
targetVendor = metadataValidationResult.targetVendor,
397357
sourceServerName = metadataValidationResult.sourceServerName,
398-
configurationFile = selectedFile
358+
sqlMetadataZip = extractedZip,
399359
)
400360
codeModernizerManager.createCodeModernizerSession(selection, context.project)
401361
}

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ const val MANIFEST_PATH = "manifest.json"
4444
const val ZIP_SOURCES_PATH = "sources"
4545
const val ZIP_DEPENDENCIES_PATH = "dependencies"
4646
const val BUILD_LOG_PATH = "build-logs.txt"
47+
const val UPLOAD_ZIP_MANIFEST_VERSION = "1.0"
48+
const val HIL_1P_UPGRADE_CAPABILITY = "HIL_1pDependency_VersionUpgrade"
49+
const val EXPLAINABILITY_V1 = "EXPLAINABILITY_V1"
4750
const val MAVEN_CONFIGURATION_FILE_NAME = "pom.xml"
4851
const val MAVEN_BUILD_RUN_UNIT_TESTS = "clean test"
4952
const val MAVEN_BUILD_SKIP_UNIT_TESTS = "clean test-compile"
@@ -53,14 +56,15 @@ const val INVALID_SUFFIX_SHA = "sha1"
5356
const val INVALID_SUFFIX_REPOSITORIES = "repositories"
5457
data class CodeModernizerSessionContext(
5558
val project: Project,
56-
var configurationFile: VirtualFile, // always needed to ZIP module
59+
var configurationFile: VirtualFile? = null, // used to ZIP module
5760
val sourceJavaVersion: JavaSdkVersion, // always needed for startJob API
5861
val targetJavaVersion: JavaSdkVersion = JavaSdkVersion.JDK_17, // only one supported
5962
var customBuildCommand: String = MAVEN_BUILD_RUN_UNIT_TESTS, // run unit tests by default
60-
var sourceVendor: String = "ORACLE", // only one supported
61-
var targetVendor: String? = null,
62-
var sourceServerName: String? = null,
63+
val sourceVendor: String = "ORACLE", // only one supported
64+
val targetVendor: String? = null,
65+
val sourceServerName: String? = null,
6366
var schema: String? = null,
67+
val sqlMetadataZip: File? = null,
6468
) {
6569
private val mapper = jacksonObjectMapper()
6670
private val ignoredDependencyFileExtensions = setOf(INVALID_SUFFIX_SHA, INVALID_SUFFIX_REPOSITORIES)
@@ -180,23 +184,22 @@ data class CodeModernizerSessionContext(
180184
}
181185

182186
fun createZipWithModuleFiles(copyResult: MavenCopyCommandsResult?): ZipCreationResult {
183-
val root = configurationFile.parent
184-
val sourceFolder = File(root.path)
187+
val root = configurationFile?.parent
188+
val sourceFolder = File(root?.path)
185189
val buildLogBuilder = StringBuilder("Starting Build Log...\n")
186-
// depDirectory will be null for SQL conversions since copyResult will be null
187190
val depDirectory = if (copyResult is MavenCopyCommandsResult.Success) {
188191
showTransformationHub()
189192
copyResult.dependencyDirectory
190-
} else {
191-
null
192-
}
193+
} else sqlMetadataZip // null copyResult means doing a SQL conversion
193194

194195
return runReadAction {
195196
try {
196197
val directoriesToExclude = findDirectoriesToExclude(sourceFolder)
197-
val files = VfsUtil.collectChildrenRecursively(root).filter { child ->
198-
val childPath = Path(child.path)
199-
!child.isDirectory && directoriesToExclude.none { childPath.startsWith(it.toPath()) }
198+
val files = root?.let {
199+
VfsUtil.collectChildrenRecursively(it).filter { child ->
200+
val childPath = Path(child.path)
201+
!child.isDirectory && directoriesToExclude.none { childPath.startsWith(it.toPath()) }
202+
}
200203
}
201204
val dependencyFiles = if (depDirectory != null) {
202205
iterateThroughDependencies(depDirectory)
@@ -208,22 +211,24 @@ data class CodeModernizerSessionContext(
208211
val depSources = File(ZIP_DEPENDENCIES_PATH)
209212
val outputFile = createTemporaryZipFile { zip ->
210213
// 1) Manifest file
211-
val dependenciesRoot = if (depDirectory != null) "$ZIP_DEPENDENCIES_PATH/${depDirectory.name}" else null
212-
var manifest = ZipManifest(dependenciesRoot = dependenciesRoot, customBuildCommand = customBuildCommand)
213-
if (schema != null) {
214+
// val dependenciesRoot = if (depDirectory != null) "$ZIP_DEPENDENCIES_PATH/${depDirectory.name}" else null
215+
var manifest = ZipManifest(customBuildCommand = customBuildCommand)
216+
if (sqlMetadataZip != null) {
214217
// doing a SQL conversion, not language upgrade
215-
manifest = ZipManifest(sourceVendor = sourceVendor, targetVendor = targetVendor, sourceServerName = sourceServerName, schema = schema)
218+
// sctFileName below will not work since configurationFile points to any file in the Java module, not the metadata ZIP
219+
manifest = ZipManifest(requestedConversions = RequestedConversions(sqlConversion = SQLConversion(source = sourceVendor, target = targetVendor, schema = schema, host = sourceServerName, sctFileName = sqlMetadataZip.listFiles { file -> file.name.endsWith(".sct") }.first().name)))
216220
}
217221
mapper.writeValueAsString(manifest)
218222
.byteInputStream()
219223
.use {
220224
zip.putNextEntry(Path(MANIFEST_PATH).toString(), it)
221225
}
222226

223-
// 2) Dependencies
227+
// 2) Dependencies / SQL conversion metadata
224228
if (depDirectory != null) {
229+
notifyStickyInfo("depDirectory", "depDirectory is NOT null")
225230
dependencyFiles.forEach { depFile ->
226-
val relativePath = File(depFile.path).relativeTo(depDirectory.parentFile)
231+
val relativePath = File(depFile.path).relativeTo(depDirectory)
227232
val paddedPath = depSources.resolve(relativePath)
228233
var paddedPathString = paddedPath.toPath().toString()
229234
// Convert Windows file path to work on Linux
@@ -239,7 +244,7 @@ data class CodeModernizerSessionContext(
239244
LOG.info { "Dependency files size = ${dependencyFiles.sumOf { it.length().toInt() }}" }
240245

241246
// 3) Sources
242-
files.forEach { file ->
247+
files?.forEach { file ->
243248
val relativePath = File(file.path).relativeTo(sourceFolder)
244249
val paddedPath = zipSources.resolve(relativePath)
245250
var paddedPathString = paddedPath.toPath().toString()

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CustomerSelection.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ package software.aws.toolkits.jetbrains.services.codemodernizer.model
55

66
import com.intellij.openapi.projectRoots.JavaSdkVersion
77
import com.intellij.openapi.vfs.VirtualFile
8+
import java.io.File
89

910
data class CustomerSelection(
10-
val configurationFile: VirtualFile, // always needed to ZIP module
11+
val configurationFile: VirtualFile? = null, // used to ZIP module
1112
val sourceJavaVersion: JavaSdkVersion, // always needed, use default of JDK_8 for SQL conversions for startJob API call
1213
val targetJavaVersion: JavaSdkVersion = JavaSdkVersion.JDK_17,
1314
val sourceVendor: String = "ORACLE", // only one supported
1415
val targetVendor: String? = null,
1516
val sourceServerName: String? = null,
17+
val sqlMetadataZip: File? = null,
1618
// note: schema and customBuildCommand are passed in to CodeModernizerSessionContext separately, *after* CodeModernizerSession is created
1719
)

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/JobHistoryItem.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import java.time.Instant
77
import kotlin.time.Duration.Companion.seconds
88
import kotlin.time.toKotlinDuration
99

10-
data class JobHistoryItem(val moduleName: String, val status: String, val startTime: Instant, val runTime: java.time.Duration, val jobId: String) {
10+
data class JobHistoryItem(val moduleName: String?, val status: String, val startTime: Instant, val runTime: java.time.Duration, val jobId: String) {
1111
operator fun get(col: Int): Any = when (col) {
12-
0 -> moduleName
12+
0 -> moduleName ?: ""
1313
1 -> status
1414
2 -> startTime
1515
3 -> runTime.toKotlinDuration().inWholeSeconds.seconds.toString()

plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,25 @@
33

44
package software.aws.toolkits.jetbrains.services.codemodernizer.model
55

6-
import software.aws.toolkits.jetbrains.services.codemodernizer.BUILD_LOG_PATH
7-
import software.aws.toolkits.jetbrains.services.codemodernizer.EXPLAINABILITY_V1
8-
import software.aws.toolkits.jetbrains.services.codemodernizer.HIL_1P_UPGRADE_CAPABILITY
9-
import software.aws.toolkits.jetbrains.services.codemodernizer.UPLOAD_ZIP_MANIFEST_VERSION
10-
import software.aws.toolkits.jetbrains.services.codemodernizer.ZIP_SOURCES_PATH
11-
126
data class ZipManifest(
137
val sourcesRoot: String = ZIP_SOURCES_PATH,
14-
val dependenciesRoot: String? = null,
8+
val dependenciesRoot: String = ZIP_DEPENDENCIES_PATH,
159
val buildLogs: String = BUILD_LOG_PATH,
16-
val version: String = UPLOAD_ZIP_MANIFEST_VERSION.toString(),
10+
val version: String = UPLOAD_ZIP_MANIFEST_VERSION,
1711
val hilCapabilities: List<String> = listOf(HIL_1P_UPGRADE_CAPABILITY),
1812
val transformCapabilities: List<String> = listOf(EXPLAINABILITY_V1),
1913
val customBuildCommand: String = MAVEN_BUILD_RUN_UNIT_TESTS,
20-
val sourceVendor: String? = null,
21-
val targetVendor: String? = null,
22-
val sourceServerName: String? = null,
14+
val requestedConversions: RequestedConversions = RequestedConversions(sqlConversion = null),
15+
)
16+
17+
data class RequestedConversions(
18+
val sqlConversion: SQLConversion? = null,
19+
)
20+
21+
data class SQLConversion(
22+
val source: String? = null,
23+
val target: String? = null,
2324
val schema: String? = null,
25+
val host: String? = null,
26+
val sctFileName: String? = null,
2427
)

0 commit comments

Comments
 (0)