diff --git a/languages/Transfer.groovy b/languages/Transfer.groovy index 0e9ce300..994de478 100644 --- a/languages/Transfer.groovy +++ b/languages/Transfer.groovy @@ -5,6 +5,8 @@ import com.ibm.dbb.build.* import com.ibm.dbb.build.report.records.* import com.ibm.dbb.build.report.* import groovy.transform.* +import java.nio.file.Files +import java.nio.file.StandardCopyOption /*** * @@ -39,6 +41,8 @@ import groovy.transform.* @Field def buildUtils= loadScript(new File("${props.zAppBuildDir}/utilities/BuildUtilities.groovy")) // Set to keep information about which datasets where already checked/created @Field HashSet verifiedBuildDatasets = new HashSet() +// Set to keep information about which USS directories where already checked/created +@Field HashSet verifiedUSSPaths = new HashSet() println("** Building ${argMap.buildList.size()} ${argMap.buildList.size() == 1 ? 'file' : 'files'} mapped to ${this.class.getName()}.groovy script") // verify required build properties @@ -67,70 +71,113 @@ buildList.each { buildFile -> // evaluate the datasetmapping, which maps build files to targetDataset defintions PropertyMappings dsMapping = new PropertyMappings("transfer_datasetMapping") PropertyMappings dsOptionsMapping = new PropertyMappings("transfer_dsOptions") + // evaluate the USS path mapping, which maps build files to USS target directory property names + PropertyMappings ussPathMapping = new PropertyMappings("transfer_toUSS") // obtain the target dataset based on the mapped dataset key mappedDatesetDef = dsMapping.getValue(buildFile) - String targetDataset = props.getProperty(mappedDatesetDef) - - if (targetDataset != null) { - - // obtain the dataset reference for targetDataset - String datasetOptions = dsOptionsMapping.getValue(mappedDatesetDef) - - if (datasetOptions == null) { - String errorMsg = "*! Dataset options for $buildFile could not be obtained PropertyMappings . " - println(errorMsg) - props.error = "true" - buildUtils.updateBuildResult(errorMsg:errorMsg) - } - - // get copy mode value from Property Mappings + String targetDataset = mappedDatesetDef ? props.getProperty(mappedDatesetDef) : null + + // check if this file should be copied to USS + def mappedUSSPathDef = ussPathMapping.getValue(buildFile) + boolean copyToUSS = mappedUSSPathDef != null + + if (targetDataset == null && !copyToUSS) { + String errorMsg = "*! Target dataset or USS path for $buildFile could not be obtained from file properties. " + println(errorMsg) + props.error = "true" + buildUtils.updateBuildResult(errorMsg:errorMsg) + } else { + + // get copy mode value from Property Mappings (shared for both PDS and USS copy) def copyMode = props.getFileProperty('transfer_copyMode', buildFile) - DBBConstants.CopyMode transferCopyMode - if (copyMode != null) { - transferCopyMode = DBBConstants.CopyMode.valueOf(copyMode) - } else { - transferCopyMode = DBBConstants.CopyMode.valueOf("TEXT") - if (props.verbose) println "** No CopyMode found for file '${buildFile}'. Using 'TEXT' as default." - } - - // allocate target dataset - if (!verifiedBuildDatasets.contains(targetDataset)) { // using a cache not to allocate all defined datasets - verifiedBuildDatasets.add(targetDataset) - buildUtils.createDatasets(targetDataset.split(), datasetOptions) + DBBConstants.CopyMode transferCopyMode + if (copyMode != null) { + transferCopyMode = DBBConstants.CopyMode.valueOf(copyMode) + } else { + transferCopyMode = DBBConstants.CopyMode.valueOf("TEXT") + if (props.verbose) println "** No CopyMode found for file '${buildFile}'. Using 'TEXT' as default." } - // copy the file to the target dataset String deployType = buildUtils.getDeployType("transfer", buildFile, null) - try { - int rc = new CopyToPDS().key(buildFile) - .file(new File(buildUtils.getAbsolutePath(buildFile))) - .copyMode(transferCopyMode) - .dataset(targetDataset) - .member(member) - .output(true) - .deployType(deployType) - .execute() - if (props.verbose) println "** Copied $buildFile to $targetDataset with copyMode $transferCopyMode and deployType $deployType (rc = $rc)" - - if (rc!=0){ - String errorMsg = "*! The CopyToPDS return code ($rc) for $buildFile exceeded the maximum return code allowed (0)." + // --- Copy to PDS target dataset --- + if (targetDataset != null) { + + // obtain the dataset allocation options + String datasetOptions = dsOptionsMapping.getValue(mappedDatesetDef) + + if (datasetOptions == null) { + String errorMsg = "*! Dataset options for $buildFile could not be obtained PropertyMappings . " println(errorMsg) props.error = "true" buildUtils.updateBuildResult(errorMsg:errorMsg) } - } catch (BuildException e) { // Catch potential exceptions like file truncation - String errorMsg = "*! (Transfer.groovy) CopyToPDS of file ${buildFile} failed with an exception \n ${e.getMessage()}." - throw new BuildException(errorMsg) + + // allocate target dataset + if (!verifiedBuildDatasets.contains(targetDataset)) { // using a cache not to allocate all defined datasets + verifiedBuildDatasets.add(targetDataset) + buildUtils.createDatasets(targetDataset.split(), datasetOptions) + } + + try { + int rc = new CopyToPDS().key(buildFile) + .file(new File(buildUtils.getAbsolutePath(buildFile))) + .copyMode(transferCopyMode) + .dataset(targetDataset) + .member(member) + .output(true) + .deployType(deployType) + .execute() + if (props.verbose) println "** Copied $buildFile to $targetDataset with copyMode $transferCopyMode and deployType $deployType (rc = $rc)" + + if (rc != 0) { + String errorMsg = "*! The CopyToPDS return code ($rc) for $buildFile exceeded the maximum return code allowed (0)." + println(errorMsg) + props.error = "true" + buildUtils.updateBuildResult(errorMsg:errorMsg) + } + } catch (BuildException e) { // Catch potential exceptions like file truncation + String errorMsg = "*! (Transfer.groovy) CopyToPDS of file ${buildFile} failed with an exception \n ${e.getMessage()}." + throw new BuildException(errorMsg) + } + } + + // --- Copy to USS target directory --- + if (copyToUSS) { + + // resolve USS target directory as 'ussfiles' under the workspace + String resolvedUSSPath = "${props.workspace}/ussfiles" + + // ensure the USS target directory exists + if (!verifiedUSSPaths.contains(resolvedUSSPath)) { + verifiedUSSPaths.add(resolvedUSSPath) + new File(resolvedUSSPath).mkdirs() + if (props.verbose) println "** Verified USS directory $resolvedUSSPath" + } + + try { + File sourceFile = new File(buildUtils.getAbsolutePath(buildFile)) + File destFile = new File("${resolvedUSSPath}/${member}") + // Use NIO copy for USS-to-USS file transfer + Files.copy(sourceFile.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING) + if (props.verbose) println "** Copied $buildFile to ${destFile.getAbsolutePath()}" + // Register the output in the build report using CopyToUnixRecord + CopyToUnixRecord record = new CopyToUnixRecord() + record.setSource(buildUtils.getAbsolutePath(buildFile)) + record.setTarget(destFile.getAbsolutePath()) + record.setDeployType(deployType) + record.setOutput(true) + record.setRc(0) + BuildReportFactory.getBuildReport().addRecord(record) + } catch (Exception e) { + String errorMsg = "*! (Transfer.groovy) USS copy of file ${buildFile} failed with an exception \n ${e.getMessage()}." + println(errorMsg) + props.error = "true" + buildUtils.updateBuildResult(errorMsg:errorMsg) + } } - } else { - String errorMsg = "*! Target dataset for $buildFile could not be obtained from file properties. " - println(errorMsg) - props.error = "true" - buildUtils.updateBuildResult(errorMsg:errorMsg) } } } - diff --git a/samples/application-conf/file.properties b/samples/application-conf/file.properties index c21945e6..7e079d04 100644 --- a/samples/application-conf/file.properties +++ b/samples/application-conf/file.properties @@ -12,7 +12,7 @@ dbb.scriptMapping = LinkEdit.groovy :: **/*.lnk dbb.scriptMapping = PLI.groovy :: **/*.pli dbb.scriptMapping = Easytrieve.groovy :: **/*.ezt dbb.scriptMapping = TazUnitTest.groovy :: **/*.bzucfg -dbb.scriptMapping = Transfer.groovy :: **/*.jcl, **/*.xml +dbb.scriptMapping = Transfer.groovy :: **/*.jcl, **/*.xml, **/*.py dbb.scriptMapping = zCEE3.groovy :: **/openapi.yaml dbb.scriptMapping = CRB.groovy :: **/crb/*.yaml dbb.scriptMapping = zCEE2.groovy :: **/zosconnect_artefacts/apis/*.*,**/zosconnect_artefacts/services/*.*,**/zosconnect_artefacts/apiRequester/*.properties,**/zosconnect_artefacts/SAR/*.properties @@ -150,12 +150,13 @@ isIMS = true :: **/cobol/DLIBATCH.cbl # # transfer_datasetMapping = transfer_jclPDS :: **/*.jcl # transfer_datasetMapping = transfer_xmlPDS :: **/xml/*.* +# transfer_toUSS = true :: **/*.py # # file mapping for overwriting the default deployType of the Transfer.groovy language script # # transfer_deployType = JCL :: **/*.jcl # transfer_deployType = XML :: **/xml/*.* - +# transfer_deployType = PYT :: **/*.py # # Override of the default copy mode to transfer the file to the target library # Available modes are ASA_TEXT, BINARY, LOAD, and TEXT